commit abf2402fc1e1b350cfcb7c939f5736b8016f9e45 Author: zhouganqing Date: Fri Dec 16 10:44:57 2022 +0800 Import Upstream version 3.4.0 diff --git a/.github/workflows/build_gnulinux_x11.yml b/.github/workflows/build_gnulinux_x11.yml new file mode 100644 index 0000000..db2316f --- /dev/null +++ b/.github/workflows/build_gnulinux_x11.yml @@ -0,0 +1,35 @@ +name: GNU/Linux (X11) build + +on: + push: + pull_request: + workflow_dispatch: + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: install dependencies + run: | + sudo apt-get update + sudo apt-get install libgl-dev libglu1-mesa-dev libx11-dev libxrandr-dev libxi-dev + + - name: generate makefile + run: cmake -DCMAKE_BUILD_TYPE=Release . + + - name: build freeglut + run: make + + - name: stage install + run: DESTDIR=freeglut-instdir make install + + - uses: actions/upload-artifact@v3 + with: + name: freeglut-instdir + path: freeglut-instdir + +# vi:ts=2 sts=2 sw=2 expandtab: diff --git a/.github/workflows/build_macosx_x11.yml b/.github/workflows/build_macosx_x11.yml new file mode 100644 index 0000000..cdec74f --- /dev/null +++ b/.github/workflows/build_macosx_x11.yml @@ -0,0 +1,34 @@ +name: MacOS X (X11) build + +on: + push: + pull_request: + workflow_dispatch: + +jobs: + build: + + runs-on: macos-latest + + steps: + - uses: actions/checkout@v3 + + - name: install dependencies + run: | + brew install libx11 libxi libxrandr libxxf86vm pkg-config mesa + + - name: generate makefile + run: cmake -DCMAKE_BUILD_TYPE=Release -DFREEGLUT_BUILD_DEMOS=OFF -DOPENGL_gl_LIBRARY=/usr/local/lib/libGL.dylib . + + - name: build freeglut + run: make + + - name: stage install + run: DESTDIR=freeglut-instdir make install + + - uses: actions/upload-artifact@v3 + with: + name: freeglut-instdir + path: freeglut-instdir + +# vi:ts=2 sts=2 sw=2 expandtab: diff --git a/.github/workflows/build_win_msvc.yml b/.github/workflows/build_win_msvc.yml new file mode 100644 index 0000000..b588e5e --- /dev/null +++ b/.github/workflows/build_win_msvc.yml @@ -0,0 +1,35 @@ +name: Windows MSVC build + +on: + push: + pull_request: + workflow_dispatch: + +jobs: + build: + + runs-on: windows-latest + + steps: + - uses: actions/checkout@v3 + + - name: prepare environment + uses: microsoft/setup-msbuild@v1.0.2 + + - name: generate project files + run: cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_GENERATOR="Visual Studio 17 2022" -DCMAKE_INSTALL_PREFIX=freeglut-instdir . + + - name: build freeglut + run: cmake --build . --config Release + + - name: stage install + run: cmake --install . + + - uses: actions/upload-artifact@v3 + with: + name: freeglut-instdir + path: | + freeglut-instdir + bin + +# vi:ts=2 sts=2 sw=2 expandtab: diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cea288f --- /dev/null +++ b/.gitignore @@ -0,0 +1,39 @@ +Makefile.in +Makefile +INSTALL +.deps +aclocal.m4 +autom4te.cache +compile +config.guess +config.sub +configure +configure.cache +config.log +config.status +config.h +depcomp +install-sh +ltmain.sh +missing +stamp-h1 +*.tar +*.tar.gz +*.tar.bz2 +*.zip +*.o +*.a +*~ +*.swp +cross-android +cross-woe +native +*.exe +*.dll +*.a +CMakeCache.txt +CMakeFiles/ +cmake_install.cmake +freeglut.pc +freeglut.rc +FreeGLUT/ diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..7dec08f --- /dev/null +++ b/AUTHORS @@ -0,0 +1,51 @@ +Current maintainers: John F. Fay, Diederick C. Niehorster, John Tsiombikas + + +Pawel W. Olszta + the person to be blamed for freeglut + +Andreas Umbach + the first person to contribute to the freeglut project, + contributed the cube and sphere geometry code + +Steve Baker + joystick code (from his great PLIB), numerous hints + tips on the freeglut usability + and for taking the project over when Pawel bowed out + +Christopher John Purnell +Don Heyse +Dave McClurg +John F. Fay +Norman Vine +Daniel Wagner +Sven Panne + contributing to the project, using the product, and generally keeping it going + +Brian Paul +Eric Sandall + giving us the oomph! to make an official release + +James 'J.C.' Jones + designing the new website + +John Tsiombikas + mostly on the UNIX/X11 side of things. + +Sylvain Beucler + support for Android, X11/EGL, OpenGL(ES) 2.x, misc fixes + +Manuel Bachmann + support for Wayland + +Diederick C. Niehorster +Chris Marshall +Clive McCarthy +Eero Pajarre +Florian Echtler +Matti Lehtonen + +Vincent Simonetti + support for BlackBerry + +...and all the opengl-gamedev-l people that made Pawel start this project :) diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..832d867 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,672 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 3.0.0 FATAL_ERROR) +PROJECT(freeglut C) + +# for multiarch LIBDIR support (requires cmake>=2.8.8) +INCLUDE(GNUInstallDirs) + +# NOTE: On Windows and Cygwin, the dll's are placed in the +# CMAKE_RUNTIME_OUTPUT_DIRECTORY, while their corresponding import +# libraries end up in CMAKE_ARCHIVE_OUTPUT_DIRECTORY. On other +# platforms, such as Linux, the shared libraries are put in +# CMAKE_ARCHIVE_OUTPUT_DIRECTORY instead. +# Static libraries end up in CMAKE_ARCHIVE_OUTPUT_DIRECTORY on all +# platforms. +SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) +SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) +SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) + +# setup version numbers +# XXX: Update these for each release! +set(VERSION_MAJOR 3) +set(VERSION_MINOR 4) +set(VERSION_PATCH 0) +set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) + +# Update fg_version.h to match the versions number here in cmake +CONFIGURE_FILE(src/fg_version.h.in src/fg_version.h) + +# shared lib version numbers (XXX: change before release) +set(SO_MAJOR 3) # increment on backwards incompatible API/ABI changes +set(SO_MINOR 12) # increment on backwards compatible API additions +set(SO_REV 0) # increment if only internal changes happened between releases + +# FREEGLUT_BUILD_SHARED_LIBS is already a standard CMake variable, but we need to +# re-declare it here so it will show up in the GUI. +# by default, we want to build both +OPTION(FREEGLUT_BUILD_SHARED_LIBS "Build FreeGLUT shared library." ON) +OPTION(FREEGLUT_BUILD_STATIC_LIBS "Build FreeGLUT static library." ON) + +# option for whether warnings and errors should be printed +OPTION(FREEGLUT_PRINT_ERRORS "Lib prints errors to stderr" ON) +#MARK_AS_ADVANCED(FREEGLUT_PRINT_ERRORS) +OPTION(FREEGLUT_PRINT_WARNINGS "Lib prints warnings to stderr" ON) +#MARK_AS_ADVANCED(FREEGLUT_PRINT_WARNINGS) + +# option to also copy .pdb files to install directory when executing +# INSTALL target +IF(MSVC) + OPTION(INSTALL_PDB "Also install .pdb files" ON) +ELSE() + SET(INSTALL_PDB OFF) +ENDIF() + +# OpenGL ES support +IF(ANDROID) + OPTION(FREEGLUT_GLES "Use OpenGL ES (requires EGL)" ON) +ELSE() + OPTION(FREEGLUT_GLES "Use OpenGL ES (requires EGL)" OFF) +ENDIF() + +# option to build either as "glut" (ON) or "freeglut" (OFF) +IF(WIN32) + OPTION(FREEGLUT_REPLACE_GLUT "Be a replacement for GLUT" OFF) +ELSE() + OPTION(FREEGLUT_REPLACE_GLUT "Be a replacement for GLUT" ON) +ENDIF() + +IF(NOT WIN32) + # Wayland support + OPTION(FREEGLUT_WAYLAND "Use Wayland (no X11)" OFF) +ENDIF() + + +SET(FREEGLUT_HEADERS + include/GL/freeglut.h + include/GL/freeglut_ucall.h + include/GL/freeglut_ext.h + include/GL/freeglut_std.h +) +IF(FREEGLUT_REPLACE_GLUT) + LIST(APPEND FREEGLUT_HEADERS + include/GL/glut.h + ) +ENDIF() +SET(FREEGLUT_SRCS + ${FREEGLUT_HEADERS} + src/fg_callbacks.c + src/fg_cursor.c + src/fg_display.c + src/fg_ext.c + src/fg_font_data.c + src/fg_gamemode.c + src/fg_geometry.c + src/fg_gl2.c + src/fg_gl2.h + src/fg_init.c + src/fg_init.h + src/fg_internal.h + src/fg_callback_macros.h + src/fg_input_devices.c + src/fg_joystick.c + src/fg_main.c + src/fg_misc.c + src/fg_overlay.c + src/fg_spaceball.c + src/fg_state.c + src/fg_stroke_mono_roman.c + src/fg_stroke_roman.c + src/fg_structure.c + src/fg_teapot.c + src/fg_teapot_data.h + src/fg_videoresize.c + src/fg_window.c +) +# TODO: OpenGL ES requires a compatible version of these files: +IF(NOT FREEGLUT_GLES) + LIST(APPEND FREEGLUT_SRCS + src/fg_font.c + src/fg_menu.c + ) +ELSE() + LIST(APPEND FREEGLUT_SRCS + src/gles_stubs.c + ) +ENDIF() + +IF(WIN32) + LIST(APPEND FREEGLUT_SRCS + src/mswin/fg_cursor_mswin.c + src/mswin/fg_display_mswin.c + src/mswin/fg_ext_mswin.c + src/mswin/fg_gamemode_mswin.c + src/mswin/fg_init_mswin.c + src/mswin/fg_internal_mswin.h + src/mswin/fg_input_devices_mswin.c + src/mswin/fg_joystick_mswin.c + src/mswin/fg_main_mswin.c + src/mswin/fg_menu_mswin.c + src/mswin/fg_spaceball_mswin.c + src/mswin/fg_state_mswin.c + src/mswin/fg_structure_mswin.c + src/mswin/fg_window_mswin.c + src/mswin/fg_cmap_mswin.c + ${CMAKE_BINARY_DIR}/freeglut.rc # generated below from freeglut.rc.in + ) + IF (MSVC AND NOT CMAKE_CL_64) + # .def file only for 32bit Windows builds (TODO: MSVC only right + # now, needed for any other Windows platform?) + LIST(APPEND FREEGLUT_SRCS + ${CMAKE_BINARY_DIR}/freeglutdll.def # generated below from src/freeglutdll.def.in + ) + ENDIF() + +ELSEIF(ANDROID OR BLACKBERRY) + # BlackBerry and Android share some similar design concepts and ideas, as with many mobile devices. + # As such, some classes can be shared between the two. XXX: Possibly rename shareable classes to + # a more generic name. *_stub? *_mobile? + LIST(APPEND FREEGLUT_SRCS + src/android/fg_cursor_android.c + src/android/fg_ext_android.c + src/android/fg_gamemode_android.c + src/android/fg_joystick_android.c + src/android/fg_spaceball_android.c + ) + IF(ANDROID) + LIST(APPEND FREEGLUT_SRCS + src/android/native_app_glue/android_native_app_glue.c + src/android/native_app_glue/android_native_app_glue.h + src/android/fg_internal_android.h + src/android/fg_init_android.c + src/android/fg_input_devices_android.c + src/android/fg_main_android.c + src/android/fg_main_android.h + src/android/fg_runtime_android.c + src/android/fg_state_android.c + src/android/fg_structure_android.c + src/android/fg_window_android.c + ) + ELSE() + LIST(APPEND FREEGLUT_SRCS + src/blackberry/fg_internal_blackberry.h + src/blackberry/fg_init_blackberry.c + src/x11/fg_input_devices_x11.c + src/blackberry/fg_main_blackberry.c + src/blackberry/fg_state_blackberry.c + src/blackberry/fg_structure_blackberry.c + src/blackberry/fg_window_blackberry.c + ) + ENDIF() + +ELSE() + # UNIX (Wayland) + IF(FREEGLUT_WAYLAND) + LIST(APPEND FREEGLUT_SRCS + src/wayland/fg_cursor_wl.c + src/wayland/fg_ext_wl.c + src/wayland/fg_gamemode_wl.c + src/wayland/fg_init_wl.c + src/wayland/fg_internal_wl.h + src/wayland/fg_input_devices_wl.c + src/wayland/fg_main_wl.c + src/wayland/fg_state_wl.c + src/wayland/fg_structure_wl.c + src/wayland/fg_window_wl.c + # font, serial port & joystick code are agnostic + src/x11/fg_glutfont_definitions_x11.c + src/x11/fg_input_devices_x11.c + src/x11/fg_joystick_x11.c + ) + # UNIX (X11) + ELSE() + LIST(APPEND FREEGLUT_SRCS + src/x11/fg_cursor_x11.c + src/x11/fg_ext_x11.c + src/x11/fg_gamemode_x11.c + src/x11/fg_glutfont_definitions_x11.c + src/x11/fg_init_x11.c + src/x11/fg_internal_x11.h + src/x11/fg_input_devices_x11.c + src/x11/fg_joystick_x11.c + src/x11/fg_main_x11.c + src/x11/fg_menu_x11.c + src/x11/fg_spaceball_x11.c + src/x11/fg_state_x11.c + src/x11/fg_structure_x11.c + src/x11/fg_window_x11.c + src/x11/fg_xinput_x11.c + src/x11/fg_cmap_x11.c + ) + IF(NOT(FREEGLUT_GLES)) + LIST(APPEND FREEGLUT_SRCS + src/x11/fg_internal_x11_glx.h + src/x11/fg_display_x11_glx.c + src/x11/fg_state_x11_glx.c + src/x11/fg_state_x11_glx.h + src/x11/fg_window_x11_glx.c + src/x11/fg_window_x11_glx.h + ) + ENDIF() + ENDIF() +ENDIF() + +# OpenGL ES requires EGL, and so does Wayland +IF(FREEGLUT_GLES OR FREEGLUT_WAYLAND) + LIST(APPEND FREEGLUT_SRCS + src/egl/fg_internal_egl.h + src/egl/fg_display_egl.c + src/egl/fg_ext_egl.c + src/egl/fg_init_egl.c + src/egl/fg_init_egl.h + src/egl/fg_state_egl.c + src/egl/fg_state_egl.h + src/egl/fg_structure_egl.c + src/egl/fg_structure_egl.h + src/egl/fg_window_egl.c + src/egl/fg_window_egl.h + ) +ENDIF() + +INCLUDE(CheckIncludeFiles) +IF(UNIX AND NOT(ANDROID OR BLACKBERRY OR FREEGLUT_WAYLAND)) + FIND_PACKAGE(X11 REQUIRED) + INCLUDE_DIRECTORIES(${X11_X11_INCLUDE_PATH}) + LIST(APPEND LIBS ${X11_X11_LIB}) + IF(X11_Xrandr_FOUND) + SET(HAVE_X11_EXTENSIONS_XRANDR_H TRUE) + LIST(APPEND LIBS ${X11_Xrandr_LIB}) + ENDIF() + IF(X11_xf86vmode_FOUND) + SET(HAVE_X11_EXTENSIONS_XF86VMODE_H TRUE) + LIST(APPEND LIBS ${X11_Xxf86vm_LIB}) + ENDIF() + IF(X11_Xinput_FOUND) + # Needed for multi-touch: + CHECK_INCLUDE_FILES("${X11_Xinput_INCLUDE_PATH}/X11/extensions/XInput2.h" HAVE_X11_EXTENSIONS_XINPUT2_H) + LIST(APPEND LIBS ${X11_Xinput_LIB}) + ELSE() + MESSAGE(FATAL_ERROR "Missing X11's XInput2.h (X11/extensions/XInput2.h)") + ENDIF() +ENDIF() + +# FreeBSD and NetBSD joystick code uses libusbhid +IF(CMAKE_SYSTEM_NAME STREQUAL FreeBSD OR CMAKE_SYSTEM_NAME STREQUAL NetBSD) + IF(HAVE_USBHID_H) + LIST(APPEND LIBS "-lusbhid") + ENDIF() +ENDIF() + +# For OpenGL ES (GLES): compile with -DFREEGLUT_GLES to cleanly +# bootstrap headers inclusion in freeglut_std.h; this constant also +# need to be defined in client applications (e.g. through pkg-config), +# but do use GLES constants directly for all other needs +# GLES1 and GLES2 libraries are compatible and can be co-linked. +IF(FREEGLUT_GLES) + LIST(APPEND PUBLIC_DEFINITIONS -DFREEGLUT_GLES) + LIST(APPEND LIBS GLESv2 GLESv1_CM EGL) +ELSE() + # On OS X, we need to link against the X11 OpenGL libraries, NOT the Cocoa OpenGL libraries. + # To do that, you need to manually find two of the libraries before calling FindOpenGL + if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin") + # get path where X11 libs are + get_filename_component(X11_LIB_PATH ${X11_Xi_LIB} DIRECTORY) + + find_library(OPENGL_gl_LIBRARY NAME GL HINTS ${X11_LIB_PATH}) + find_library(OPENGL_glu_LIBRARY NAME GLU HINTS ${X11_LIB_PATH}) + endif() + + FIND_PACKAGE(OpenGL REQUIRED) + LIST(APPEND LIBS ${OPENGL_gl_LIBRARY}) + INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR}) +ENDIF() + +# For Wayland: compile with -DFREEGLUT_WAYLAND and pull EGL +IF(FREEGLUT_WAYLAND) + ADD_DEFINITIONS(-DFREEGLUT_WAYLAND) + LIST(APPEND LIBS wayland-client wayland-cursor wayland-egl EGL xkbcommon) +ENDIF() + +# lib m for math, not needed on windows +IF (NOT WIN32) + # For compilation: + LIST(APPEND LIBS m) + # For CHECK_FUNCTION_EXISTS: + LIST(APPEND CMAKE_REQUIRED_LIBRARIES m) +ENDIF() + +IF(WIN32) + # hide insecure CRT warnings, common practice + ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) + IF(MSVC) + SET( CMAKE_DEBUG_POSTFIX "d" ) + ENDIF(MSVC) + + IF(NOT(MSVC_VERSION LESS "1600")) + # minimum requirement for WM_TOUCH device + ADD_DEFINITIONS(-D_WIN32_WINNT=0x0601) + ADD_DEFINITIONS(-DWINVER=0x0601) + ELSEIF(NOT(MSVC_VERSION LESS "1300")) + # minimum requirement for spaceball device + ADD_DEFINITIONS(-D_WIN32_WINNT=0x0501) + ADD_DEFINITIONS(-DWINVER=0x0501) + ELSE() + # enable the use of Win2000 APIs (needed for really old compilers like MSVC6) + ADD_DEFINITIONS(-D_WIN32_WINNT=0x0500) + ADD_DEFINITIONS(-DWINVER=0x0500) + ENDIF() + +ENDIF() + +IF(CMAKE_COMPILER_IS_GNUCC) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") + IF(NOT(ANDROID OR BLACKBERRY OR FREEGLUT_WAYLAND)) + # not setting -ansi as EGL/KHR headers doesn't support it + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic") + ENDIF() +ENDIF(CMAKE_COMPILER_IS_GNUCC) + +IF(ANDROID) + # -landroid for ANativeWindow + # -llog for native Android logging + LIST(APPEND LIBS android log) +ELSEIF(BLACKBERRY) + # -lbps for event loop + # -screen for native screen + LIST(APPEND LIBS bps screen) + + if(NOT PLAYBOOK) + # -lslog2 for logging + # -pps for low-level screen manipulation + LIST(APPEND LIBS slog2 pps) + ENDIF() +ENDIF() + +INCLUDE(CheckFunctionExists) +INCLUDE(CheckTypeSize) +INCLUDE(CheckCCompilerFlag) +CHECK_INCLUDE_FILES(sys/types.h HAVE_SYS_TYPES_H) +CHECK_INCLUDE_FILES(unistd.h HAVE_UNISTD_H) +CHECK_INCLUDE_FILES(sys/time.h HAVE_SYS_TIME_H) +CHECK_INCLUDE_FILES(stdbool.h HAVE_STDBOOL_H) +CHECK_INCLUDE_FILES(sys/param.h HAVE_SYS_PARAM_H) +CHECK_INCLUDE_FILES(sys/ioctl.h HAVE_SYS_IOCTL_H) +CHECK_INCLUDE_FILES(fcntl.h HAVE_FCNTL_H) +CHECK_INCLUDE_FILES(usbhid.h HAVE_USBHID_H) +CHECK_FUNCTION_EXISTS(gettimeofday HAVE_GETTIMEOFDAY) +CHECK_FUNCTION_EXISTS(XParseGeometry HAVE_XPARSEGEOMETRY) +IF (NOT HAVE_XPARSEGEOMETRY) + LIST(APPEND FREEGLUT_SRCS + src/util/xparsegeometry_repl.c + src/util/xparsegeometry_repl.h) + SET(NEED_XPARSEGEOMETRY_IMPL TRUE) +ENDIF() +# decide on suitable type for internal time keeping, 64-bit if possible +CHECK_INCLUDE_FILES(stdint.h HAVE_STDINT_H) +CHECK_INCLUDE_FILES(inttypes.h HAVE_INTTYPES_H) +IF (NOT (HAVE_STDINT_H OR HAVE_INTTYPES_H)) + IF (MSVC) + # Some old Microsoft VC releases don't support unsigned long + # long, but all we care about is support for unsigned __int64 on + # MSVC, so test for presence of that type + CHECK_TYPE_SIZE("unsigned __int64" U__INT64 BUILTIN_TYPES_ONLY) + ELSEIF() + CHECK_TYPE_SIZE("unsigned long long" ULONG_LONG BUILTIN_TYPES_ONLY) + ENDIF() +ENDIF() + +# The generated config.h is placed in the project's build directory, just to +# ensure that all CMake-generated files are kept away from the main source tree. +# As a result, the build directory must to be added to the include path list. +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_BINARY_DIR}/config.h) +INCLUDE_DIRECTORIES(BEFORE ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/src) +ADD_DEFINITIONS(-DHAVE_CONFIG_H) +IF(WIN32) + # we also have to generate freeglut.rc, which contains the version + # number + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/freeglut.rc.in ${CMAKE_BINARY_DIR}/freeglut.rc) + IF (MSVC AND NOT CMAKE_CL_64) + # .def file only for 32bit Windows builds with Visual Studio + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/src/freeglutdll.def.in ${CMAKE_BINARY_DIR}/freeglutdll.def) + ENDIF() +ENDIF() + +IF(FREEGLUT_BUILD_SHARED_LIBS) + ADD_LIBRARY(freeglut SHARED ${FREEGLUT_SRCS}) +ENDIF() +IF(FREEGLUT_BUILD_STATIC_LIBS) + ADD_LIBRARY(freeglut_static STATIC ${FREEGLUT_SRCS}) +ENDIF() + + +SET(LIBNAME freeglut) +IF(WIN32) + IF(FREEGLUT_REPLACE_GLUT) + SET(LIBNAME glut) + ENDIF() + + LIST(APPEND LIBS winmm gdi32) + IF(FREEGLUT_BUILD_SHARED_LIBS) + TARGET_COMPILE_DEFINITIONS(freeglut PRIVATE FREEGLUT_EXPORTS) + SET_TARGET_PROPERTIES(freeglut PROPERTIES OUTPUT_NAME ${LIBNAME}) + ENDIF() + IF(FREEGLUT_BUILD_STATIC_LIBS) + TARGET_COMPILE_DEFINITIONS(freeglut_static PUBLIC FREEGLUT_STATIC) + IF(FREEGLUT_REPLACE_GLUT) + SET_TARGET_PROPERTIES(freeglut_static PROPERTIES OUTPUT_NAME ${LIBNAME}) + ENDIF() + # need to set machine:x64 for linker, at least for VC10, and + # doesn't hurt for older compilers: + # http://public.kitware.com/Bug/view.php?id=11240#c22768 + IF (CMAKE_CL_64) + SET_TARGET_PROPERTIES(freeglut_static PROPERTIES STATIC_LIBRARY_FLAGS "/machine:x64") + ENDIF() + ENDIF() +ELSE() + # on UNIX we need to make sure: + # - all shared libraries must have a soname/version, see : + # http://sourceware.org/autobook/autobook/autobook_91.html#SEC91 + # http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html + # Current: -version-info 12:0:9 -> 3.9.0 + # Note: most platforms now prefer the latter major.minor.revision form + # (e.g. FreeBSD, cf. http://debbugs.gnu.org/cgi/bugreport.cgi?bug=8765), + # or special-cased FreeGLUT long ago (e.g. .so.4 on OpenBSD), so + # the lack of support for current:revision:age in CMake should + # not be a problem. + # - the output library should be named glut so it'll be linkable with -lglut + # (unless FREEGLUT_REPLACE_GLUT is false). + # - the shared library should link to the dependency libraries so that the user + # won't have to link them explicitly (they shouldn't have to know that we depend + # on Xrandr or Xxf86vm) + IF(FREEGLUT_GLES) + SET(LIBNAME freeglut-gles) + ELSE() + IF(FREEGLUT_REPLACE_GLUT) + SET(LIBNAME glut) + ENDIF() + ENDIF() + + IF(FREEGLUT_BUILD_SHARED_LIBS) + SET_TARGET_PROPERTIES(freeglut PROPERTIES VERSION ${SO_MAJOR}.${SO_MINOR}.${SO_REV} SOVERSION ${SO_MAJOR} OUTPUT_NAME ${LIBNAME}) + ENDIF() + IF(FREEGLUT_BUILD_STATIC_LIBS) + SET_TARGET_PROPERTIES(freeglut_static PROPERTIES OUTPUT_NAME ${LIBNAME}) + ENDIF() + IF(ANDROID) + # Not in CMake toolchain file, because the toolchain + # file is called several times and generally doesn't + # seem to be meant for modifying CFLAGS: + # '-mandroid' is not mandatory but doesn't hurt + # '-O0 -gstabs+' helps the currently buggy GDB port + # Too late to manipulate ENV: SET(ENV{CFLAGS} "$ENV{CFLAGS} -mandroid") + # Not using _INIT variables, they seem to be used internally only + IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mandroid") + ENDIF() + CHECK_C_COMPILER_FLAG(-O0 HAVE_O0_FLAG) + IF(HAVE_O0_FLAG) + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0") + ENDIF() + CHECK_C_COMPILER_FLAG(-gstabs+ HAVE_GSTABSP_FLAG) + IF(HAVE_gstabsp_FLAG) + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -gstabs+") + ENDIF() + ENDIF() +ENDIF() +IF(FREEGLUT_BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(freeglut ${LIBS}) + TARGET_COMPILE_DEFINITIONS(freeglut PUBLIC ${PUBLIC_DEFINITIONS}) +ENDIF() +IF(FREEGLUT_BUILD_STATIC_LIBS) + TARGET_LINK_LIBRARIES(freeglut_static ${LIBS}) + TARGET_COMPILE_DEFINITIONS(freeglut_static PUBLIC ${PUBLIC_DEFINITIONS}) +ENDIF() + +IF(FREEGLUT_BUILD_SHARED_LIBS) + INSTALL(TARGETS freeglut EXPORT FreeGLUTTargets + RUNTIME DESTINATION bin + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + INCLUDES DESTINATION include + ) + IF(INSTALL_PDB) + IF(CMAKE_GENERATOR MATCHES "^Visual Studio" OR + CMAKE_GENERATOR MATCHES "Ninja Multi-Config") + INSTALL(FILES ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug/freeglut${CMAKE_DEBUG_POSTFIX}.pdb + DESTINATION bin + CONFIGURATIONS Debug + COMPONENT Devel) + ELSE() + INSTALL(FILES ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/freeglut${CMAKE_DEBUG_POSTFIX}.pdb + DESTINATION bin + CONFIGURATIONS Debug + COMPONENT Devel) + ENDIF() + ENDIF() +ENDIF() +IF(FREEGLUT_BUILD_STATIC_LIBS) + INSTALL(TARGETS freeglut_static EXPORT FreeGLUTTargets + RUNTIME DESTINATION bin + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + INCLUDES DESTINATION include + ) +ENDIF() +INSTALL(FILES ${FREEGLUT_HEADERS} DESTINATION include/GL COMPONENT Devel) + + + +# Optionally build demos, on by default. +option( FREEGLUT_BUILD_DEMOS "Build FreeGLUT demos." ON ) + +SET(DEMO_LIBS ${OPENGL_glu_LIBRARY} ${LIBS}) +# lib m for math, not needed on windows +IF (NOT WIN32) + LIST(APPEND DEMO_LIBS m) +ENDIF() + +MACRO(ADD_DEMO name) + IF( FREEGLUT_BUILD_DEMOS ) + IF(FREEGLUT_BUILD_SHARED_LIBS) + ADD_EXECUTABLE(${name} ${ARGN}) + TARGET_LINK_LIBRARIES(${name} ${DEMO_LIBS} freeglut) + IF(WIN32 AND MSVC) + SET_TARGET_PROPERTIES(${name} PROPERTIES DEBUG_POSTFIX d) + ENDIF() + ENDIF() + IF(FREEGLUT_BUILD_STATIC_LIBS) + ADD_EXECUTABLE(${name}_static ${ARGN}) + TARGET_LINK_LIBRARIES(${name}_static ${DEMO_LIBS} freeglut_static) + IF(WIN32 AND MSVC) + SET_TARGET_PROPERTIES(${name}_static PROPERTIES DEBUG_POSTFIX d) + ENDIF() + ENDIF() + ENDIF() +ENDMACRO() + +ADD_DEMO(CallbackMaker progs/demos/CallbackMaker/CallbackMaker.c) +ADD_DEMO(Fractals progs/demos/Fractals/fractals.c) +ADD_DEMO(Fractals_random progs/demos/Fractals_random/fractals_random.c) +ADD_DEMO(Lorenz progs/demos/Lorenz/lorenz.c) +IF (NOT WIN32) + ADD_DEMO(One progs/demos/One/one.c) +ELSE() + ADD_DEMO(One progs/demos/One/one.c + progs/demos/One/one.rc) +ENDIF() +ADD_DEMO(resizer progs/demos/resizer/resizer.c) +ADD_DEMO(multi-touch progs/demos/multi-touch/multi-touch.c) +ADD_DEMO(shapes progs/demos/shapes/shapes.c + progs/demos/shapes/glmatrix.h + progs/demos/shapes/glmatrix.c) +ADD_DEMO(smooth_opengl3 progs/demos/smooth_opengl3/smooth_opengl3.c) +ADD_DEMO(spaceball progs/demos/spaceball/spaceball.c + progs/demos/spaceball/vmath.c + progs/demos/spaceball/vmath.h) +ADD_DEMO(joystick progs/demos/joystick/joystick.c) +ADD_DEMO(subwin progs/demos/subwin/subwin.c) +ADD_DEMO(timer progs/demos/timer/timer.c) +ADD_DEMO(timer_callback progs/demos/timer_callback/timer.c) +ADD_DEMO(keyboard progs/demos/keyboard/keyboard.c) +ADD_DEMO(indexed_color progs/demos/indexed_color/idxcol.c) +ADD_DEMO(3dview progs/demos/3dview/3dview.c) + + + +# pkg-config support, to install at $(libdir)/pkgconfig +# Define static build dependencies +IF(WIN32) + SET(PC_LIBS_PRIVATE "-lopengl32 -lwinmm -lgdi32") +ELSEIF(FREEGLUT_GLES) + IF(ANDROID) + SET(PC_LIBS_PRIVATE "-llog -landroid -lGLESv2 -lGLESv1_CM -lEGL -lm") + ELSEIF(BLACKBERRY) + IF(PLAYBOOK) + SET(PC_LIBS_PRIVATE "-lbps -lscreen -lGLESv2 -lGLESv1_CM -lEGL -lm") + ELSE() + SET(PC_LIBS_PRIVATE "-lbps -lslog2 -lscreen -lGLESv2 -lGLESv1_CM -lEGL -lm") + ENDIF() + ELSEIF(FREEGLUT_WAYLAND) + SET(PC_LIBS_PRIVATE "-lwayland-client -lwayland-cursor -lwayland-egl -lGLESv2 -lGLESv1_CM -lEGL -lxkbcommon -lm") + ELSE() + SET(PC_LIBS_PRIVATE "-lX11 -lXxf86vm -lXrandr -lGLESv2 -lGLESv1_CM -lEGL -lm") + ENDIF() +ELSE() + IF(FREEGLUT_WAYLAND) + SET(PC_LIBS_PRIVATE "-lwayland-client -lwayland-cursor -lwayland-egl -lGL -lxkbcommon -lm") + ELSE() + SET(PC_LIBS_PRIVATE "-lX11 -lXxf86vm -lXrandr -lGL -lm") + ENDIF() +ENDIF() +# Client applications need to define FreeGLUT GLES version to +# bootstrap headers inclusion in freeglut_std.h: +SET(PC_LIBNAME ${LIBNAME}) +SET(PC_FILENAME "${LIBNAME}.pc") +IF(FREEGLUT_GLES) + SET(PC_CFLAGS "-DFREEGLUT_GLES") +ENDIF() +IF(FREEGLUT_BUILD_STATIC_LIBS) + LIST(APPEND PC_CFLAGS -DFREEGLUT_STATIC) +ENDIF() +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/freeglut.pc.in ${CMAKE_BINARY_DIR}/freeglut.pc @ONLY) +INSTALL(FILES ${CMAKE_BINARY_DIR}/freeglut.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig/ RENAME ${PC_FILENAME} COMPONENT Devel) +# TODO: change the library and .pc name when building for GLES, +# e.g. -lglut-GLES + +INCLUDE(CMakePackageConfigHelpers) +WRITE_BASIC_PACKAGE_VERSION_FILE( + "${CMAKE_CURRENT_BINARY_DIR}/FreeGLUT/FreeGLUTConfigVersion.cmake" + VERSION ${VERSION} + COMPATIBILITY AnyNewerVersion +) + +# needs cmake 3.0 (as does the "INCLUDES DIRECTORY" argument to install(TARGETS)): +EXPORT(EXPORT FreeGLUTTargets + FILE "${CMAKE_CURRENT_BINARY_DIR}/FreeGLUT/FreeGLUTTargets.cmake" + NAMESPACE FreeGLUT:: +) +CONFIGURE_FILE(FreeGLUTConfig.cmake.in + "${CMAKE_CURRENT_BINARY_DIR}/FreeGLUT/FreeGLUTConfig.cmake" + @ONLY +) +SET(ConfigPackageLocation ${CMAKE_INSTALL_LIBDIR}/cmake/FreeGLUT) +INSTALL(EXPORT FreeGLUTTargets + FILE FreeGLUTTargets.cmake + NAMESPACE FreeGLUT:: + DESTINATION ${ConfigPackageLocation} +) +INSTALL( + FILES + "${CMAKE_CURRENT_BINARY_DIR}/FreeGLUT/FreeGLUTConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/FreeGLUT/FreeGLUTConfigVersion.cmake" + DESTINATION ${ConfigPackageLocation} + COMPONENT Devel +) diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..fc36ad9 --- /dev/null +++ b/COPYING @@ -0,0 +1,27 @@ + + Freeglut Copyright + ------------------ + + Freeglut code without an explicit copyright is covered by the following + copyright: + + Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies or substantial portions of the Software. + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Pawel W. Olszta shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Pawel W. Olszta. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..696c97f --- /dev/null +++ b/ChangeLog @@ -0,0 +1,3888 @@ +2022-10-07 John Tsiombikas + + freeglut 3.4 changes: + + * Add GLUT_ACTIVE_SUPER modifier, and corresponding GLUT_KEY_SUPER_L + and GLUT_KEY_SUPER_R special keys. These map to Windows/Command keys. + * Fix RGB mode (GLUT_RGBA) colors on 8bpp displays on windows + (construct default RGB332 palette). + * Fix indexed color context creation on X11 and windows (GLUT_INDEX). + * Add missing colormap management functions for X11 and windows + (glutSetColor, glutGetColor). + * Fix crash when calling glutTimerFuncUcall. + * Fix FreeBSD build by essentially disabling the joystick code for + newer FreeBSD versions. It will eventually need to be replaced/fixed. + * Add fallbacks for the old GLX (<1.3) context creation API + (glXChooseVisual/glXCreateContext), makes us compatible with IRIX 5.x + and other old UNIX systems. + * Add fallbacks for OpenGL 1.0 (no vertex arrays/client state). + * Use nanosleep instead of usleep on UNIX, which is more widely + supported on old UNIX systems. + * Fix build on X11 if GL_SAMPLES is not defined. + * Fix overly strict context version checking on Android leading to + context creation failure in some cases. + * Fix GLUT_CURSOR_INFO on windows, should be IDC_HAND, not IDC_HELP. + * Fix mismatched font declarations on X11. + * Add alternative simple ways to build freeglut with native tools only, + without having to use cmake. + * Fix build on windows with cmake 3.0.0. Explicitly link with gdi32. + * Fix build on MSVC 2005. + * Fix build on MacOS X. Link with all the necessary X libraries. + * Fix build on SGI IRIX. + * Fix build on Android (mismatched function prototypes and missing + glutCreateMenuUcall). + * Add support for the ninja multi-config generator. + * Removed spurious dependency on a C++ compiler. One of the demos was + being compiled as C++ for no reason. + * Silence unnecessary warnings when VBOs or GLSL are not available. + * New demo programs: 3dview, keyboard, joystick. + * Documentation: added MacOS X build instructions. + * Made it possible to eventually support building freeglut as a single + compilation unit, by avoiding name conflicts on static variables. + * Other minor fixes. + +2022-02-06 John Tsiombikas + + freeglut 3.2.2 changes: + + * Fix netbsd/aarch64 build by including sys/joystick.h instead of + machine/joystick.h. + * Fix build with gcc >= 10 which made -fno-common the default by no + longer relying on COMMON symbols for globals. + * Fix android build (default to FREEGLUT_GLES, and check for debug + flags). + * Add flat shading option to the shapes demo. + * Fix crash when calling primitive drawing functions without creating a + window first. + * Dropped really old and unmaintained doc directory from the source + tree. + +2019-09-29 John Tsiombikas + + freeglut 3.2.1 changes: + + * Fixed failure to install glut.h when the "replace glut" build option + is enabled. + * Take into account CMAKE_INSTALL_LIBDIR in the installed cmake module. + * Fixed broken menu drawing when the user requests a core profile + context. + +2019-09-16 John Tsiombikas + + freeglut 3.2.0 changes: + + * Added new callback registration functions and corresponding callback + types in the extended API, which take an extra user pointer, and pass + it through to the callbacks (ucall API). + * Added initial wayland support. + * Fixed mousewheel callbacks on X11. + * Fallback to non-sRGB context, instead of crashing, if the user + requested SRGB but failed to get one. + * Added GLUT_WINDOW_SRGB query to check if the context supports sRGB or + the fallback was triggered. + * Added missing spaceball support for windows. + * Fixed crash on re-init after having set a custom cursor. + * Added init error handler demo. + * Added cmake package. + * Added GLUT_ALLOW_NEGATIVE_WINDOW_POSITION option. + * Fixed incorrect library name in pkg-config files when building with + "replace glut" option disabled. + * Added spaceball button definitions in the extended API header. + * Added the "replace glut" option on windows too. + * Fixed missing static defines from pkg-config. + * Fixed incorrectly trying to install glut.h when the "replace glut" + option is disabled. + * Take "maximized" state into account when updating the visibility flag + on windows. + * Corrected "exit state" checking in the main loop, by placing the check + after every glutMainLoopEvent invocation. + * Added checking for the XInput dependency in cmake. + * Fixed netbsd build (joystick code). + * Fixed -pedantic GCC warnings on GNU/Linux. + * Fixed PDB installation for nmake/msvc builds on windows. + * Clear window work mask when marking it for destruction. + * Fixed android build with clang. + * Fixed GLUT_STEREO on nvidia windows drivers, which don't play well + with fullscreen windows with frames. + * Fixed original-GLUT compatibility in spaceball button numbering. + * Dropped unnecessary X11 utility library dependencies. + * Fixed namespace pollution due to some global symbols missing the fg + prefix. + * Fixed improper setting of the non-blocking flag in the joystick code + on UNIX. + +2012-01-09 John F. Fay + * Released freeglut 2.8.0 a few days ago and am restarting the ChangeLog + * Added 'cmake' support + * Moved source files from 'src' directory to 'src/Common' directory with + an eye to moving platform-specific code to separate files in separate + directories + +2009-08-10 Sven Panne + + * include/GL/freeglut_ext.h,include/GL/freeglut_std.h,src/freeglut_ext.c, + src/freeglut_init.c,src/freeglut_internal.h,src/freeglut_state.c, + src/freeglut_window.c,src/freeglutdll.def: Added support for sRGB + framebuffers via the GLX_ARB_framebuffer_sRGB / WGL_ARB_framebuffer_sRGB + extensions. Added support for context profiles via the new parts of the + GLX_ARB_create_context / WGL_ARB_create_context extensions. + +2009-06-11 Paul Blew + + * replaced broken IDE based OpenWatcom build with a makefile based one + +2009-06-11 Sven Panne + + * include/GL/freeglut_std.h: Disable the ATEXIT_HACK for Watcom, their + "exit" function has a different calling convention, leading to + compilation errors. + +2009-05-24 Sven Panne + + * freeglut_static_vs2008.vcproj,freeglut_vs2008.vcproj, + freeglut_vs2008.sln,freeglut_vs2008_static.sln: Move all files related + to Visual Studio 2008 into 2 directories, one for the normal DLL + build, and one for the static build. We should do this for other IDEs, + too. + +2009-05-22 Sven Panne + + * include/GL/freeglut_std.h: Avoid warnings when the ATEXIT_HACK is used + with GCC, making the hack even uglier. + + * include/GL/freeglut_std.h,src/freeglut_init.c,src/freeglut_internal.h, + src/freeglut_menu.c,src/freeglut_window.c,src/freeglutdll.def: Added the + ugly ATEXIT_HACK from GLUT 3.7, making freeglut binary compatible with the + GLUT DLLs out in the wild. + + * src/freeglutdll.def: Removed obsolete lines. Fixed version number. + + * freeglut_vs2008.vcproj: Use our module definition file, so we get + undecorated names in the resulting DLL, just like the classic GLUT DLL + from Nate Robins. + +2009-04-05 Sven Panne + + * Makefile.am: Added more project/workspace/... files to distribution. + * .cvsignore,doc/.cvsignore,include/.cvsignore,include/GL/.cvsignore, + progs/.cvsignore,progs/demos/.cvsignore, + progs/demos/CallbackMaker/.cvsignore,progs/demos/Fractals/.cvsignore, + progs/demos/Fractals_random/.cvsignore,progs/demos/Lorenz/.cvsignore, + progs/demos/One/.cvsignore,progs/demos/shapes/.cvsignore, + src/.cvsignore: Removed remnants of CVS. + +2009-03-30 Sven Panne + + * progs/demos/smooth_opengl3/smooth_opengl3.c: Make the example fully + OpenGL-3.1-compliant. + +2009-03-27 Sven Panne + + * progs/demos/smooth_opengl3/smooth_opengl3.c: Make Visual C happy by + including stddef.h and explicitly marking some literals as float. + +2009-03-26 Sven Panne + + * src/freeglut_init.c,src/freeglut_input_devices.c: Unbreak the build: + C++ style comments are not allowed in ISO C90 + +2009-03-19 John F. Fay + + * src/freeglut_input_devices.c: Fixing "freeglut_input_devices.c" for + MSVS2005 and later per e-mail from Diederick Niehorster dated Thu + 3/19/2009 6:57 AM + +2009-03-17 John F. Fay + + * src/freeglut_init.c, src/freeglut_input_devices.c: Removing some build + warnings from deprecated functions for VS2008 per e-mail from + Diederick Niehorster dated Tue 3/10/2009 + * freeglut_static_vs2008.vcproj, freeglut_vs2008.sln, + freeglut_vs2008.vcproj, + progs/demos/CallbackMaker/CallbackMakerStatic_vs2008.vcproj, + progs/demos/CallbackMaker/CallbackMaker_vs2008.vcproj, + progs/demos/Fractals/FractalsStatic_vs2008.vcproj, + progs/demos/Fractals/Fractals_vs2008.vcproj, + progs/demos/Fractals_random/Fractals_randomStatic_vs2008.vcproj, + progs/demos/Fractals_random/Fractals_random_vs2008.vcproj, + progs/demos/Lorenz/lorenzStatic_vs2008.vcproj, + progs/demos/Lorenz/lorenz_vs2008.vcproj, + progs/demos/One/oneStatic_vs2008.vcproj, + progs/demos/One/one_vs2008.vcproj, progs/demos/demos_vs2008.sln, + progs/demos/shapes/shapesStatic_vs2008.vcproj, + progs/demos/shapes/shapes_vs2008.vcproj, + progs/demos/smooth_opengl3/smooth_opengl3Static_vs2008.vcproj, + progs/demos/smooth_opengl3/smooth_opengl3_vs2008.vcproj: Adding Visual + Studio 2008 solution and project files + +2009-03-16 Sven Panne + + * src/freeglut_init.c,src/freeglut_window.c: Set the default number of + samples per pixel to 4 and actually use the value set with + glutSetOption(GLUT_MULTISAMPLE,...) in Windows code. Previously the + Windows code used a hardwired value of 4 and the GLX code had a + default of 0, neither made much sense. Similarly, set the default + number of auxiliary buffers to 1 and use that value when GLUT_AUX is + used. Note: There latter token has the same value as GLUT_AUX1, and + for historical reasons we seem to have 2 APIs to set the number of + auxiliary buffers: Explicitly using GLUT_AUX1 ... GLUT_AUX4, and using + a combination of GLUT_AUX with glutSetOption. The default of 1 ensures + consistent behaviour in both cases. + * src/freeglut_state.c: Added GLUT_AUX and GLUT_MULTISAMPLE as possible + parameters for glutGet, making things more symmetric with + glutSetOption. + * src/freeglutdll.def: Added missing API entries. + +2009-03-10 John F. Fay + + * progs/demos/demos.dsw: Adding the "smooth_opengl3" demo + +2009-03-09 John F. Fay + + * include/GL/freeglut_std.h: Making the definition of + "WIN32_LEAN_AND_MEAN" conditional to enhance compatibility with GLEW + per suggestion by Diederick C. Niehorster in e-mail dated Mon 3/9/2009 + 8:06 AM + * progs/demos/Fractals/fractals.c: Setting the "fractals" demo initial + number of levels to 4 per suggestion from Diederick C. Niehorster + [diederick@niehorster.eu] in e-mail dated Mon 3/9/2009 5:29 AM + +2009-03-01 John F. Fay + + * progs/demos/CallbackMaker/CallbackMaker.c, + progs/demos/Lorenz/lorenz.c, progs/demos/shapes/shapes.c: Fixing + Microsoft compatibility with the new "vsnprintf" by putting an + underscore in front of it if WIN32 is defined but __CYGWIN__ is not + +2009-03-01 Sven Panne + + * configure.ac: We do not depend on GLU anymore + * README.win32: Added notes for building under Cygwin + * src/Makefile.am: To build shared libraries on Windows, one has to + declare explicitly that there are no undefined symbols during linking. + No idea why, but this seems to be the only way to enable this on + Cygwin via -mno-cygwin. Hopefully this won't cause problems on other + platforms (which has to be tested). + * progs/demos/smooth_opengl3/smooth_opengl3.c: Windows fun again: Use + the correct calling convention for OpenGL extension entries. + +2009-02-28 Sven Panne + + * progs/demos/smooth_opengl3/smooth_opengl3.c: When -mno-cygwin is used, + we get ancient GL headers, so be a bit more conservative. + * progs/demos/Fractals_random/fractals_random.c, + progs/demos/Lorenz/lorenz.c, progs/demos/shapes/shapes.c: + _CrtDumpMemoryLeaks and its header are Microsoft-specific, e.g. Cygwin + doesn't provide them. + * src/freeglut_window.c: Do not try to destroy a GLX context when there + is none, e.g. when glXCreateContextAttribsARB is not there. + * src/freeglut_joystick.c: Use snprintf or _snprintf instead of the + potentially dangerous sprintf to avoid warnings. + + NOTE: Due to excessive use of #ifdefs, the joystick code is on the + border of being unmaintainable! I could only check that it compiles + cleanly on my Linux box. Others should test this on their platforms + (Windows, Mac OS X, *BSD) to make sure that nothing has been broken. + * progs/demos/CallbackMaker/CallbackMaker.c, + progs/demos/Lorenz/lorenz.c, progs/demos/shapes/shapes.c: Use + vsnprintf instead of the potentially dangerous sprintf to avoid + warnings. Using snprintf directly would be a little bit more tricky, + because once again Microsoft decided to avoid followind standards and + provide _snprintf instead. We could use this, too, but this would + require an additional autoconf check, which I'd like to avoid, if + possible. + + Note: If VS *still* issues warnings, but this time about vsnprintf, + somebody should add some pragmas or whatever is needed to shut up that + warning, it would be silly. + * progs/demos/Lorenz/lorenz.c: Position the distance message closer to + the middle of the window, it has been far, far off to the upper right. + * src/freeglut_internal.h: Synched version number with configure.ac. We + should better remove this redundancy and calculate this from + configure.ac directly. + +2009-02-19 John F. Fay + + * progs/demos/smooth_opengl3/smooth_opengl3.dsp, + progs/demos/smooth_opengl3/smooth_opengl3Static.dsp: Fixing the + DOS/Linux line ending problems in the progs/demos/smooth_opengl3 + project files + +2009-02-18 John F. Fay + + * src/freeglut_window.c: Fixing a build error caused by a variable + declaration being out of place + +2009-02-15 Sven Panne + + * progs/demos/smooth_opengl3/smooth_opengl3.c: Final changes to make the + example fully OpenGL-3.0-compliant: + + * Use vertex attribute arrays. + + * Use our own projection matrix. + + * Do not use deprecated vertex/fragment shader variables. + * progs/demos/smooth_opengl3/smooth_opengl3.c: Use GLSL shaders (still + 1.20, though). Dump GL info. + * progs/demos/smooth_opengl3/smooth_opengl3.c: Added a commandline + option for 'classic' contexts. Aesthetic changes. + * progs/demos/smooth_opengl3/smooth_opengl3.c: Use VBOs in new example. + Added a few comments. + +2009-02-14 Sven Panne + + * configure.ac, progs/demos/Makefile.am, progs/demos/smooth_opengl3, + progs/demos/smooth_opengl3/Makefile.am, + progs/demos/smooth_opengl3/smooth_opengl3.c, + progs/demos/smooth_opengl3/smooth_opengl3.dsp, + progs/demos/smooth_opengl3/smooth_opengl3Static.dsp: Initial version + of a fully OpenGL-3.0-compliant of the famous smooth.c from the Red + Book. What has been done already: + + * Explicitly request a forward-compatible 3.0 context + + * Report GL errors, if any, at a few crucial places + + * Replaced gluOrtho2D with a home-grown matrix + glLoadMatrixf + + What remains to be done: + + * Use vertex shaders and fragment shaders + + * Use vertex buffer objects + +2009-02-13 Sven Panne + + * README: Mention autogen.sh + * src/freeglut_window.c: Synchronized WGL behavior with GLX + implementation: Do not call the new context creation API when it is + not required. Fixing a bug in a previous commit on the way... :-} + * src/freeglut_internal.h, src/freeglut_window.c: More refactorings: + Removed useless return value. Simplified control structures even more. + * src/freeglut_window.c: Refactoring only (replace nested conditionals + with guard clauses), making the normal path of execution much clearer. + * configure.ac: We have added some API entries, so we have to update + library version information conforming to + http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html + * autogen.sh, configure.ac: Avoid CR\LF vs. LF troubles when using + TortoiseSVN plus Cygwin. + * .: Ignore config.lt, too. It seems to be generated by recent + autotools. + +2009-02-13 John F. Fay + + * src/freeglut_internal.h, src/freeglut_main.c, src/freeglut_window.c: + Adding OpenGL 3.0 context detection for Windows per e-mail from Paul + Martz dated Thu 2/12/2009 9:03 AM (more or less) + +2009-02-03 John F. Fay + + * README: Adding some instructions about building on a *nix platform to + the 'README' file + * include/GL/freeglut_ext.h, src/freeglut_main.c: Removing some errant + tabs, fixing ticket #2137721, and adding special-key capability to + recognizing the NumLock, Delete, and keypad '5' keys + * src/freeglut_joystick.c, src/freeglut_main.c: A further response to + bug [ 1804696 ] Warnings when building on OpenSolaris -- per comment + by Nigel Stewart on that bug report + +2009-02-02 John F. Fay + + * src/freeglut_internal.h, src/freeglut_joystick.c: Fixing bug [ 1804696 + ] Warnings when building on OpenSolaris as updated 2/2/09 by Nigel + Stewart + +2008-11-20 Sven Panne + + * src/freeglut_glutfont_definitions.c, src/freeglut_internal.h: Yet + another try to make the font definitions compile on all platforms. + +2008-11-17 John F. Fay + + * src/freeglut_glutfont_definitions.c, src/freeglut_internal.h: Allowing + "freeglut" to compile without errors under *nix. Before this, there + were problems with conflicting definitions of the GLUT font + definitions. + +2008-11-06 Sven Panne + + * src/freeglut_main.c: Ooops, forgot one file in the previous commit + (fix for "--without-x"). + * configure.ac: Use autoconf to detect gettimeofday instead of broken + #ifdef. + + Note: freeglut compiles under Cygwin now, even when "--without-x" is + used for configuration. + * configure.ac: We need to link against winmm under Cygwin when + --without-x is used to get timeBeginPeriod, timeEndPeriod, joyGetPosEx + and joyGetDevCaps. + * src/freeglut_window.c: Fixed first parameter of CreateWindow call, + used for multisampling on Windows. It compiles, but it is otherwise + untested. + +2008-11-05 Sven Panne + + * src/freeglut_misc.c: Be conservative about the presence of + GL_TABLE_TOO_LARGE. + * src/freeglut_glutfont_definitions.c, src/freeglut_stroke_mono_roman.c, + src/freeglut_stroke_roman.c: freeglut_internal.h needs some GL types, + but it is not self-contained. TODO: Move freeglut.h #include into + freeglut_internal.h itself? + * src/freeglut_window.c: Removed the annoying "Unable to create direct + context rendering..." warning, it served no real purpose, and on some + platforms there simply is no such thing as a direct context. + * progs/demos/CallbackMaker, progs/demos/Fractals, + progs/demos/Fractals_random, progs/demos/Lorenz, progs/demos/One, + progs/demos/shapes: Ignore *.exe + * src/freeglut_ext.c: Handle new glutInitContext* API entries in + glutGetProcAddress + * src/freeglut_internal.h: Make freeglut compile under Cygwin, which has + an ancient GLX header + +2008-11-02 Sven Panne + + * include/GL/freeglut_ext.h, src/freeglut_init.c, + src/freeglut_internal.h, src/freeglut_state.c, src/freeglut_window.c: + Added OpenGL 3.0 context creation API entries + + glutInitContextVersion, glutInitContextFlags + + and their related constants + + GLUT_INIT_MAJOR_VERSION GLUT_INIT_MINOR_VERSION GLUT_INIT_FLAGS + + GLUT_DEBUG GLUT_FORWARD_COMPATIBLE + + Note that this works with GLX only currently, the glutInitContext* API + entries have no effect for WGL yet. + + TODO: Centralize the context creation code for WGL (the harder part) + and use the new wglCreateContextAttribsARB API entry (the easy part, + re-use most of the GLX code). + * src/freeglut_window.c: Refactored GLX context creation into a single + function, centralizing things to be changed for OpenGL 3.0 context + creation and removing some cut-n-paste. + * src/freeglut_ext.c, src/freeglut_internal.h: Make a + wgl/glXGetProcAddress abstraction available internally. We will need + this to get the new context creation function. + * src/freeglut_misc.c: Do not depend on GLU, it will vanish in the + future, at least in its current form. + * src/freeglut_internal.h: Removed superfluous #includes. + * configure.ac: Fix for bug #1709675 ("probably not be so + ISO-conformant"): The C compiler flag -Werror is not used by default + anymore, a separate configure flag --enable-warnings-as-errors has + been introduced for this purpose, which is off by default. + * configure.ac: Added AM_PROG_CC_C_O to configure.ac, removing a warning + during autogen.sh. This flag seems to be necessary for per-target + flags (used in demo programs) nowadays. + +2008-07-21 John F. Fay + + * configure.ac, src/Makefile.am: Implementing a patch from Jocelyn + Frechot (thank you, Jocelyn) that "should enable the XInput extension + management with the autotools." See e-mail of Sun 7/20/2008 12:01 PM. + +2008-07-10 John F. Fay + + * src/freeglut_ext.c: Adding "glutExit" to the functions in + "fghGetProcAddress" in accordance with an e-mail from Jocelyn Frechot + dated Tue 7/8/2008 12:26 PM + +2008-04-05 John F. Fay + + * src/freeglut_main.c: Adding "SC_MONITORPOWER" and other new options to + the "wParam" option list (e-mail from Ron Larkin, 3/17/08, 11:00 AM) + +2007-12-02 John F. Fay + + * include/GL/freeglut_ext.h, src/freeglut_display.c, src/freeglut_ext.c, + src/freeglut_init.c, src/freeglut_internal.h, src/freeglut_main.c, + src/freeglut_state.c, src/freeglut_window.c: Adding + "glutFullScreenToggle" for X11 -- still needs implementation in + Windows (e-mail by Jocelyn Frechot, Sun 11/25/2007 11:29 AM) + +2007-12-01 John F. Fay + + * src/freeglut_window.c: Fixing the window position for asynchronous X11 + implementations (e-mail by Jocelyn Frechot, Sun 11/25/2007 11:29 AM) + +2007-11-26 John F. Fay + + * progs/demos/Fractals/fractals.c: Making a demo program that uses + "glutMainLoopEvent" + +2007-11-12 John F. Fay + + * include/GL/freeglut_ext.h, src/freeglut_ext.c, src/freeglut_init.c, + src/freeglut_internal.h, src/freeglut_state.c, + src/freeglut_structure.c, src/freeglut_window.c: Implementing Jocelyn + Frechot's changes -- see e-mail of Thursday, 11/8/2007 9:12 AM. + +2007-10-02 John F. Fay + + * src/freeglut_joystick.c: Removing more Win64 build warnings from + joystick code + +2007-09-30 John F. Fay + + * src/freeglut_main.c: Removing the final compiler warning when building + on Win75 -- thank you, Antonio Mattos. + +2007-09-29 John F. Fay + + * src/freeglut_cursor.c: Removing the remaining compiler warnings from + the cursor code, thanks to Antonio Mattos of Brazil. The double + type-casting is needed because of a bug in the new MSVC; there is a + discussion on the web on this subject. + +2007-09-25 John F. Fay + + * src/freeglut_cursor.c: Changing the cursor definition macro for newer + versions of MSVC -- thanks to "Mattos" of Brazil + * src/freeglut_window.c: More changes for Jocelyn Frechot's + multisampling changes. The library builds now. It still needs some + testing with sample cases under X11. + +2007-09-23 John F. Fay + + * src/freeglut_window.c: Fixing a remaining bug in the multisampling + change ... there may be more ... + +2007-09-22 John F. Fay + + * src/freeglut_internal.h, src/freeglut_state.c, + src/freeglut_structure.c, src/freeglut_window.c: Putting in Jocelyn + Frechot's X11 visual context changes. THIS WILL BREAK THE BUILD as I + am unable to test it on a Linux machine here. Somebody please test it + for me. + +2007-09-21 John F. Fay + + * src/freeglut_init.c, src/freeglut_main.c, src/freeglut_misc.c: + Removing compiler warnings in MSVC 2005 build + * include/GL/freeglut_ext.h, src/freeglut_init.c: Implementing Larry + Ramey's "glutExit" feature (see e-mails from him on 11/9/05, 6/28/06) + +2007-09-19 John F. Fay + + * include/GL/freeglut_std.h, src/freeglut_window.c: Implementing first + part of Windows version of "GLUT_CAPTIONLESS" and "GLUT_BORDERLESS" + per feature request "[ 1197016 ] need GLUT_CAPTIONLESS window option". + Needs more work; menus are slightly mispositioned, X11 version does + not support it, banner appears at beginning but disappears on window + resize. But this is a start. + * src/freeglut_main.c: Fixing Linux key-repeat mode bug reported in "[ + 1796845 ] Keyboard events are lost when key repeat is enabled." + * src/freeglut_joystick.c: Fixing a build error on SuSE described in bug + report "[ 1792047 ] freeglut_joystick.c error" + +2007-09-18 John F. Fay + + * src/freeglut_window.c: Implementing feature request "[ 947118 ] Popup + menu is hidden under the TOPMOST window" + * src/freeglut_menu.c: Adding Takeshi Nishimura's Feature Request "[ + 1045202 ] Cope with a menu with many items" -- sorry it took so long. + * src/freeglut_window.c: Addressing Feature Request #1307049 that + "freeglut" should return 0 if "glutGetWindow" is called without a + prior call to "glutInit", rather than terminating on error. + * freeglut.dep, freeglut.mak, freeglut_static.dep, freeglut_static.mak: + Added Windows "nmake" Makefiles and dependency files for the two + "freeglut" projects in accordance with Feature Request #1454543 + +2007-09-16 John F. Fay + + * src/freeglut_window.c: Fixing bug #1688954, submitted in Marcy '07. I + changed "FREEGLUT" to _T("FREEGLUT") and nothing changed on my Windows + XP system. If this will allow it to work on Vista, then in it goes. + * src/freeglut_gamemode.c, src/freeglut_internal.h, src/freeglut_main.c, + src/freeglut_state.c, src/freeglut_structure.c, src/freeglut_window.c: + Fixing bug report #1052151 from October 2004. + +2006-11-28 John F. Fay + + * FrequentlyAskedQuestions: Adding a Frequently Asked Questions file + +2006-09-28 Joe Krahn + + * src/freeglut_state.c, src/freeglut_window.c: Removed incorrect comment + about internal WGL/ARB definitions. I actually had put those comments + in because I had meant to go back and re-check the WGL extension. But, + maybe locally defined extensions should be kept in a separate include + file? + +2006-09-27 Joe Krahn + + * freeglut.dsp, freeglut.dsw, freeglut_static.dsp, + progs/demos/CallbackMaker/CallbackMaker.dsp, + progs/demos/CallbackMaker/CallbackMakerStatic.dsp, + progs/demos/Fractals/Fractals.dsp, + progs/demos/Fractals/FractalsStatic.dsp, + progs/demos/Fractals_random/Fractals_random.dsp, + progs/demos/Fractals_random/Fractals_randomStatic.dsp, + progs/demos/Lorenz/lorenz.dsp, progs/demos/Lorenz/lorenzStatic.dsp, + progs/demos/One/one.dsp, progs/demos/One/oneStatic.dsp, + progs/demos/demos.dsw, progs/demos/shapes/shapes.dsp, + progs/demos/shapes/shapesStatic.dsp: Undo svn:eol-style=CR/LF for MSVC + project files. + +2006-09-26 Joe Krahn + + * include/GL/freeglut_std.h, src/freeglut_joystick.c, + src/freeglut_state.c, src/freeglut_window.c: Added + FREEGLUT_LIB_PRAGMAS to control MS library pragmas, and fixed NOMINMAX + define. + * freeglut.dsp, freeglut.dsw, freeglut_static.dsp, + progs/demos/CallbackMaker/CallbackMaker.dsp, + progs/demos/CallbackMaker/CallbackMakerStatic.dsp, + progs/demos/Fractals/Fractals.dsp, + progs/demos/Fractals/FractalsStatic.dsp, + progs/demos/Fractals_random/Fractals_random.dsp, + progs/demos/Fractals_random/Fractals_randomStatic.dsp, + progs/demos/Lorenz/lorenz.dsp, progs/demos/Lorenz/lorenzStatic.dsp, + progs/demos/One/one.dsp, progs/demos/One/oneStatic.dsp, + progs/demos/demos.dsw, progs/demos/shapes/shapes.dsp, + progs/demos/shapes/shapesStatic.dsp: Added svn:eol-style=CRLF property + to MSVC project/workspace files. + +2006-09-25 John F. Fay + + * src/freeglut_window.c: Fixing a typo bug in the display mode checking + (removing multisampling if it is not supported) + +2006-09-25 Joe Krahn + + * src/freeglut_state.c: Fixed a small mistake in the previous commit for + glutGet. + * src/freeglut_state.c: Added proper support for number of mouse buttons + in X11, and a keyboard in Windows CE. Also, several glutGet results + returning TRUE/FALSE were changed to 1/0, because the actual return + type is int (although they are technically the same in practice). + +2006-09-24 Joe Krahn + + * src/freeglut_init.c, src/freeglut_internal.h, src/freeglut_main.c: + Converted Time counter to a uniform unsigned long it value. The + initialized flag was redundant with the main Initialized flag, and + conversion of timeval to milliseconds in POSIX makes the code cleaner. + Timeval has a longer range, but the time value is already limited by + the GLUT API. + +2006-09-23 Joe Krahn + + * src/freeglut_gamemode.c, src/freeglut_internal.h, src/freeglut_main.c: + Removed WindowState.IsGameMode; it is redundant with + Structure.GameModeWindow + +2006-09-21 John F. Fay + + * src/freeglut_state.c, src/freeglut_window.c: Adding support for the + multisampling query per bug report 1274193 + * ChangeLog, src/freeglut_main.c: Fixing Bug #1398196 - Windows message + argument + +2006-09-21 Joe Krahn + + * src/freeglut_cursor.c: test (comment edited) + +2006-09-21 John F. Fay + + * ChangeLog, src/freeglut_init.c: Adding temporary fix to + "glutInitDisplayString" to ignore numerical assignments + * ChangeLog, src/freeglut_window.c: Adding multisampling to *nix and + Windows; also some other pixel format enhancements to Windows + * ChangeLog, progs/demos/CallbackMaker/CallbackMaker.c: Enhancing the + "CallbackMaker" demo + * ChangeLog, src/freeglut_cursor.c, src/freeglut_display.c, + src/freeglut_ext.c, src/freeglut_gamemode.c, + src/freeglut_glutfont_definitions.c, src/freeglut_init.c, + src/freeglut_input_devices.c, src/freeglut_internal.h, + src/freeglut_joystick.c, src/freeglut_main.c, src/freeglut_menu.c, + src/freeglut_misc.c, src/freeglut_state.c, src/freeglut_teapot.c, + src/freeglut_teapot_data.h, src/freeglut_window.c: Joe Krahn's changes + to "TARGET_HOST" defined constants + * ChangeLog, src/freeglut_internal.h, src/freeglut_joystick.c, + src/freeglut_main.c, src/freeglut_window.c: Fixing two minor bugs, + adding comments + * ChangeLog, src/freeglut_gamemode.c, src/freeglut_internal.h, + src/freeglut_menu.c, src/freeglut_state.c, src/freeglut_structure.c: + Changing "GameMode" to "GameModeWindow ... and testing whether I can + get to SVN directly + +2006-08-05 Sven Panne + + * ChangeLog, progs/demos/Fractals/fractals.c, + progs/demos/Fractals_random/fractals_random.c, + progs/demos/Lorenz/lorenz.c: Check fgets for return value to avoid + warnings. + * freeglut.spec: Fixed typo in date + * freeglut.spec: Updated build requirements for SuSE 10.1 + +2005-10-12 Sven Panne + + * ., .cvsignore: Ooops, forgot to ingore INSTALL and install-sh in + previous commit... + * ChangeLog, include/GL/freeglut_ext.h, include/GL/freeglut_std.h: Moved + GLUT_INIT_STATE to , it is not part of the original + GLUT. + * ., .cvsignore, ChangeLog, INSTALL, autogen.sh, install-sh, + mkinstalldirs: Simply use autoreconf in autogen.sh, it is much simpler + and the recommended way in the autotools documentation. Removed + INSTALL, install-sh and mkinstalldirs, they are either unused or + automatically generated by autogen.sh. + +2005-10-06 John F. Fay + + * include/GL/freeglut_ext.h: Allowing compilation of Windows version by + removing DLL decorations from deprecated joystick interface extensions + * src/freeglut_window.c: Implementing Stereo in Windows + +2005-09-07 Sven Panne + + * ChangeLog, src/Makefile.am: Use target-specific *_CPPFLAGS, not the + deprecated INCLUDES. + * ChangeLog, autogen.sh: Use -Wall for automake to catch some buglets, + deprecated stuff, etc. + +2005-09-04 Sven Panne + + * ChangeLog, autogen.sh: Silenced autogen.sh + +2005-08-31 John F. Fay + + * freeglut.rc, freeglut.tgt, freeglut.wpj, freeglut_static.tgt: + Necessary files for Open Watcom support + * src/freeglut_internal.h: Adding Open Watcom support + * ChangeLog, README.win32: Documenting support for Open Watcom + * include/GL/freeglut_std.h: Implementing WATCOM support + +2005-07-14 Sven Panne + + * src/freeglut_input_devices.c: Nuked useless bit-fiddling, pointed out + by John. I was a bit too quick to cut-n-paste the cfmakeraw() + definition into our code... :-] + * ChangeLog, src/freeglutdll.def: Synched the DLL definitions with + reality. + * ChangeLog, src/freeglut_cursor.c: Fixed the GLUT_CURSOR_INHERIT logic + once again... + + Note that this commit is untested, but at least it looks better than + before. We really a need a cursor test program. + +2005-07-13 John F. Fay + + * src/freeglut_cursor.c: Fixing a cursor bug in \"GLUT_CURSOR_INHERIT\" + +2005-07-13 Sven Panne + + * ChangeLog, configure.ac: Improve autoconf magic: To detect headers + like GL/gl.h, it might be necessary to temporarily use the X11 flags + found by AC_PATH_XTRA. + * ChangeLog, src/freeglut_joystick.c: Avoid gcc warnings for some + joystick code (e.g. on Solaris). + * src/freeglut_input_devices.c: Tiny cleanup only... + * ChangeLog, src/freeglut_input_devices.c: Solaris doesn't have + cfmakeraw, but it is only a convenience function for some + bit-fiddling, anyway. + +2005-07-08 Sven Panne + + * ChangeLog, include/GL/freeglut_ext.h, src/freeglut_ext.c, + src/freeglut_internal.h: Made all the "glutJoystickXXX" functions part + of the freeglut extensions. If this is not what we want, we can easily + #ifdef this away again... + * ChangeLog, src/freeglut_geometry.c: Made a few global arrays "static", + avoiding namespace pollution. The only externally visible symbols + should either be from the GLUT API ("glutXXX") or internal freeglut + entities ("fgYYY"). Reformatted things a bit on the way. + +2005-07-06 Sven Panne + + * ChangeLog, src/freeglut_main.c: We only have pending redisplay + callbacks when the window wants to be redisplayed *and* it is visible. + Otherwise we won't redraw, anyway, and immediately discover that + there's still something to do, etc. etc., leading to 100% CPU load. + * ChangeLog, src/freeglut_main.c: Removed redundant code. + * ChangeLog, src/freeglut_init.c: X11 only: Destroy the global menu + rendering context when deinitializing. The visual/context handling for + menus is still rather obscure, though... + * progs/demos/Lorenz/lorenz.c: Reverting previous commit: %lf is a valid + format specifier for the scanf familiy of functions only, not for the + printf family. + +2005-07-05 John F. Fay + + * src/freeglut_main.c: Implementing the new menu context variable names + in Windows ... + * src/freeglut_internal.h: Changing a comment ... nothing big. + * progs/demos/Lorenz/lorenz.c: Fixing output formats ... nothing big + +2005-07-05 Sven Panne + + * ChangeLog, src/freeglut_state.c, src/freeglut_window.c: X11 only: Free + XVisualInfo structures when they are not needed anymore, fixing a + space leak. Not perfect for menus yet... + * src/freeglut_internal.h, src/freeglut_window.c: Tiny change to make + grep's life easier: Rename the fields of the menu context. Not really + worth a ChangeLog entry... + + IMHO it looks like we could kill the whole MenuContext stuff, it is of + no use currently and some things look strange, like e.g. having a + context per menu. The latter is not OK when a menu is attached to + multiple windows. + +2005-07-02 Sven Panne + + * ChangeLog, src/freeglut_init.c, src/freeglut_internal.h, + src/freeglut_main.c, src/freeglut_state.c: Handle modifiers in + MotionNotify events, too. This fixes bug #1227920 (glutGetModifiers + not set/allowed in mouse callbacks). In addition, some related cleanup + has been done. + * ChangeLog, src/freeglut_joystick.c: Partial fixes for bug #1218900 + (freeglut-2.4.0 on FreeBSD). + * ChangeLog, Makefile.am: Remove wrong "execute" bits when creating a + distribution. This fixes bug #961938 (Executable bit set on non exe + files). + * configure.ac: Tiny cosmetic change, not worth a ChangeLog entry. + * ChangeLog: Added John's missing ChangeLog entry. + +2005-07-01 John F. Fay + + * freeglut.dsp, freeglut_static.dsp: Adding the + \"freeglut_input_devices.c\" file to the Windows project files + +2005-07-01 Sven Panne + + * ChangeLog, configure.ac, src/Makefile.am: Some steps toward + compilation under MinGW. Note that there are still linking troubles + for the examples. + * src/freeglut_internal.h: Fixed #ifdef for ChangeDisplaySettingsEx + prototype. + * ChangeLog, src/freeglut_input_devices.c: Silenced a signed/unsigned + mismatched via a cast. + * ChangeLog, src/freeglut_internal.h: MinGW is lacking a prototype for + ChangeDisplaySettingsEx, so supply one in this case. Note that this + should better be handled via autoconf than via cpp. + * ChangeLog, Makefile.am: Removed redundant files from EXTRA_DIST. + +2005-06-30 Sven Panne + + * src/freeglut_main.c: Ooops, forgot to set the current window in the + last commit. I'll have to test better before committing... :-] + * ChangeLog, src/freeglut_main.c: When a window is iconified, only an + UnmapNotify is sent, not a VisibilityNotify, so we have to handle the + window status callback in the former case, too. This fixes bug #763442 + (Call the visibility callback when minimizing a window). + * ChangeLog, src/freeglut_main.c: Cleaned up + CreateNotify/ConfigureNotify handling. + * src/freeglut_main.c: Ooops, forgot to dump a few fields in some + events... + * ChangeLog, configure.ac, src/freeglut_main.c: Added --enable-debug + configure flag. Currently it only turns on X11 event tracing, but in + the future we could add more. + + Note: freeglut_main.c could benefit from some restructuring to clean + up the #ifdefs and cut down the sizes of some extremely long + functions. + * ., .cvsignore: Ignore files generated during RPM build. + +2005-06-23 John F. Fay + + * doc/freeglut_user_interface.html: Fixing the documentation regarding + callbacks and geometry shape additions + * progs/demos/Fractals/Fractals.dsp, + progs/demos/Fractals/FractalsStatic.dsp, + progs/demos/Fractals_random/Fractals_random.dsp, + progs/demos/Fractals_random/Fractals_randomStatic.dsp, + progs/demos/Lorenz/lorenz.dsp, progs/demos/Lorenz/lorenzStatic.dsp, + progs/demos/One/one.dsp, progs/demos/One/oneStatic.dsp, + progs/demos/shapes/shapes.dsp, progs/demos/shapes/shapesStatic.dsp: + Adding separate static library and DLL demonstration program projects + * progs/demos/CallbackMaker/CallbackMaker.dsp, + progs/demos/CallbackMaker/CallbackMakerStatic.dsp: Adding separate + demo program projects for static library and DLL versions + * progs/demos/demos.dsw: Adding support for separate static library demo + programs + * ChangeLog: Keeping current ... + * src/freeglut_input_devices.c: New file for Joe Krahn\'s dials input + device + +2005-06-22 John F. Fay + + * src/freeglut_geometry.c: Fixing a bug in the Sierpinski sponge code + that made the application crash if called with number of levels < 0 + * src/Makefile.am, src/freeglut_init.c, src/freeglut_internal.h, + src/freeglut_joystick.c, src/freeglut_state.c: Joe Krahn\'s input + (dials) device implementation. + +2005-06-14 Sven Panne + + * ChangeLog, freeglut.spec: Added an RPM spec file based on the one + shipped with SuSE 9.3. + +2005-06-10 James Jones + + * ChangeLog, configure.ac: Release of 2.4.0 + +2005-06-02 James Jones + + * ChangeLog, configure.ac, src/freeglut_internal.h: 2.4.0 Release + Candidate 5 + +2005-05-26 John F. Fay + + * src/freeglut_main.c: Takeshi Nishimura\'s changes to make the Windows + mouse wheel/button mapping match that of X11; also fixing a typo in + the associated mouse callback argument list + +2005-05-26 James Jones + + * ChangeLog, configure.ac: 2.4.0 RC4 updates + * src/freeglut_main.c: Fix joysticks so they are polled by their timer + correctly. (Dan Torop) + +2005-05-24 Sven Panne + + * ChangeLog, src/freeglut_gamemode.c: The original glutEnterGameMode() + returns the window id of the game mode window, not TRUE/FALSE, we + should better follow that. Note that most man pages claim that this + function returns void, but this is definitely wrong. + * ChangeLog, src/freeglut_gamemode.c, src/freeglut_main.c: When + switching to game mode under X11, no ConfigureNotify event will happen + and consequently no reshape callback will ever be called via the + normal mechanism. To fix this, note that the game mode window needs to + be resized and handle this before redraw. + +2005-05-22 Sven Panne + + * ChangeLog, src/freeglut_ext.c: Guarantee consistency of + names/addresses in glutGetProcAddress by using a macro. In addition, + this avoids any non-constant initializer issues which might be raised + when using WinDoze GCCs. The additional code overhead is negligible, + at least for x86 (a few instructions per name). + * ChangeLog, configure.ac: Lowering minimum autoconf version required. + +2005-05-20 James Jones + + * ChangeLog: Tag for 2.4.0 RC3 + * ChangeLog: Notes + +2005-05-19 Sven Panne + + * src/freeglut_gamemode.c: Fixed SF bug #1204256: Off-by-one error in + X11 mode switching. The code which changes the X11 video mode has an + off-by-one error, resulting in a wrong mode or segfault. I've + refactored the code slightly to make it hopefully clearer what's going + on and corrected some #ifdefs on the way. Now at least the "One" demo + works for me. + * src/freeglut_window.c: Fixed SF bug #1204261: Mini space leak when + creating an X11 window (X11 text property values have to be freed + after using them) + +2005-05-18 John F. Fay + + * src/freeglut_gamemode.c: Removing a C++ comment and simplifying the + string handling + +2005-05-17 John F. Fay + + * src/freeglut_gamemode.c: Misiek\'s changes to fix Game Mode--getting + display settings under Windows and setting the window size correctly + on all operating systems. + +2005-05-16 James Jones + + * ChangeLog: Mark for 2.4 RC 2 + +2005-05-13 John F. Fay + + * src/freeglut_menu.c: Removing two unused variables so this will + compile on Linux with -Wall + +2005-05-12 John F. Fay + + * ChangeLog: Updating the ChangeLog ... + * src/freeglut_internal.h, src/freeglut_main.c, src/freeglut_menu.c: + Takeshi Nishimura\'s menu changes--menus should now work properly. Use + the GLUT \"GLUTmech\" and \"walker\" demos to test them. + * src/freeglut_main.c: Takeshi Nishimura\'s menu fixes + +2005-05-09 James Jones + + * ChangeLog, Makefile.am, configure.ac: Freeglut 2.4.0 Release Candidate + 1 + +2005-05-06 Sven Panne + + * ChangeLog, progs/demos/shapes/shapes.c: Fixed a cuboctahedron vertex, + implemented wire mode for that shape. + * ChangeLog, progs/demos/shapes/shapes.c, src/freeglut_internal.h, + src/freeglut_main.c: Necessary compilation fixes for newer GCCs (e.g. + 3.3.5, 4.0). Side effect: The shapes demo has a new 'i' key now. + +2005-05-05 John F. Fay + + * ChangeLog: Updated the ChangeLog again ... + +2005-05-04 John F. Fay + + * progs/demos/shapes/shapes.c: Replacing the original \"freeglut\" + \"shapes\" demo with the much snazzier OpenGLUT \"shapes\" demo. Many + thanks to the OpenGLUT community for writing it. The copyright notice + stays in the program. + * src/freeglut_main.c: Changing hard-coded constant (number of mouse + buttons = 3) to a \"glutDeviceGet\" call in two places under X11 + * src/freeglutdll.def: Changing the version number from 2.0 to 2.4.0 ... + do we need to add any new interface functions? + * src/freeglut_internal.h: Removing an unused variable + * src/freeglut_window.c: Adding a comment on why \"freeglut\" differs + from GLUT in a particular way + * src/freeglut_joystick.c: Removing an unused function + * src/freeglut_init.c: Making the \"key repeat\" initialization + consistent with the rest of its usage; also making the + \"initDisplayString\" ever-so-slightly more general + * ChangeLog, TODO, src/freeglut_window.c: Updating the ChangeLog and + TODO files in preparation for the upcoming release + +2005-04-29 John F. Fay + + * src/freeglut_joystick.c: Adding a \"TODO\" comment about dynamically + allocating joystick buttonj and axis arrays + * ChangeLog: Updationg the ChangeLog ... + +2005-04-28 John F. Fay + + * README.win32: Adding a \"README.Win32\" file with instructions on how + to install \"freeglut\" under Windows. + * src/freeglut_main.c: Adding Window Exit event handling to the Windows + code; also adding a note that eventually it would be good to handle + the Window Entry event + +2005-04-27 John F. Fay + + * src/freeglut_window.c: Fixing bug [ 1111218 ] fullscreen not working + Better late than never. + * src/freeglut_init.c: Fixing Bug Report [ 1160442 ] + glutGet(GLUT_ELAPSED_TIME) is too granular + +2005-04-26 John F. Fay + + * src/freeglut_internal.h, src/freeglut_structure.c: Fixing the + typecasts on the callback fetches and invocations to allow + \"freeglut\" to compile with GCC 4.0 + * src/freeglut_menu.c: Fixing erroneous implementation of Takeshi\'s fix + * src/Makefile.am: Changing include path from relative to absolute to + support off-directory builds (Yuri D\'Elia, March 22, 5:59 PM) + * LISEZ_MOI: Adding \"LISEZ-MOI\", the French version of \"README\" + +2005-04-25 John F. Fay + + * ChangeLog: Updating the ChangeLog ... it seems to be something of a + stepchild if we\'re not careful. + +2005-04-22 John F. Fay + + * src/freeglut_menu.c: Yuri D\'Elia\'s changes to get the virtual + maximum screen extent instead of the actual screen size. + * src/freeglut_gamemode.c: Yuri D\'Elia\'s changes to the game mode + window + * src/freeglut_structure.c: Change a hard-coded number to a defined + constant and add some initializations + * src/freeglut_cursor.c: Removing duplicate cursor code. This and the + previous change (in freeglut_main.c) apparently got combined. + * ChangeLog: Updating the ChangeLog to reflect activity over the past + few months + * src/freeglut_callbacks.c, src/freeglut_cursor.c, + src/freeglut_display.c, src/freeglut_gamemode.c, + src/freeglut_internal.h, src/freeglut_main.c, src/freeglut_menu.c, + src/freeglut_misc.c, src/freeglut_state.c, src/freeglut_structure.c, + src/freeglut_window.c: Trying again to change \"fgStructure.Window\" + to \"fgStructure.CurrentWindow\" and \"fgStructure.Menu\" to + \"fgStructure.CurrentMenu\" for easier maintenance. + +2005-04-15 John F. Fay + + * ChangeLog: Updating the ChangeLog as a means of testing pCVSc + * src/freeglut_internal.h: Testing! + +2005-03-23 Brian Paul + + * include/GL/freeglut_ext.h: added comment about AUX flags + +2005-02-16 Brian Paul + + * src/freeglut_internal.h, src/freeglut_main.c, src/freeglut_menu.c, + src/freeglut_structure.c, src/freeglut_window.c: fixes for menus being + attached to multiple buttons/windows (John Fay) + * src/freeglut_callbacks.c: added error check (John Fay) + +2005-02-15 Brian Paul + + * src/freeglut_init.c, src/freeglut_window.c: AUX buffers for Windows + (John Fay) + +2005-02-11 Brian Paul + + * include/GL/freeglut_ext.h, src/freeglut_init.c, src/freeglut_window.c: + Aux color buffer support. Pass one of GLUT_AUX[1234] to + glutInitDisplayMode. Only implemented/tested on GLX, not Windows. + * include/GL/freeglut_ext.h, src/freeglut_ext.c, + src/freeglut_internal.h: Fix object/function pointer inconsistencies + which are a problem for gcc 3.4.2. Added GLUTproc type, returned by + glutGetProcAddress(). + +2005-01-23 Sven Panne + + * configure.ac: autoconf 2.58 is enough + * src/freeglut_callbacks.c, src/freeglut_internal.h: Stylistic change + only (added "do { ... } while( 0 )" around multi-statement macros) + * configure.ac, src/freeglut_joystick.c, src/freeglut_main.c: Testing + for errno.h is overkill. :-) + * src/freeglut_cursor.c, src/freeglut_main.c: Windows platforms only: + Merged some cursor-related code from John Fay (with minor changes) + +2005-01-05 Sven Panne + + * src/freeglut_ext.c, src/freeglut_font.c, src/freeglut_main.c, + src/freeglut_state.c, src/freeglut_window.c: Hopefully removed all + damage done by commits without merge + * ChangeLog, src/freeglut_cursor.c: Reworked the X11 part of + glutSetCursor, fixing bug #764187 (Variable mouse pointers don't work) + on the way: * Use slightly more compatible cursor shapes for + GLUT_CURSOR_RIGHT_ARROW and GLUT_CURSOR_LEFT_ARROW. * Refactored and + fixed the erroneous code for GLUT_CURSOR_NONE. * Removed the incorrect + use of XFreeCursor and use a cache of cursors instead. Cursors are + never freed now, we could do this e.g. via reference countig if this + is really needed. * Fixed error handling. * Unknown cursor types are + an error now. * Now the window state always corresponds to the wanted + cursorID, even in the case of GLUT_CURSOR_FULL_CROSSHAIR. + + NOTE: I am not sure where the cursor cache should really reside, + currently it is simply a file-local variable. + +2005-01-03 Sven Panne + + * ChangeLog, src/freeglut_gamemode.c: Fixed part of bug #926883 (Video + mode matching code, memory leaks, fullscreen), i.e. issue warnings + when XF86VidModeFOO fails. + * ChangeLog, src/freeglut_gamemode.c: (234) Fixed part of bug #926883 + (Video mode matching code, memory leaks, fullscreen): Now we first try + to get an exact mode match, ignoring the refresh rate if none could be + found. This way the X11 part and the WinDoze behave similarly. NOTE: + We still don't behave like GLUT, because it has a wider notion of + "best" match. We have to refactor and extend freeglut quite a bit to + do that. + * ChangeLog, src/freeglut_gamemode.c: Fixed part of bug #926883 (Video + mode matching code, memory leaks, fullscreen), i.e. memory leak caused + by not freeing the mode lines returned by XF86VidModeGetAllModeLines + * ChangeLog, src/freeglut_window.c: Improved error message a bit when no + suitable visual could be found (X11 only). + * configure.ac, src/freeglut_internal.h, src/freeglut_main.c: autoconf'd + vfprintf + * src/freeglut_joystick.c: Removed redundant #include + * ChangeLog, configure.ac, src/freeglut_joystick.c, src/freeglut_main.c: + autoconf'd handling and removed an unused '#include + ' + * configure.ac, src/freeglut_joystick.c, src/freeglut_main.c: autoconf'd + and handling, removing MIN/MAX macros on the + way. + * src/freeglut_internal.h: Cosmetics. + * configure.ac, src/freeglut_joystick.c: autoconf'd and + handling + * src/freeglut_internal.h, src/freeglut_joystick.c, src/freeglut_main.c: + Improved / handling as suggested by the + autoconf docs. + * configure.ac, progs/demos/Lorenz/lorenz.c, src/freeglut_internal.h, + src/freeglut_main.c: Fixed / handling as + suggested by the autoconf docs. + * src/freeglut_callbacks.c, src/freeglut_cursor.c, + src/freeglut_display.c, src/freeglut_ext.c, src/freeglut_font.c, + src/freeglut_font_data.c, src/freeglut_gamemode.c, + src/freeglut_geometry.c, src/freeglut_init.c, src/freeglut_internal.h, + src/freeglut_joystick.c, src/freeglut_main.c, src/freeglut_menu.c, + src/freeglut_misc.c, src/freeglut_overlay.c, src/freeglut_state.c, + src/freeglut_structure.c, src/freeglut_teapot.c, + src/freeglut_videoresize.c, src/freeglut_window.c: Moved '#include + "config.h"' to freeglut_internal.h, we will need it there soon and it + makes everything a bit shorter. + * ChangeLog: Resurrected my recent additions which were nuked by the + previous commit, adding the latest change on the way. :-( + * acconfig.h: Removed acconfig.h, it is deprecated and we don't need it. + * src/freeglut_cursor.c, src/freeglut_font.c, src/freeglut_init.c, + src/freeglut_structure.c: Make it compile again with "-Wall -pedantic + -Werror", redoing quite a few things I've fixed already a few days + ago. Have today's commits been done by copying instead of merging? :-( + +2005-01-03 James Jones + + * src/freeglut_internal.h, src/freeglut_main.c, src/freeglut_menu.c, + src/freeglut_window.c: Changes remove duplicate menu code from + "freeglut_window.c" and put it into one place in "freeglut_menu.c" + where it belongs. - John Fay + * ChangeLog: General ChangeLog Updates + * src/freeglut_callbacks.c, src/freeglut_cursor.c, + src/freeglut_display.c, src/freeglut_ext.c, src/freeglut_font.c, + src/freeglut_gamemode.c, src/freeglut_geometry.c, src/freeglut_init.c, + src/freeglut_internal.h, src/freeglut_joystick.c, src/freeglut_main.c, + src/freeglut_menu.c, src/freeglut_misc.c, src/freeglut_state.c, + src/freeglut_structure.c, src/freeglut_teapot.c, + src/freeglut_teapot_data.h, src/freeglut_window.c: Adding + initialization checking to all GLUT interface functions and removing + asserts from the rest of the code - John Fay + +2005-01-01 Sven Panne + + * ChangeLog, src/Makefile.am: Added missing files from "src" + subdirectory to dist. + * AUTHORS: Synched with project member list on SourceForge + * ChangeLog, Makefile.am, configure.ac: Modernized configure.ac a bit + and added a rule to Makefile.am to update libtool. Note that all gcc + compiler warnings are now on by default. + * ChangeLog, include/GL/freeglut_std.h, + progs/demos/CallbackMaker/CallbackMaker.c, + progs/demos/Fractals_random/fractals_random.c, + progs/demos/Lorenz/lorenz.c, progs/demos/One/one.c, + src/freeglut_cursor.c, src/freeglut_font.c, src/freeglut_init.c, + src/freeglut_teapot_data.h: Make "gcc -Wall -pedantic -Werror" happy. + * ., .cvsignore: Ignore files generated by autoscan. + * ChangeLog, INSTALL, configure.ac, configure.in: Renamed "configure.in" + to the officially preferred "configure.ac". + * stamp-h, stamp-h.in: Removed unused stamp-h* files, configure + generates them (a single stamp-h1, to be exact). + * ChangeLog, Makefile.am: Added eMbedded Visual Tools project/workspace + files to distribution. + * ., .cvsignore: Ignore distribution tar files + +2004-12-31 Sven Panne + + * ChangeLog, src/freeglut_main.c: Fixed first bug of #1064195 (two + things when using signals): Don't issue a warning about select when a + non-blocked signal was caught. This makes sense and is more compatible + with GLUT. + * ChangeLog, src/freeglut_font.c: Fixed bug #1040435 (glutBitmapString() + bug). + * ChangeLog: Alas, the ChangeLog has not the usual ChangeLog format, so + tell (X)Emacs about that fact. + * ChangeLog, src/freeglut_window.c: Fixed bug #1045054 (KeyReleaseMask + typo). + * ChangeLog, src/freeglut_state.c: Fixed bug #1087642 + (glutDeviceGet(GLUT_DEVICE_KEY_REPEAT) unimplemented). + * ChangeLog, src/freeglut_ext.c: Fixed bug #1079530 (glutGetProcAddress + and geometric objects). + * ., .cvsignore, doc, doc/.cvsignore, include, include/.cvsignore, + include/GL, include/GL/.cvsignore, progs, progs/.cvsignore, + progs/demos, progs/demos/.cvsignore, progs/demos/CallbackMaker, + progs/demos/CallbackMaker/.cvsignore, progs/demos/Fractals, + progs/demos/Fractals/.cvsignore, progs/demos/Fractals_random, + progs/demos/Fractals_random/.cvsignore, progs/demos/Lorenz, + progs/demos/Lorenz/.cvsignore, progs/demos/One, + progs/demos/One/.cvsignore, progs/demos/shapes, + progs/demos/shapes/.cvsignore, src, src/.cvsignore: Improved + ignorance. + +2004-12-17 James Jones + + * src/freeglut_cursor.c, src/freeglut_display.c, + src/freeglut_internal.h, src/freeglut_menu.c, src/freeglut_misc.c, + src/freeglut_window.c: Some assertion changes / removals from Dr. John + Fay + +2004-10-06 Brian Paul + + * src/freeglut_callbacks.c, src/freeglut_internal.h, + src/freeglut_joystick.c, src/freeglut_state.c: joystick init fixes + (John Fay) + +2004-10-05 Brian Paul + + * src/freeglut_main.c: updated comments (John Fay) + * src/freeglut_init.c, src/freeglut_main.c, src/freeglut_window.c: + improved comments and mouse coord adjustments (John Fay) + * src/freeglut_init.c: more clean-ups, fixes from John Fay + +2004-09-23 Brian Paul + + * src/freeglut_font.c, src/freeglut_stroke_mono_roman.c, + src/freeglut_stroke_roman.c: font updates from John Fay + * src/freeglut_main.c: more updates from John Fay + * src/freeglut_geometry.c, src/freeglut_init.c: assorted updates from + John Fay + +2004-09-15 James Jones + + * src/freeglut_init.c: Fix to glutInit() command-line argument + compaction - Patch #1027724 from takeshi2 + +2004-09-13 Brian Paul + + * src/freeglut_callbacks.c, src/freeglut_cursor.c, + src/freeglut_gamemode.c, src/freeglut_init.c, src/freeglut_internal.h, + src/freeglut_joystick.c, src/freeglut_main.c, src/freeglut_state.c, + src/freeglut_window.c: more updates from John Fay + * src/freeglut_cursor.c, src/freeglut_gamemode.c, + src/freeglut_geometry.c, src/freeglut_init.c, src/freeglut_internal.h, + src/freeglut_joystick.c, src/freeglut_main.c, + src/freeglut_structure.c, src/freeglut_teapot.c, + src/freeglut_window.c: some function renaming, etc (John Fay) + +2004-09-10 Brian Paul + + * src/freeglut_callbacks.c, src/freeglut_init.c, + src/freeglut_internal.h, src/freeglut_main.c: joystick updates from + John Fay + * src/freeglut_cursor.c, src/freeglut_font_data.c, + src/freeglut_gamemode.c, src/freeglut_geometry.c, src/freeglut_init.c, + src/freeglut_internal.h, src/freeglut_joystick.c, src/freeglut_main.c, + src/freeglut_menu.c, src/freeglut_misc.c, src/freeglut_state.c, + src/freeglut_stroke_mono_roman.c, src/freeglut_stroke_roman.c, + src/freeglut_structure.c, src/freeglut_teapot.c, + src/freeglut_window.c: updated comments from John Fay + +2004-08-11 James Jones + + * src/freeglut_gamemode.c, src/freeglut_internal.h, src/freeglut_main.c: + Fix a game mode crashing bug, conditional compilation for Windows, and + comment out some diagnostic prints (John Fay) + +2004-08-05 James Jones + + * src/freeglut_window.c: Implements Richard Rauch's request that the + warning about indirect rendering contexts be suppressed for his BSD + operating systems. + * src/freeglut_teapot_data.h: Someone used C++ style comments in a C + file... tisk tisk... + * src/freeglut_font.c: Bugfix for "glutBitmapString" so that it now + handles end-of-line characters properly (Richard Rauch) + * README: Incremental update ... (John Fay) + +2004-06-29 Brian Paul + + * src/freeglut_structure.c: give menu windows the title 'freeglut menu' + (helps Chromium) + * src/freeglut_window.c: move glXMakeCurrent() to after the point where + the window's title is set (helps Chromium) + +2004-05-13 James Jones + + * freeglut.dsp, freeglut_static.dsp: Add one more header file to MSVC + files + +2004-05-12 James Jones + + * include/GL/freeglut_ext.h, include/GL/freeglut_std.h: John Fay: + Direct/indirect rendering context change, fix a bug that somebody + reported (about needing "GLUT_XLIB_IMPLEMENTATION" defined) and remove + a false deprecation of a function. + * src/freeglut_main.c: John Fay: A bug fix re: behavior of the code when + the user clicks the "x" to close a window, and commentary to a message + type with fixes for a Windows event processing bug. + * src/freeglut_init.c, src/freeglut_internal.h, src/freeglut_state.c, + src/freeglut_window.c: John Fay: Implement the modified logic of the + direct/indirect rendering context. + * src/freeglut_font.c, src/freeglut_font_data.c: John Fay: Implement the + upper end of the bitmapped fonts (beyond ASCII code 127). The fonts + are very close to the GLUT fonts. + * src/freeglut_teapot.c, src/freeglut_teapot_data.h: John Fay: These + files implement the teapot for WINCE. + * src/freeglut_internal.h: John Fay: Remove some obsolete defined + symbols. + * freeglut.dsp, freeglut_static.dsp: John Fay: Add + "freeglut_glutfont_definitions.c" to the build and tell it to look in + the "include" directory for the file. + +2004-03-28 Steve Baker + + * progs/demos/shapes/shapes.c: Removed unnecessary initialisation. + * progs/demos/shapes/shapes.c: Added a cullface test. + +2004-03-22 drgoldie + + * freeglut_evc4.vcp, src/freeglut_gx.cpp, src/freeglut_init.c, + src/freeglut_main.c: removed .cpp file (using LoadLibrary() instead) + removed modified gx.h file cleaned up all // and tabs + +2004-03-17 nigels + + * src/freeglut_main.c: Prevent exceeding array bounds in X11 key-repeat + detection + +2004-03-16 drgoldie + + * freeglut_evc4.vcp, src/freeglut_ext.c, src/freeglut_gx.cpp, + src/freeglut_init.c, src/freeglut_main.c, src/freeglut_misc.c, + src/freeglut_state.c, src/freeglut_window.c: replaced all tabs with 4 + spaces replaced all // with /* */ block fixed freeglut_gx.cpp file + with #if TARGET_HOST_WINCE + +2004-03-16 nigels + + * src/freeglut_init.c, src/freeglut_main.c, src/freeglut_state.c: + Whitespace conversion - tabs to 4 spaces + * src/freeglut_window.c: Revert X11 fgCloseWindow to 1.38 pre-offscreen + implementation. + +2004-03-15 drgoldie + + * freeglut_evc4.vcp, src/freeglut_gx.cpp, src/freeglut_main.c: fixed + mouse position and keyboard mapping. added c-wrapper cpp file for + GAPI. + * freeglut_evc4.vcp, freeglut_evc4.vcw, include/GL/freeglut_std.h, + src/freeglut_cursor.c, src/freeglut_display.c, src/freeglut_ext.c, + src/freeglut_gamemode.c, src/freeglut_init.c, src/freeglut_internal.h, + src/freeglut_main.c, src/freeglut_menu.c, src/freeglut_misc.c, + src/freeglut_state.c, src/freeglut_window.c: added support for + WindowsCE (building on top of klimt) + +2004-03-15 nigels + + * src/freeglut_main.c: Repeat-key handling for Win32 Utilise both + FreeGLUT state and per-window filtering modes + +2004-03-15 rkrolib + + * ChangeLog: Forgot to update the ChangeLog for the benefit of those who + do not have CVS or Web access. + * configure.in, include/GL/freeglut_ext.h, src/freeglut_internal.h, + src/freeglut_window.c: Completed removal of all support for the + offscreen rendering. + + If you wish to do offscreen supportin a portable manner, you will no + longer be able to do so with current versions of freeglut. + * progs/demos/Makefile.am: Removed Makefile support for the offscreen + demo. + * progs/demos/One/one.c, progs/demos/offscreen: Removed offscreen demo + program. + +2004-03-15 nigels + + * src/Makefile.am: Provide local include path to automake for + GL/freeglut.h etc + +2004-03-14 nigels + + * src/freeglut_window.c: Code formatting tweak + * src/freeglut_init.c, src/freeglut_internal.h, src/freeglut_main.c, + src/freeglut_misc.c, src/freeglut_state.c, src/freeglut_structure.c: + Resolution of X11 key-repeat handling + + glutSetKeyRepeat is global to all FreeGLUT windows in the application + glutIgnoreKeyRepeat is a per-window over-ride + + To avoid nasty global X11 state interaction, or GLUT-style event queue + filtering - the approach in FreeGLUT is to use the current key state + XQueryKeymap to detect and ignore KeyRelease/KeyPress pairs that are + auto-generated. + + See also: + http://pyopengl.sourceforge.net/documentation/manual/glutSetKeyRepeat.3GLUT.xml + http://pyopengl.sourceforge.net/documentation/manual/glutIgnoreKeyRepeat.3GLUT.xml + * src/freeglut_callbacks.c, src/freeglut_cursor.c, src/freeglut_ext.c, + src/freeglut_font.c, src/freeglut_font_data.c, + src/freeglut_gamemode.c, src/freeglut_geometry.c, + src/freeglut_glutfont_definitions.c, src/freeglut_init.c, + src/freeglut_internal.h, src/freeglut_joystick.c, src/freeglut_main.c, + src/freeglut_state.c, src/freeglut_structure.c, src/freeglut_window.c: + Stripped out tabs and end-of-line whitespace Differences are in + whitespace only + +2004-03-10 nigels + + * src/freeglut_window.c: Resolve [ 853044 ] FreeGLUT menus on Win32 in + task bar and ALT-TAB list CreateWindowEx(WS_EX_TOOLWINDOW,...) + extended style suppresses the popup menu window from the taskbar or + ALT-TAB list + +2004-03-08 nigels + + * src/freeglut_init.c: ignoreKeyRepeat mode in FreeGLUT is TRUE by + default For compatibility with GLUT, the mode should be FALSE by + default This issues was probably undetected until now because + ignoreKeyRepeat didn't yet work. + * src/freeglut_main.c: Resolved bug #869765 glutIgnoreKeyRepeat() Fix + (Win32) glutIgnoreKeyRepeat now behaves correctly on Win32 + * src/freeglut_internal.h: C++ style comment converted to C style + comment + * src/freeglut_callbacks.c, src/freeglut_cursor.c, + src/freeglut_display.c, src/freeglut_ext.c, src/freeglut_font.c, + src/freeglut_font_data.c, src/freeglut_gamemode.c, + src/freeglut_geometry.c, src/freeglut_init.c, src/freeglut_joystick.c, + src/freeglut_main.c, src/freeglut_menu.c, src/freeglut_misc.c, + src/freeglut_overlay.c, src/freeglut_state.c, + src/freeglut_structure.c, src/freeglut_teapot.c, + src/freeglut_videoresize.c, src/freeglut_window.c: Include freeglut + header via rather than "../include/GL/freeglut.h" This + allows some additional flexibility with file layout. It should be the + responsibility of the build environment, rather than at source level. + This change tested on MSVC 6, cygwin and mingw32 gcc and Linux gcc. + +2004-03-03 nigels + + * src/freeglut_joystick.c: According to John F. Fay: The variable + "num_axes" should be "joy->num_axes". + +2004-02-20 rkrolib + + * src/freeglut_gamemode.c: Removed nonstandard #warning constructs. + Converted to XXX comments. (These are warnings about gamemode features + not working the same on some systems as on others. The semantics of + gamemode are dubious, since it was never formally documented, and has + for a long time worked in different ways on different systems, so it + is arguable that there is nothing really wrong with systems that don't + support resolution-changes.) + * src/freeglut_callbacks.c: Fixed the bug where glutDisplayFunc() was + effectively invoking glutPostRedsiplay(). This is wrong on the face of + it, and may be at root for some of the annoying "timing" issues we've + had with redisplay events being called inappropriately. + +2004-02-19 rkrolib + + * progs/demos/offscreen/Makefile.am: I had rubbed the + offscreen/Makefile.am off from the shapes demo. I forgot to remove a + couple of references to the shapes.c and shapes.dsp (.dsw?) files. + * configure.in, include/GL/freeglut_ext.h, progs/demos/Makefile.am, + progs/demos/offscreen, progs/demos/offscreen/Makefile.am, + progs/demos/offscreen/offscreen.c: Added "offscreen" demo, a very + simple program that produces an onscreen window and, upon command, + renders a similar offscreen display and writes the result to disk. + + Also, modified the build structure for UNIX_X11 to autobuild the demo. + (Not done for WIN32 at this time.) + + Also, forgot to previously commit the updated freeglut_ext.h include. + Eeep. + +2004-02-18 rkrolib + + * src/freeglut_window.c: Minor comment adjustments. + +2004-02-18 nigels + + * src/freeglut_geometry.c: Refinements to comments + +2004-02-14 rkrolib + + * src/freeglut_joystick.c: Normalized the style of the new joystick a + bit. + * src/freeglut_main.c: For some reason, the X "expose" event handler was + *directly* calling the display handler in the client. (Okay, it was + calling a function that operates on the window handle.) + + If you have any complexity to the display code, this can be painful to + watch. I can't think of a good reason to do the display immediately, + so I fixed the code to do a glutPostRedisplay(). + * src/freeglut_joystick.c: A commit on behalf of John (in turn, and in + part, also on behalf of Thierry). + + * Renamed some of the old PLIB functions to have glut* prefixes. (I + guess that there is some thought about exporting them to the API.) + + * Changes from Thierry for FreeBSD support, and/or results of testing? + + * I re-merged an XXX comment re. NetBSD/amd64 and propogated a comment + on a duplicated #define for FreeBSD. We need the GNU autoconfig stuff + to be updated by someone who groks it, now. + +2004-02-09 rkrolib + + * src/freeglut_init.c: Commit of John's tidying-up of a comment, closing + out an XXX comment that I wrote. Thanks, John. + +2004-02-07 rkrolib + + * src/freeglut_window.c: ...AND a tab snuck into my changes for + GLUT_OFFSCREEN support. Mea culpa. + * src/freeglut_joystick.c: Removed a ^M that snuck into the #pragma for + the new joystick code. + * src/freeglut_window.c: Ooops. We don't want people to be able to + create a subwindow of an offscreen window. (^& This is no longer + permitted. + + (Actually, it would be nice if it would work, but I don't think that + you can subwindow a pixmap in UNIX_X11, and assume that subwindowing + offscreen doesn't work on WIN32, either.) + * ChangeLog: Added entries for the joystick updates and the offscreen + experimental support. + * src/freeglut_joystick.c: Changed a couple of XXX comments. Added a new + one. These all the nest of #ifs in the BSD section of the new joystick + code. + * progs/demos/CallbackMaker/CallbackMaker.c: "Heavy editing" by John to + his CallbackMaker demo. + * src/freeglut_joystick.c: John added a #pragma to the joystick code for + WIN32 users. + * src/freeglut_internal.h, src/freeglut_window.c: Adds GLUT_OFFSCREEN as + a display mode option. This includes: + + * Recognizing the mode when you call glutCreateWindow(). (Offscreen + looks and acts like a top-level window in many ways.) + + * During the life of the offscreen "window", various window-management + functions are modified to respect offscreen status. + + (Excepting reshaping windows, there is not much useful interpretation + for management of offscreen areas. Reshaping is possibly more work than + it's worth to support, and GLUT specs allow us to ignore the request.) + + * Cleanup for "offscreen" windows is a little different than for + regular windows. + + Windows still don't start up quite ideally. Offscreen windows should + probably get a reshape event, but not a display. + +2004-02-05 rkrolib + + * src/freeglut_init.c, src/freeglut_joystick.c: Big import of updated + joystick code from PLIB, with permission from Steve Baker. Most of the + adaptation done by John, with a little bit of testing and changes by + Thierry Thomas and myself. Seems to compile on: + + WIN32 Red Hat LINUX FreeBSD NetBSD/amd64 + +2004-02-01 rkrolib + + * src/freeglut_main.c: Close a bug whereby events can be delayed + arbitrarily long if they get caught between the socket and the + client-side queue on X, sometime after glutMainLoopEvent()'s loop + quits and before the sleep code is invoked. + +2004-01-16 rkrolib + + * src/freeglut_main.c: Amended a comment on fgCheckJoystickCallback(). + * src/freeglut_main.c: Minor style normalizations to minimize the diffs + between *now* and from before John's changes. No functional changes: + + * Removed some hard TABs introduced. * Removed some + spaces-at-end-of-line introduced. * A couple of function calls were + touched up. + + I did this separately only because I don't like messing with other + people's commits. (I don't like feeling like the style police, either, + but when I mess with the commit, there's no room for reverting my + interference if it is deemed undesirable...) + * src/freeglut_main.c: Some changes from John. + + The main attraction seems to be correcting a bug with the action-on- + window-close. + +2004-01-05 nigels + + * src/freeglut_main.c, src/freeglut_window.c: Win32 glutIconifyWindow() + patch contributed by John F. Fay Restrict resize callbacks to visible + windows When iconified via glutIconifyWindow(), don't pass (0,0) to + resize callback Note that minimising the window via the menu or + minimise button is not yet resolved. + +2003-12-30 rkrolib + + * src/freeglut_main.c, src/freeglut_menu.c, src/freeglut_structure.c: + Split a few overlong lines. + + Adjusted some spacing in a few spots to be more consistent with + freeglut style. Including one unindented if() body. + + Eliminated a dead variable. + * src/freeglut_joystick.c: Changed several #ifdef's to proper #if's. + Eeek. Oook. + * src/freeglut_main.c: Hm... I thought that I committed this last night. + What's up? + + This is Nigel's modified fgSleepForEvents(), essentially. Take 2. + +2003-12-30 nigels + + * include/GL/freeglut_std.h: Three supported win32 compilation + environments: MSVC, Cygwin and MingW32 #pragma is specific to MS + compiler + * src/freeglut_internal.h: Explicitly cast function pointer to (void *) + in SET_WCB since all callbacks stored as void pointers suppress gcc + -Wall -pendantic "noise" + * src/freeglut_structure.c: Typesafe handling of temporary window + destroy callback Move assignment out of while test, scope temporary + inside loop Be explicit about assignment/comparison in if test for gcc + peace of mind suppress gcc -Wall -pendantic "noise" + * src/freeglut_internal.h: Three supported win32 compilation + environments: MSVC, Cygwin and MingW32 The windows mmsystem header + need only be included internally to freeglut strdup vs _strdup is + specific to the MS compiler + * src/freeglut_font.c: strlen expects (char *), rather than (unsigned + char *) suppress gcc -Wall -pendantic "noise" + * src/freeglut_cursor.c: Replace assignment of array to struct with + field-by-field assignment suppress gcc -Wall -pendantic "noise" + * src/freeglut_menu.c: glutBitmapString and glutBitmapLength expect + (unsigned char *) rather than (char *) suppress gcc in -Wall + -pendantic "noise" + * src/freeglut_joystick.c: Replace #ifdef WIN32 with #ifdef + TARGET_HOST_WIN32, as per FreeGLUT convention + * src/freeglut_init.c: fgState.FPSInterval is unsigned int (GLuint), + environment variable GLUT_FPS can be negative + * src/freeglut_window.c: OpenGL context is not made current on Win32 + until fgSetWindow is called. This resolves severe problems observed in + GLUI applications. + * src/freeglut_window.c: #pragma message is only understood my MS + compiler #if defined(_MSC_VER) .. #endif + * src/freeglut_state.c: Resolve bug 864978 - GLUT_OWNS_JOYSTICK + unhandled + * src/freeglut_main.c: Tidy nested if/else to suppress gcc -Wall + -pedantic noise gcc suggests explicit braces to avoid ambiguous `else' + +2003-12-25 rkrolib + + * progs/demos/CallbackMaker/CallbackMaker.c, + progs/demos/Fractals/fractals.c, + progs/demos/Fractals_random/fractals_random.c: Configuring with + "--enable-warnings" broke three demos: * CallbackMaker defined, but + did not use, the Joystick() function (a callback for the freeglut + joystick interface). I uncommented the callback-registration. I assume + that it was commented out because it was spammy. (freeglut does + joysticks by polling with a timer.) Perhaps a longer interval than + 10ms would be advisable? + + * fractals.c used strcpy() without getting the prototype. Added + #include at the top. + + * fractals_random.c had the same problem as fractals.c. + +2003-12-23 rkrolib + + * src/freeglut_main.c: Moved the window-resize code so that it happens + whenever there is a pending resize for the window, whether or not the + window is visible or in need of a redisplay. The resize is now done + before the visibility and need-to-redisplay checks. + +2003-12-22 rkrolib + + * src/freeglut_structure.c: Got rid of those int/ptr warnings on AMD64. + (The code was casting an {int} to a pointer, and later retrieving the + int by another cast. It should be safe provided that pointers are at + least as big as {int}, but GCC was giving warnings on my system, + so...fixed.) + * src/freeglut_main.c, src/freeglut_structure.c: Several + test-on-assignment cases have been converted to stop GCC from + complaining about if( a = get_a_value_for_a( ) ) type code. + +2003-12-19 rkrolib + + * src/freeglut_internal.h: Ooops, left some cruft in a comment in the + header when committing the last patch. Cleaned up. + * src/freeglut_callbacks.c, src/freeglut_internal.h, + src/freeglut_structure.c: Wrote SET_WCB() to set a window callback. + This lets us out of using the FETCH_WCB() as an lvalue (which it + shouldn't, since the value of the FETCH is cast to the correct + function-pointer type). + +2003-12-15 James Jones + + * progs/demos/Fractals/Fractals.dsp: Change the destination directory of + the debug version to "Debug" (John Fay) + +2003-12-13 James Jones + + * ChangeLog: Release 2.2.0 + +2003-12-11 rkrolib + + * src/freeglut_main.c, src/freeglut_window.c: Stripped out TABs that got + reintroduced. + + There were no changes other than replacing about 10 to 12 TABs with a + visually-suitable number of spaces, so this can probably be blindly + treated as equivalent to the previous versions of the two affected + files. + +2003-12-11 Christopher John Purnell + + * src/freeglut_internal.h, src/freeglut_structure.c: The deferred window + destruction code was destroying the windows in reverse order. This + cased a crash when the call to glutDestroyWindow() for a sub windows + was immediately followed by a call to glutDestroyWindow() for it's + parent. fgCloseWindows() would call fgDestroyWindow() for the parent + first fgDestroyWindws() would recurse over the children and then + fgCloseWindows() would call fgDestroyWindow() again for the child. + + I've replaced the single linked list with one of our two way link list + structures. I've also moved it into fgStructure because that seemed + the consistent thing to do. + + I said the the deferred windows destruction causes more problems then + it solves. + +2003-12-11 James Jones + + * progs/demos/CallbackMaker/Makefile.am: Include project file in the + distribution. + * ChangeLog: Updates for 2.2.0 RC2 + * progs/demos/demos.dsw: Add shapes to the Visual C workspace. + * progs/demos/shapes/Makefile.am: Package the visual C project file with + the distribution + * configure.in: Set the version to 2.2.0 + * src/freeglut_gamemode.c, src/freeglut_main.c, src/freeglut_window.c: + Nigel Stewart's Win32 window-sizing fix for game mode + * progs/demos/One/one.c: Disable/enable lighting in the "one.c" demo + (John Fay) + * progs/demos/CallbackMaker/CallbackMaker.dsp: Add some essentials to + get this program to compile (Nigel) + * src/freeglut_internal.h: Update to reflect 2.2.0 release + * ChangeLog: Note the release of 2.2.0 RC1 + +2003-12-11 rkrolib + + * src/freeglut_structure.c, src/freeglut_window.c: John correctly + observed that the initialization {OldHeight} and {OldWidth} in the + window structure should be done for both windows and sub-windows, and + the easiest way to do this is in the + freeglut_structure.c:fgCreateWindow() code. So, transplant one line. + +2003-12-10 rkrolib + + * src/freeglut_main.c: Commit of John's change to stop an infinite-loop + condition when the only windows left are freeglut menu windows, and + correctly calls exit() if we drop out of the main loop without having + requested any freeglut extensions to glutMainLoop() handling. + +2003-12-07 rkrolib + + * progs/demos/shapes/shapes.c, progs/demos/shapes/shapes.dsp: Two from + Nigel: + + * Updated shapes.c. I think that it's just reformatting and the + addition of some comments. + + * Added shapes.dsp, a Microsoft Visual C++ Developer Studio Project + file for building shapes on WIN32 with MSVC++. + +2003-12-03 Christopher John Purnell + + * configure.in: Added an option to enable gcc compiler warnings. I've + explicitly excluded the one about adding parentheses. + +2003-12-03 rkrolib + + * src/freeglut_main.c: Touched up several comments, pointing up things + that may be worth reflect- ing upon in the future. + * src/freeglut_internal.h, src/freeglut_main.c, src/freeglut_window.c: + Hrm. I misunderstood the purpose of {window->State.Width} and + {...Height}. Those are *not* records of the old values, but rather of + the *desired* *new* values, hence it was inappropriate to use them in + ConfigureNotify X11 event handling. Doing so introduced some new + problems. + + So, I created OldHeight and OldWidth in the window State structure, + and *those* do what I require. + + I also stripped out the obsolete comment about getting extra/bogus + reshape events. (Though I maintain that an application should be + robust against them, freeglut should no longer generate them if the + window has not changed size since last reported.) + +2003-12-02 rkrolib + + * src/freeglut_main.c: Changed Create/ConfigureNotify handling in + UNIX_X11: + + * Just need to call GETWINDOW() once. Ooops. Heh. * Update + {window->State} with the new size of the window. * If the window-size + has NOT changed, then do NOT call the Reshape event. + * src/freeglut_main.c: Added an "XXX" earmark for post-release + contemplation. (The point is definitely in need of consideration, I + believe, but is not immediately a major bug, so I'd rather not mess + with it at the risk of postponing a release "soon".) + * src/freeglut_main.c: Ensure that the time-out for sleeping is never + negative. + * src/freeglut_main.c: Fixed a bug for UNIX_X11 where window reshape + events were causing freeglut to mark the window as *needing* a reshape + (which during general display callback handling would result in + effectively a glutReshapeWindow()). + + The code is now system-dependent. It should be abstracted to a + function, but is presently copied in two places. Sorry. + + Also, inverted the order of the associated if()/else check (in both + WIN32 and UNIX_X11 branches) since the former "else" part was a + one-line callback invocation. + + This fixes two seemingly unrelated bugs that I was seeing in UNIX_X11. + +2003-12-01 Christopher John Purnell + + * src/freeglut_internal.h: Added missing prototype for new list + function. + +2003-11-28 Christopher John Purnell + + * src/freeglut_init.c, src/freeglut_internal.h, src/freeglut_main.c, + src/freeglut_structure.c: Timer optimizations. Made the list of + pendinig timers ordered. Added a free list of used timer structures. + * src/freeglut_callbacks.c: Timer optimizations. + * src/freeglut_window.c: Fixed windows compilation problem with last + update. + +2003-11-27 Christopher John Purnell + + * src/freeglut_gamemode.c, src/freeglut_internal.h, src/freeglut_main.c, + src/freeglut_structure.c, src/freeglut_window.c: Window close fix. The + default behaiour should now be the same as with glut. + +2003-11-26 rkrolib + + * src/freeglut_init.c: Added change from Nigel to have resize events + cause redraw events in WIN32. Also slightly reshuffled comments to + deal with line-wrap issues. + +2003-11-25 rkrolib + + * src/freeglut_main.c: John reported, and fixed, a problem that recent + changes caused for the Lorenz demo (seems to be WIN32 specific). + * src/freeglut_structure.c: Update from John: Removed the freeglut hack + of decrementing the highst-window-ID marker when the highest window is + deleted. (This was a half-way measure for an idea that was decided to + be dubious in the first place.) + * configure.in, progs/demos/Makefile.am, progs/demos/shapes, + progs/demos/shapes/Makefile.am, progs/demos/shapes/shapes.c: Added a + new demo (from Nigel) showing some of the basic GLUT geometry shapes. + "shapes" is the name of the demo. + * include/GL/freeglut_ext.h, src/freeglut_geometry.c: Commit of work + from Nigel: + + Massive rework of the geometric primitive code. Includes a new + primitive (cylinder; solid and wireframe) and corresponding update to + freeglut_ext.h for the prototype. + * src/freeglut_internal.h, src/freeglut_main.c, + src/freeglut_structure.c: More work from John (sorry for + procrastinating): + + * We forgot to bump our version number in freeglut_internal.h It is + now at 2.0.2 (actually, I think that 2.1.0 might be a better choice), + which is presumably going to be our next formal release. 2.0.1 is + incorrectly identified as 2.0.0 in the header. + + * A typo in a comment has been corrected ("than"/"that"). + + * Numerous "manual" checks for callbacks are omitted now, since + INVOKE_WCB() does this for us. These were holdovers from the + pre-INVOKE_WCB() days. There may be some very subtle changes in + freeglut behavior, since freeglut used to test the callbacks a little + earlier in some cases and may have skipped some minor things (like + changes to the current window) in some special cases, otherwise. It is + not believed that any documented behavior is broken, and it is + unlikely---not to say impossible---that any extant applications will + detect the change. It is even possible that there is no external + behavioral change in freeglut. + + This also significantly simplifies some sections of code that used to + have conditional execution. "Unconditional code is simpler code" as + one of the comments used to say. + + * Lots of XXX commentary is now removed. Some of it was obsoleted by + other changes, some by changes from John. + * src/freeglut_internal.h, src/freeglut_main.c, + src/freeglut_structure.c: Change from John (I removed a couple of + spaces from a couple of lines in his freeglut_internal.h file where + they were wrapping in EMACS; otherwise, the files are exactly as he + sent them to me). + + The change unifies the WIN32 and UNIX_X11 code by defining our own + window-handle-type in freeglut_internal.h. This let John rip out some + #if garbage in several places. The result is clearer code. + + Thanks, John! + +2003-11-21 rkrolib + + * src/freeglut_font.c, src/freeglut_geometry.c, + src/freeglut_glutfont_definitions.c, src/freeglut_init.c, + src/freeglut_internal.h, src/freeglut_main.c, src/freeglut_menu.c, + src/freeglut_misc.c, src/freeglut_state.c, src/freeglut_structure.c, + src/freeglut_window.c: Numerous style normalizations from John: + + * Convert "return( value );" to "return value;" * Normalize spacing + around semicolons. * Remove extraneous parens. * Split multi-statement + lines into multiple lines. (Mostly things of the form: "if( condition + ) return;".) + * src/freeglut_internal.h, src/freeglut_main.c, src/freeglut_window.c: + All changes are from John, except for: (a) I re-inserted the meat of a + comment that I still feel is relavent. (b) I fixed a compile-time + error in the UNIX_X11 code where a variable is declared after + executable code in a block without creating a new sub-block for the + declaration. + + Changes from John include: (a) Style revision. (b) Changes to postpone + the handling of window resizes. + + Lots of lines were changed, but I think that thos two cover the ground + that he hit. See the diffs for details. + +2003-11-18 Christopher John Purnell + + * src/freeglut_cursor.c, src/freeglut_ext.c, src/freeglut_geometry.c, + src/freeglut_init.c, src/freeglut_internal.h, src/freeglut_main.c, + src/freeglut_menu.c, src/freeglut_state.c, src/freeglut_structure.c: + Lots of stuff that John F. Fay pointed out. Plus some changes to + remove gcc warnings. + +2003-11-17 Christopher John Purnell + + * src/freeglut_init.c, src/freeglut_internal.h, src/freeglut_main.c, + src/freeglut_state.c, src/freeglut_structure.c: Fix spelling mistake + in a variable name. Added a comment for John Fay. Added the copyright + notice for XParseGeometry source. + +2003-11-16 Christopher John Purnell + + * src/freeglut_init.c, src/freeglut_internal.h, src/freeglut_main.c, + src/freeglut_state.c, src/freeglut_structure.c: Made Modifers variable + global as per glut classic. + * src/freeglut_init.c: Removed old unused glutInitDisplayString code. + Reformated new glutInitDisplayString and XParseGeometry code. + * src/freeglut_init.c: Use XParseGeometry for better geometry parsing. + Moved geometry parsing to after fgInitialize() so we can use the + screen size to correctly calculate negative positions in the geometry + string. Copied the code for XParseGeometry from the X11 sources for + use in the Win32 version. freeglut now passes test1 of the glut test + suite. + +2003-11-15 Christopher John Purnell + + * src/freeglut_gamemode.c, src/freeglut_init.c, src/freeglut_internal.h, + src/freeglut_main.c, src/freeglut_structure.c, src/freeglut_window.c: + Removed the state variable BuildingAMenu. Instead pass a new parameter + isMenu to fgCreateWindow(). Elsewhere use window->IsMenu. + * src/freeglut_init.c: freeglut_assert_ready is going to have to go at + some point. But for now I've moved setting fgState.Initalized to + GL_FALSE. + * src/freeglut_callbacks.c, src/freeglut_display.c, + src/freeglut_gamemode.c, src/freeglut_init.c, src/freeglut_internal.h, + src/freeglut_joystick.c, src/freeglut_main.c, src/freeglut_menu.c, + src/freeglut_misc.c, src/freeglut_state.c, src/freeglut_structure.c, + src/freeglut_window.c: Replace TRUE with GL_TRUE and FALSE with + GL_FALSE where the type is GLboolean. + +2003-11-15 rkrolib + + * src/freeglut_main.c, src/freeglut_menu.c: Normalized the spacing + around symbols, for the most part. Ho-hum. + +2003-11-15 Christopher John Purnell + + * src/freeglut_main.c: Added a call to fgDeinitialize() before the call + to exit() in fgError(). + +2003-11-15 rkrolib + + * src/freeglut_joystick.c: Style normalizations to the joystick code. + +2003-11-15 Christopher John Purnell + + * src/freeglut_init.c, src/freeglut_internal.h, src/freeglut_main.c, + src/freeglut_state.c, src/freeglut_structure.c, src/freeglut_window.c: + Added a new state variable "Initalized". Replaced referenced to + Time.Set with this new variable where appropriate. fgElapsedTime() now + set the start time if Time.Set is false. Moved + glutGet(GLUT_ELAPSED_TIME) handling to before the assert. + +2003-11-14 rkrolib + + * src/freeglut_internal.h: Normalized the internal header's style a bit. + * src/freeglut_init.c: Plowed one more file this morning. Still just + trivial formatting issues. + + And I left alone the "INIT DISPLAY STRING PARSING" section, since it + still appears to be in flux. + * src/freeglut_font.c, src/freeglut_gamemode.c: Yet more trivial style + normalizations. + + Sorry, but that's all that I'm up to at the moment. On the plus, + excepting the font_data file (which I've been skipping), up through + this file, I think that the code style is pretty close to uniform. + * src/freeglut_font.c: Minor style corrections. + * src/freeglut_display.c: Minor spacing quibble. + * src/freeglut_cursor.c: Added a brief explanatory note to the X code + for GLUT_CURSOR_NONE. + + Corrected the indentation of a block of code. + * src/freeglut_window.c: Noted one of a few cases where we do something + immediately that could more efficiently be postponed, quite + easily---and which GLUT promises *is* to be postponed. (It is unlikely + that the difference will break any apps, but postponing should be + easy...) + + No real change, just a comment in the code. + +2003-11-11 rkrolib + + * ChangeLog: Updated ChangeLog for the day. + * include/GL/freeglut_std.h, progs/demos/One/one.c, src/freeglut_ext.c, + src/freeglut_font.c: Removal of all remaining TABs in the freeglut + *.[ch] files. (I missed a few in the "one" demo, it seems, and some + more crept back into freeglut_(ext|font).c, presumably due to my own + edits when I forgot to use the "freeglut-c-mode" in EMACS.) + * progs/demos/One/one.c: Moved glutInit*() functions ahead of + glutInit(). (This is proper use of glutInit() in general, since it + allows the user to override settings via {argc, argv} command-line + params.) + * progs/demos/One/one.c: Style normalizations: Removed CRs and hard TABs + mostly. + * ChangeLog, src/freeglut_structure.c: Corrected the numbering of the + ChangeLog (there were two (110)s). + + Added entries summarizing my commits since September or late August, + for the benefit of those lacking both CVS and web access. + * progs/demos/demos.dsw: Added CRs to the ends of all lines in MS + developer studio demos.dsw file.. + +2003-11-10 rkrolib + + * src/freeglut_main.c: John's fix for the minimize/close/maximize + controls no longer working. WIN32 expected us to pass the message on + up the chain (or do something else with it), rather than just throwing + away the event, for a certain class of events. (See the diffs for more + details.) + + The code is also slightly reformatted from what was previously in the + repository. + * freeglut.dsp, freeglut_static.dsp, + progs/demos/CallbackMaker/CallbackMaker.dsp, progs/demos/demos.dsw: A + *.dsp file for CallbackMaker in the demos. + + Plus updated *.dsp and *.dsw files to reflect the new freeglut header + file. + + NOTE: The prior version of the *.dsw file does not in fact have CRs. I + thought that it did. For consistency, I am not putting them in in this + version, either. (At least one person said that his MSVC++ system is + happy with the current files. If there are problems, we can easily add + the CRs, but that should be a separate commit...) + * configure.in, progs/demos/CallbackMaker, + progs/demos/CallbackMaker/CallbackMaker.c, + progs/demos/CallbackMaker/Makefile.am, + progs/demos/Fractals_random/fractals_random.c, + progs/demos/Makefile.am: New demo from John: CallbackMaker. + + This demo shows the use of every callback that you can register with + freeglut, and also generates event reports so that you can see what is + happening to the program as it runs. + + Not much to look at, but both utilitarian and a practical example. + + Please double-check that I updated everything that needs to be + updated. I reran autogen.sh and ./configure, and it built okay for me. + (^& + * src/freeglut_structure.c: Hm. I thought that I already hit this file + for style normalization. Oh well... Should be no functional changes. + Should be pretty close to in-line with the style of changes that I've + been making else- where. + * src/freeglut_structure.c: Ooops. Forgot that we already had a call to + fgClearCallBacks() in the code and added a second one. I just deleted + the new one. Sorry. + * src/freeglut_structure.c: Added Nigel's suggested code to clear all + but the destroy callback early on, leaving Destroy to be cleared later + after the last possible point where it should be invoked. + * src/freeglut_menu.c: Modified the menus to refer to {border} rather + than {FREEGLUT_MENU_BORDER}, in fghDisplayMenuBox(). The local + variable was already defined and used for some purposes, so we might + as well use it throughout. It does serve to shorten and clarify the + code a bit---though I have mixed feelings about creating aliases that + way. + + Still, the variable already existed and was already used in places. + (We could even move it into the freeglut state, or make it a {const + static} value...) + + Oh well. Stuff to ponder. + * src/freeglut_cursor.c: Well, a couple of days have gone by, so I + assume that items (a) and (b) in the freeglut_cursor.c file's "Open + issues" comment are now satisfactor- ily closed. + + I also partially implemented some error-checking, using my limited + understanding of how Xlib users are supposed to do this. (No one + commented about the lack of error-checking, pro or con. Perhaps + someone will care to comment now?) + + At present, it just will print out a warning, via fgWarning(). In part + because I'm not sure what is best to do, and in part because failure + to set the cursor type is probably not a fatal problem. + +2003-11-08 Christopher John Purnell + + * progs/demos/Fractals/Makefile.am, + progs/demos/Fractals_random/Makefile.am, + progs/demos/Lorenz/Makefile.am, progs/demos/One/Makefile.am: Applied + Braden McDaniel's non-srcdir build patch. + +2003-11-08 rkrolib + + * src/freeglut_menu.c: A first pass over freeglut_menu.c to bring it in + line with the rest of freeglut's style. Mostly re-indenting and + splitting long lines. For those that may be concerned: No, I didn't do + any more arrangements of the form (CONST == a) rather than (a == + CONST). (^& + * progs/demos/Fractals_random/fractals_random.c: Altered the way that + the {random} value (from 0..3) is chosen. + + Previously, it picked out two adjacent bits in the result of rand(). + Unfortunately, these adjacent bits (at least on NetBSD) have a certain + amount of dependence. After a period (perhaps a thousand or so?), it + starts to repeat the pattern of those two bits. (I think; I haven't + actually tested that directly.) This presumably is locking it into a + an an N-way attractor on the "snowflake", such that if you zoom in a + ways, you will start to see some spots *quickly* are colored, and + others are *never* colored. + + What I've done now is to pick up two widely-spaced bits in a single + rand() call. (Perhaps we would do as well to pick up something like + bit #16 from two consecutive rand() calls?) These widely-spaced bits + have a lower statistical dependence on one another (if I can get away + with using that term for an arithmetic operation; though since stats + has more to do with sampling and less to do with true randomness, I + may be safe). + + The net effect, at leats on NetBSD, is far better snowflake if you + zoom in on it. + +2003-11-07 rkrolib + + * src/freeglut_main.c: From John: + + [This] implements the visible/invisible for Windows. It does NOT call + the visibility callback, though. + * src/freeglut_main.c: Stripped out the now truly extraneous {braces} in + such forms as: + + if( ... ) { INVOKE_WCB( ... ); } + + Check for compiling on WIN32. + * src/freeglut_internal.h: Adopted Eero Pajarre's suggestion of using a + do { ... } while rather than { ... } for the INVOKE_WCB() macro. This + lets it be used "more like a function", in that: + + if( ... ) INVOKE_WCB( ... ); else ... + + ...is now legal. + * src/freeglut_main.c: Pure code janitoring: Shuffled the order of some + of the case statements in the UNIX_X11 X event processing loop. (In + general, it's nice to have case statements sorted, especially when you + have a *huge* switch statement like this. That makes it easier to find + the one that you're looking for, and to see if a certain case is + defined...) + * src/freeglut_main.c: Combined EnterNotify and LeaveNotify event + processing in the UNIX_X11 event loop. + * src/freeglut_main.c: Added ReparentNotify case to UNIX_X11 event loop, + to catch the extraneous ReparentNotify event types (type 21). + * src/freeglut_internal.h, src/freeglut_structure.c: Oh well, I might as + well add the call to clear callbacks on window destruction. Also + renamed the function to do this: fgClearCallBacks(). Ho-hum. + * src/freeglut_internal.h, src/freeglut_structure.c: Added + fgInitCallBacks() to freeglut_structure.c. (The function takes an + {SFG_Window *}.) Added prototype to freeglut_internal.h. Added use of + the function to the window initialization. (Don't count on calloc(), + which sets all bits to 0.) + * src/freeglut_gamemode.c: Style normalization; removal of + say-nothing-useful comments. + * src/freeglut_font.c: Normalized the style of freeglut_font.c No + substantial alterations. + * src/freeglut_ext.c: Somewhat normalized the style of this file. + + Also moved the "glutMouseWheelFunc" extension down into the + "extensions" part of the table. (Purely internal organization. It will + still be found.) + * src/freeglut_display.c: Further normalization of the code's style. No + substantial changes. + * src/freeglut_cursor.c: Split one last overlong line in + freeglut_cursor.c. + * src/freeglut_cursor.c: Added GLUT_CURSOR_NONE support in UNIX_X11 + (well, NetBSD; you lot need to try it on others; (^&). + + Deallocated some resources that we are creating. VERY slight memory + leak, but plugged now. + + These two complete the first two "Open issues" ( (a) and (b) ). The + first one also completes X support for glutSetCursor(). If others can + verify, we can fully demote the outstanding bug over this to + WIN32-specific. + + I'll delete the dead Open issues and re-letter the others if someone + will cross-check me. Or if no one says anything in a day or two. (^& + * src/freeglut_cursor.c: Further normalized the style of the cursor + code. + * src/freeglut_callbacks.c: Slight style improvements. Two rules of + thumb that are almost always good to apply: + + * Don't write a == CONST. Instead, write CONST == a. Or, more + generally (in C like languages): Avoid putting an lvalue on the + left-hand side of an == comparison. (For consistency, I try to avoid + lvalues on the left- hand side of any comparison---but == is the most + notorious.) + + (An "lvalue" is a value that can safely go on the left side of an "=" + assignment, of course. (^&) + + * Do not write if( !condition ) return; other_thing; return; + + (See page 18 of K&P's _The Elements of Programming Style_.) + + Instead, it is better to just write: + + if( condition ) other_thing; return; + + There are times when sacrificing structured programming (e.g., via + multiple return statements) is okay. But, here, there is no apparent + gain---indeed, there seems only loss---in the non-structured code. + * src/freeglut_main.c: Grr. Forgot to enable the "freeglut" C + programming mode in EMACS, and had a few TABs in the last commit. This + fixes that. Sorry. + * src/freeglut_main.c: Minor corrections to the UNIX_X11 mouse-wheel + support. In part this reflects that {button} is already shifted to the + GLUT numbering, and hence should be counted as 3&4, 5&6, etc. + + The other change was simply to clarify the computation of {direction}. + The original code did some clever arithmetic. The new code is more + straightforward, even if it requires more lines to express. + +2003-11-06 rkrolib + + * src/freeglut_main.c: Ooops. I screwed up on part of John's fixes. + Sorry. + + I think that I have his fix properly committed now. Mea culpa. + * src/freeglut_callbacks.c, src/freeglut_internal.h, + src/freeglut_main.c, src/freeglut_structure.c: Cleanup pass after + committing callback conversion (from structure to array-of-pointers). + Mostly deleted commented-out struct-based code. Also added some XXX + comments that I though should be pondered. (My own pair of eyes, and + one brain cell, were not sufficient at this time to decide what to do + for those ponderables. (^&) + * src/freeglut_callbacks.c, src/freeglut_init.c, + src/freeglut_internal.h, src/freeglut_joystick.c, src/freeglut_main.c, + src/freeglut_misc.c, src/freeglut_structure.c: Converted the + "Callbacks" structure (with named members holding individual callback + pointers) to a "CallBacks" array in fgState. (This is to allow us to + write a loop to clear all callbacks from windows when the window is + dead/dying. Using this, we can safely assign NULL to each in a loop.) + + Support includes two new macros, FETCH_WCB() and INVOKE_WCB(). See + freeglut_internal.h for more details there. + + Some typedefs of function pointer types were altered to make them more + uniform (necessary for the macros). + + All references to window-based callbacks in freeglut are updated to + use the new macros. + + Old usages will cause compile-time errors. + + As a side bonus, the new invocation macro sets the current window and + checks pointers so that these common steps can be uniformly done on + every window-based callback. This makes it easier to do things right. + At the same time, the array notation (and now required associated + casts) make it harder to bypass the macros and abuse the function + pointers, in general. + + After this commit, I will go through the code and clean up dangling + issues about formatting. This commit is just a "it now works, let's + checkpoint it" type of affair. + * src/freeglut_main.c: From John, a couple of lines needed to be changed + to fix the mouse wheel support on WIN32. + * progs/demos/Fractals_random/fractals_random.c: Update from John: + Includes mouse button, mouse motion, and mouse wheel support. + +2003-11-04 rkrolib + + * src/freeglut_menu.c: Multiple changes from John. Style issues, plus a + bug-fix to check a pointer before deallocating some memory. + + He also removed one obsolete comment, and added some more comments. + * src/freeglut_main.c: Some changes, mostly from John. Mostly style + changes. + + One bug fix from John: Execution state bug-fix in glutMainLoop(), per + his post yesterday. + + One fix from me: Changed "if( ButtonPress )" to "if( pressed )". + {ButtonPress} is a constant. + * progs/demos/Fractals_random/fractals_random.c: Per John's emailed + desire to have all files obey UNIX EOL conventions, I have stripped + out carriage returns from this file. + + This is the *only* change, but every line is touched. If you want to + see the real differences between older and newer versions, you will + have to get local copies of each and first match their EOL + convnetions. + * progs/demos/Lorenz/lorenz.c: Update from John: + + I [John] added a feature to check for memory leaks under Windows. + * progs/demos/Fractals_random/fractals_random.c: Update from John: + + I [John] converted everything to double precision to avoid compiler + warnings. I also added a feature to check for memory leaks under + Windows and removed a memory leak (surprise!). + * src/freeglut_callbacks.c, src/freeglut_cursor.c, + src/freeglut_display.c, src/freeglut_ext.c, src/freeglut_font.c, + src/freeglut_gamemode.c, src/freeglut_geometry.c, + src/freeglut_glutfont_definitions.c, src/freeglut_init.c, + src/freeglut_joystick.c, src/freeglut_main.c, src/freeglut_menu.c, + src/freeglut_misc.c, src/freeglut_overlay.c, src/freeglut_state.c, + src/freeglut_structure.c, src/freeglut_teapot.c, + src/freeglut_videoresize.c, src/freeglut_window.c: Got rid of the + G_LOG_DOMAIN junk, per discussion on the mailing list. + * src/freeglut_callbacks.c: Minor formatting quibbles. (The brain isn't + up to anything more serious at the moment.) + * src/freeglut_main.c: Missed a block where one level was 2-space + indented. + + Nit-picked a few other lines for consistency. + +2003-11-03 rkrolib + + * src/freeglut_init.c: Fixed a memory leak (thanks for the correction, + John!). + + Smoothed over some code style issues while I was here, but left the + init-string parsing alone for now. + * freeglut13.dsp, freeglutdll.dsp, freeglutstatic.dsw: Deleted 3 files + (again?) from CVS, on John's request. Old/obsolete MSVC++ project + files. (freeglut13.dsp, freeglutdll.dsp, freeglutstatic.dsw) + * src/freeglut_main.c, src/freeglut_structure.c: * Indentation issues. * + Pulled some common code into a nicely packaged function. * Found some + pointer/int issues. + * src/freeglut_main.c: Heh. + + Forgot to wrap the fgGetXModifiers() in a #if. Fixed. + * src/freeglut_main.c: Extracted some common code to a subroutine, in + glutMainLoopEvent(). (The common code was a snippet to compute X + keyboard modifiers as a bit-mask of GLUT symbols.) + * src/freeglut_main.c: Caught a few more little style issues. + * src/freeglut_main.c: Added a "case" for an X event that we turn on but + do not use. ({MapNotify}). We already caught {MappingNotify} and + {UnmapNotify}. + * src/freeglut_main.c: * Fixed a bug in the X11 handling of + scrollwheel/mouse. The old code, I believe, checked if *either* a + wheel or button callback was set, and then decided which to use---and + unconditionally called it. I left the "either" check in, but added + additional checks before actually doing the invocation. * Lots of + reformatting. Massive. The usual suspects, though, and fairly trivial: + Re-indenting to standard size, shuffling some spaces to match the + freeglut "standard" of: if( ... ) ...and: func( ... ) + +2003-10-31 rkrolib + + * src/freeglut_callbacks.c: Cleaned up one macro definition. + + Picked up an over-long line that I missed before. + * src/freeglut_callbacks.c: Fit some long lines to 80 columns. + * src/freeglut_cursor.c, src/freeglut_display.c, + src/freeglut_gamemode.c, src/freeglut_geometry.c: Last of the hard + TABs in the src/*.c files. + * src/freeglut_init.c, src/freeglut_joystick.c, src/freeglut_main.c, + src/freeglut_menu.c, src/freeglut_state.c: En masse removal of most (I + think) of the remaining hard TABs in files. There are still a couple + of files that need to be hit. + * src/freeglut_window.c: Picked up some stray TABs scattered in this + file. + * src/freeglut_window.c: Noted by XXX comments that the XFlush() calls + probably shouldn't be there. Flushing the X protocol stack every + little bit both adds clutter to the code and may impede performance. + + It seems that we should be able to get rid of these, though allowing + client code to directly call glutMainLoopEvent() does make it a little + more complicated. + + Something to ponder. + * src/freeglut_window.c: Polished off the say-nothing-new comments and + lines-over-80-columns in freeglut_window.c + + There should be no functional changes. + * src/freeglut_window.c: Missed a few say-nothing-new comments in + fgOpenWindow(). Eeep. Should be better now. (^& + * src/freeglut_window.c: Cleansed fgCloseWindow(): * say-nothing-new + comments axed. * de-TABbed. * Made the white-space to be consistent. + * src/freeglut_window.c: Cleaned up fgOpenWindow(): * Removed TABs. * + Made indentation consistent. * Deleted say-nothing-new comments. * + Changed an *error*check* from an assert to an if(). (The error-check + was on window creation; we don't want to lose that if the user + compiles with asserts deactivated. Also, assert()s really tell us more + about programming errors, rather than run-time errors, so it is a + little misleading to use assert() for error-checks, even if you can + depend upon assert()s never being compiled away to null statements.) * + Added some XXX comments for things that bear some rumination. + * src/freeglut_window.c: Cleanup to fgSetWindow(). The usual suspects: * + Removed tabs. * Made indentation consistent. * Killed off + say-nothing-new comments. + * src/freeglut_window.c: Cleanup to fgSetupixelFormat(). Should be no + functional changes. + + Code facelift included: + + * Consistent indentation. * Removal of all TABs (there were a bunch). + * Fit to 80 columns. + * src/freeglut_window.c: There should be no changes to code + functionality, though a fair bit of little changes to the code + appearance. + + * Fit the comments at the start of the file to fit 80 columns. * Noted + an unusual feature of the ATTRIB() macro. * Added ATTRIB_VAL() macro + which is really just two ATTRIB()s. This lets us put things like + {ATTRIB (GLX_RED_SIZE); ATTRIB (1);} on one statement: {ATTRIB_VAL + (GLX_RED_SIZE, 1);}. I did this to preserve some of the layout of + information while also avoiding the nasty semi-visible ";" in the + middle of a line of code. And by putting the {braces} in the macro + definition, I was able to visually clean code of the form: if + (condition) { ATTRIB( X ); ATTRIB( 1 ); } ...rewriting as: if + (condition) ATTRIB_VAL( X, 1 ); * Eliminated a bunch of + say-nothing-new comments in fgChooseVisual(). * Combined some + semi-useful comments into a block comment summarizing a loop. + +2003-10-30 rkrolib + + * src/freeglut_structure.c: Finished off most of the issues with + freeglut_structure.c, from a stylistic point of view (at least, + insofar as: The original file's code was INCON- SISTANT. I did not + remove the "!= NULL" stuff, did not address the shortest-branch-first + issue for if-else statements, and left some rather ugly "if (x) {... + return y} /* else do this */ return NULL;" garbage. This should, I + think, be re-written as "if (x) return y; else return NULL;" or even + better, "ret = NULL; if (x) ret = y; return ret;" + + In short, the code still has some issues, but I think that it's a bit + better. + + (Oh, I also got rid of outstanding TABs.) + * src/freeglut_structure.c: Eliminated most of the say-nothing-new + comments. + + Fit most of the code to no more than 80 columns. + + Raised some issues about completeness/correctness of trying to + decrement the max-window-ID (apparently in order to partially recycle + some window IDs to slightly slow the rate of growth of window IDs). (I + didn't change what the code does, though.) + + The functionality of the code should be unchanged. + * src/freeglut_main.c: Forgot to set {direction} explicitly to +/- 1 for + freeglut mouse-wheel API on MS-WINDOWS. Oops. + + Now it should always report +/- 1 on MS-WINDOWS, per the spec. + * src/freeglut_main.c: Minor fix to allow for multiple ticks to be + received at one time by the WIN32 code. Take abs(direction) as the + number of ticks, and count it down. + + *should* be included by freeglut_internal.h, I think, so it + should be okay; otherwise add a suitable #include. + * src/freeglut_main.c: Grrr. My attempt to commit got aborted, and the + commit message was lost. Now I've lost track of what I said I'd done. + Something like: + + * Fixed some issues with multiple wheels. * Noted in comments some + issues about other-than-3-real-buttons. * Fixed formatting to fit 80 + columns. * Removed some BCPL/C++ style comments (//) that are not + legal, and which, if memory servers, are not even strictly legal when + disabled by preprocessor directives. E.g., + + #if 0 not-syntactically-valid-C #endif + + ...is not legal. Though most cpp's will discard the bracketed material + completely before the main C compiler pass has a chance to analyze the + syntax. (MSVC++ and GCC both don't seem to mind the BCPL style + comments in plain C, but let's keep the sources clean, eh?) * Fixed a + problem that would have caused freeglut to report doubled wheel events + under XFree86. + + Not tested other than compiling. Personally, I think that the + interface is inherently broken at this point unless you are willing to + get user- configuration. (Which would then solve the complaint that + Steve had about computing the tick-size on behalf of applications.) + I.e., there is NO WAY to know if we have the right buttons to start + wheels at, or if there are any buttons after the first wheel(s), etc. + We just have to guess---and if we are wrong, we can get varying + degrees of brokeness. + +2003-10-29 Christopher John Purnell + + * src/freeglut_window.c: There is a problem with the way I did + glutFullscreen() in my last commit. So I've copied the way the game + mode does it. It's not ideal but it works. The glutGet() for the + window border sizes will also have to be fixed at some point. + * src/freeglut_window.c: Rewrote glutFullscreen(). It now correctly + places the window in X11. It now uses system dependent code for more + efficient use of windowing system calls. + +2003-10-29 rkrolib + + * src/freeglut_joystick.c: Should be no real changes to the code + function. + + I missed a few lines that went past 80 columns. (^& + + Also made formatting more consistent. + + Added a couple of XXX comments re. FreeBSD vs. general BSD #ifdef's. + * src/freeglut_joystick.c: Should be entirely superficial changes to + code style: + + * Fit lines to 80 columns. (It does get tiresome seeing long lines + forced to break by the right-hand border of windows...(^&) * + Eliminated say-nothing-new comments. * Made formatting more consistent + in spots. * Eliminated some hard TAB characters. + * src/freeglut_joystick.c: Added Thierry's change to include + sys/param.h. This lets us pick out version numbers for OS releases + corresponding to system headers. + + I modified it to also work with NetBSD; I cannot confirm if it is safe + with any other systems, so it remains protected by a #if. + * src/freeglut_state.c: Deleted some say-nothing-new comments. + + Added some XXX's where comments seemed to require future attention. + + Added some new comments with XXX's where future attention seems + profitable. + * src/freeglut_state.c: Deleted a bunch of say-nothing-new comments. + Someday, there shall be an end to them. + * src/freeglut_state.c: Previous changes were made without the freeglut + major mode in EMACS. Re-tweaked some lines (mostly got rid of some + TABs, but also resulted in some changed indentation). + + Reformatted a big comment to fit to 80 columns. + + Removed bogus references to "Linux". (UNIX, and/or X11 were relavent, + and "UNIX/X11" was substituted for "Linux" in those places. This + includes UNIX-alike systems.) + * src/freeglut_state.c: Rewrote the TODO BEFORE THE STABLE RELEASE + comment to fit to 80 columns. + + Cleanup of fghGetConfig(). (One return statement, simpler code.) + + Made glutSetOption() have a more consistent style---and also got its + lines to stay under 80 columns. + * src/freeglut_misc.c: Got the last of the say-nothing-new comments in + freeglut_misc.c. + + (I would have picked them up before, but wanted the bug-fix and + conversion-to-error-message changes to go in before I did more + superficial stuff.) + * src/freeglut_cursor.c, src/freeglut_main.c, src/freeglut_misc.c: * + Fixed a bug that I introduced in fgWarning()/fgError(): I thought that + ((a) || (b)) was defined to have value as: (a) if (a) != 0 (b) if (a) + == 0 + + ...instead, it has value 0/1. This was causing a bug. It's probably + just as well, since what I was trying to do definitely fell into the + category of "clever code" rather than "clear code". + + Sorry. + + * Made glutSetKeyRepeat() call fgError() if you go out of range. (The + old code silently did nothing---not even a warning.) + + If it is really desirable to keep running, we should probably at least + generate an fgWarning(). + + * Deleted some say-nothing-new comments. + + * XXX added: Is glutSetKeyRepeat() deprecated? + +2003-10-28 rkrolib + + * include/GL/freeglut_ext.h, src/freeglut_callbacks.c, + src/freeglut_ext.c, src/freeglut_internal.h, src/freeglut_main.c: + Commit, mostly of work from John: + + * Removed some say-nothing-useful comments. * Added some tentative + mouse-wheel support. * Fairly massive reformatting of code. + + I made some secondary changes to his changes: + + * One compilation error was fixed (missing close-paren + semicolon). * + Deleted a few ore say-nothing-useful comments. * Some of John's code + was strangely formatted to the point that it seemed completely out of + place, so I took the liberty of reformatting it. Since I used GNU + EMACS's key (which re-indents rather than inserts TAB + characters), I had to propagate some indentation changes a little + further than the bare necessity to match up with John's changes. (John + seems to shoot for 2-space indents, while EMACS (and I, I confess) + strongly prefer 4-space indents. The code that I was re-indenting had + been put to 8-space indents, however.) + + I have *not* tested the code beyond compiling. I assume that John did + (and that the compilation error was a result a minor change just + before asking me to commit). + * src/freeglut_cursor.c: Re-indentation style changes from John. + + There should be no alterations to how the code performs. + + (I modified how the X11 section of the set-cursor code is indented to + slightly better match (IMHO) the rest of his changes.) + +2003-10-27 rkrolib + + * src/freeglut_menu.c: Converted a few "x != NULL" tests to "x" for + clarity. + + I think that I've touched enough lines of source for one morning. + * src/freeglut_menu.c: Cleaned up a little redundancy in a comment on + the {menu_pen_*} variables. + * src/freeglut_menu.c: Removed about 90 lines of say-nothing-new + comments. + + The code should be functionally unaltered by these changes. + * src/freeglut_menu.c: Propogated a pointer-check from menu-attach to + menu-detach. (Apparently, in some cases, the Menu member variable can + be NULL.) + + Corrected the menu-attach code to make sure that both Window and Menu + pointers are non-NULL (rather than "at least one"). + + Rewrote button-checks to more simply and more clearly assert that the + "menu button" is a valid button for menu actions: Instead of + laboriously comparing against the three valid buttons (0, 1, 2 or + GLUT_BUTTON_*), we do a simpler range-check and the upper bound is + {FREEGLUT_MAX_MENUS}, allowing us to change the number of menuable + buttons fairly easily in the future. + + Also deleted a few say-nothing-new comments. + * src/freeglut_menu.c: Cosmetic changes (mostly deleted a few more + say-nothing-new comments). The functionality of the code should be + unchanged. + * src/freeglut_menu.c: Changed an "#elif TARGET_HOST_UNIX_X11" to + "#else", since this simply governed menu aesthetics. I think that it's + better to have a default that works than to break completely, should + freeglut ever be ported to a new (non-WIN32, non-UNIX/X11) target. + * src/freeglut_menu.c: Minor modifications to the menus: + + * Updated an old "TODO BEFORE STABLE" comment. + + * Expanded a comment re. some #define macros. + + * Made colors and font choice system dependent. The UNIX freeglut + menus look more like UNIX GLUT menus, now. (This is PURELY a cosmetic + change. But it achieves better compatibility visually.) + * src/freeglut_main.c: Cleaned up glutMainLoop() a bit: + + * Deleted numerous say-nothing-new comments. * Reformatted a + say-something-useful comment to fit on an 80-column display. + * src/freeglut_main.c: Partially (re-?)unified some of the + glutMainLoopEvent() code. The only code that really needs to be + system-specific is the window event handling, which in MS-WINDOWS is + tucked into a separate function. In UNIX/X11, it's all spilled out + into glutMainLoopEvent() for some reason. + + If the X11 code could be tucked into another function, + glutMainLoopEvent() could be platform-independent. + +2003-10-26 rkrolib + + * src/freeglut_main.c: Moved the idle callback out of + glutMainLoopEvent() and into glutMainLoop(), per discussion on the + list. The code looks okay, to me, though I remain less than wholly + convinced that treating idles as special cases is the best way to go. + Still, a case can be made for taking "non-event" idle callbacks out of + the "event loop". From an organizational perspective, I think that + it's an improvement, and it fixes a bug for at least one program. + * src/freeglut_menu.c: Added John's text-positioning modification. + + The lines that he was altering were very oddly-split, so while I was + at it, I repaired the line-break damage. + * src/freeglut_joystick.c: Committed change from Nigel to fix the + joystick bug. (The joystick code was not setting the GLUT window prior + to calling callbacks.) + + Please verify. If so, this closes out, I think, the latter half of + that bug report, so anyone with the means to modify/close bug reports + should do so upon verification of the fix. + * src/freeglut_main.c: Superficial cleanup of the code. Mostly taking + lines such as: + + ... + + /* * */ + + + ...and rewrote as: + + ... + + freeglut_main.c still has a lot of that in it, but it looks a bit + better, now. + * src/freeglut_init.c: Added some error-checking (particularly w.r.t. + strdup()). + + Deleted numerous 4-line "padding" sequences of C-as-English trans- + literation comments. + + Re-indented some (but not all) code that is using 2-space indentation. + (Most of the freeglut code seems to be using 4-space indentation.) + + I did not touch the "INIT DISPLAY STRING PARSING" code, since it is + filled with a ton of over-long lines and also appears to be in more + flux than the rest of the code. (Well, I added one error-check to a + strdup().) + * src/freeglut_font.c: Removed two more bogus "carriage return" + references where the comments were in fact talking about a line feed + (a.k.a. newline, LF, ^J, \n, ...). + * src/freeglut_init.c, src/freeglut_internal.h, src/freeglut_main.c: + Fixed the buglet about failing to report the program's name on error- + messages. Please test. (Modified glutInit(), the state structure, and + the warn/err functions.) + +2003-10-23 James Jones + + * ChangeLog: Released 2.0.1 + +2003-10-21 Christopher John Purnell + + * configure.in, include/GL/Makefile.am, include/GL/freeglut.h, + include/GL/freeglut_std.h, include/GL/glut.h, + progs/demos/Fractals/Makefile.am, + progs/demos/Fractals_random/Makefile.am, + progs/demos/Lorenz/Makefile.am, progs/demos/One/Makefile.am, + src/Makefile.am: Added --disable-replace-glut option to autoconf + configure. + +2003-10-15 James Jones + + * NEWS: Noted the release of 2.0.0 + * configure.in: Version bump + +2003-10-14 rkrolib + + * src/freeglut_font.c: Swept the freeglut_font.c for comment cleanup: * + Got rid of the "rewrite C as English" comments. * Corrected several + bogus references to "carriage returns" (in strings). The symbols were + newlines or EOLs or LFs (\n). They were *not* carriage returns or CRs + (\r). * Clarified the comments on glBitmap() calls. + +2003-10-13 rkrolib + + * progs/demos/Fractals/fractals.c, + progs/demos/Fractals_random/fractals_random.c: Small bug-fix that's + been on my mind: + + Modified the two Fractals* demos so that they only clear (for the + random one) or redraw (for the non-random one) if there is need to do + so. (E.g., pressing the space bar should not clear and redraw the + random fractal since no parameters are altered.) + * src/freeglut_cursor.c, src/freeglut_display.c: Removed the obsolete + hack (or very ill-conceived dream), fgDisplayCursor(). + * src/freeglut_display.c: Cleaned up some of the style issues (mostly + "fluff" comments) in freeglut_display.c. + * src/freeglut_cursor.c: Comment-cleaning sweep. + + Mostly got rid of the say-it-in-English comments that were adding 1 + line of English and 2 or 3 lines of filler for each of several lines + of C code. Updated a couple of other comments, and tweaked some + white-space. + * src/freeglut_callbacks.c: Cleaned up the comments a bit in the + callbacks.c file (mostly removed some of the + kill-4-lines-to-translate-one-line-of-C-into-English comments). + +2003-10-12 rkrolib + + * src/freeglut_cursor.c: Added all missing GLUT cursor types for X11. + + (Type NONE is not properly supported, yet.) + + Corrected behavior for the several old types: * Wrong glyphs. * + Reversed glyphs (left/right confusion!) + + There are some remaining imperfections, but it's a lot closer to GLUT + comformity, now. + +2003-10-11 rkrolib + + * src/freeglut_callbacks.c: Three tidying-up changes to the code of + freeglut_callbacks.c; none of them are Earth-shattering, but as I + swept through looking somewhat more systematically for errors, I + picked these off. See the diff's for details. + * src/freeglut_callbacks.c: Fixed a basic readability/style error in the + code. (Two statements per line are almost never a good idea; in this + case the combined line was past 80 columns.) + * src/freeglut_callbacks.c: Added a safety-check on a memory allocation. + (Timers were using dynamic memory allocation but NOT checking the + result!) + * src/freeglut_menu.c: Committed two lines from John to help fix the + menus a bit. + * src/freeglut_callbacks.c: Check the glutDisplayFunc() callback for + being a NULL pointer. This is illegal and is disallowed in GLUT 3.0+, + so we disallow it too in freeglut 2.0.1+ + +2003-10-09 rkrolib + + * progs/demos/Fractals/fractals.c, + progs/demos/Fractals_random/fractals_random.c: Applied John's updated + ReadConfigFile() changes to the fractals demos. + * progs/demos/Fractals_random/fractals_random.c: Fixed: * glutInit() + ordering w.r.t. glutInit*() and {argv} processing. * Aspect ratio. * + Removed depth-buffer usage. (Also done for Fractals in previous + commit...) + * progs/demos/Fractals/fractals.c: A few minor changes: * glutInit*() + calls should precede glutInit(), per se, generally. This is so that + glutInit()'s configuration (which picks up on user parameters) can + override application defaults. * glutInit() should be called before + ANY attempt to process {argv, argc}. This is because there may be + GLUT/freeglut parameters (such as "-display" on X11). * If the window + is tall and skinny, rather than short and squat, we need to handle + aspect ratios differently. + + The first is a user-interface bug. The second is a serious bug + (especially since the demo assumes that argv[1] contains a filename). + The third is a display bug. + +2003-10-08 rkrolib + + * src/freeglut_main.c: Changed CreateNotify (in X11 ONLY) to act like a + ConfigureNotify event. + + This is done so that subwindows on X11 will get "resize" events when + they are created. Old GLUT did this---presumably by design in order to + ensure that (a) All windows get notified of their size as soon as the + window exists, and (b) probably more importantly, so that windows and + sub-windows behave as much alike as possible. I believe that GLUT was + right to do this, and I believe that compatibility requires this (I + have a sample program that breaks in freeglut but not GLUT without + this fix). + + I did not touch the Microsoft side, because I don't know what their OS + does---nor if old GLUT was historically system-dependent about this. + +2003-10-08 Eric Sandall + + * ChangeLog, src/freeglut_menu.c: freeglut_menu.c:217,519,532: Fix menus + to stay in the window (John Fay) + +2003-10-08 rkrolib + + * src/freeglut_menu.c: Several updates from John and myself. + + The broad outlines are: + + * Color schemes are now in variables, are closer to old GLUT, and are + system dependent (as old GLUT did). * You can change the font to any + bitmapped font more easily, which can aid in finding a better + approximation. (Old GLUT does not seem to have used a GLUT font for + the menus, which causes problems for us.) The menus rescale + automatically, including the triangle "arrow" for sub-menus. * Menus + have real borders, and the placement of highlighting is much improved. + * src/freeglut_main.c: Fixed a bug in the menu callback behavior. Menus + were not setting the current window correctly. + +2003-10-06 Eric Sandall + + * ChangeLog, src/freeglut_menu.c: freeglut_menu.c:328 Fix submenu + triangle (John Fay) + +2003-10-04 James Jones + + * ChangeLog, src/freeglut_main.c, src/freeglut_structure.c: Tweaking for + menu behavior in Linux regarding mouse whatnot - John Fay + +2003-10-01 rkrolib + + * src/freeglut_joystick.c: Applied a patch from "extraeme@netbsd.org" to + add joystick support. Untested, but it compiles for me. + + Should also add Joystick support for older FreeBSD systems. Also + untested. + * src/freeglut_main.c: Added support for more arbitrary number of mouse + buttons (though only the first three can work with menus), in X. This + closes a compatibility gap with old GLUT, and leaves us the option of + supporting scroll-wheels properly. + +2003-09-27 Christopher John Purnell + + * progs/demos/Fractals/Makefile.am, + progs/demos/Fractals_random/Makefile.am, + progs/demos/Lorenz/Makefile.am, progs/demos/One/Makefile.am: Don't + install the demos. + +2003-09-26 James Jones + + * progs/demos/Makefile.am: Package the demos.dsw file. + * progs/demos/demos.dsw: Demos workspace for MSVC users + +2003-09-24 rkrolib + + * src/freeglut_main.c: Corrected a bug w.r.t. display and joystick + events. When getting ready to sleep, we need to go through ALL windows + to check for pending joysticks and to check for pending redisplays. I + was just going through all TOP- LEVEL windows. Eeek. This won't do. + +2003-09-23 Brian Paul + + * progs/demos/Fractals_random/fractals_random.c: added needClear flag to + take care of initial window clear and window resize clears + +2003-09-23 rkrolib + + * src/freeglut_init.c: Per Nigel Stewart's comments, converted + + #ifdef TARGET_HOST_... + + to: + + #if TARGET_HOST_... + + in src/freeglut_init.c. These changes should not have any functional + impact at this time, but you don't want bad examples lying around to + trip people up later. + * progs/demos/Fractals_random/fractals_random.c, src/freeglut_main.c, + src/freeglut_window.c: Fixed: * GLUT_SINGLE now should behave more or + less correctly. Thanks to Brian Paul! + + * Sleeping is now cognizant of outstanding redisplays. + + * Fractals_random has been restored more or less to as-before, save + that it uses the more minimal glFlush() rather than glutSwapBuffers(). + glutSwapBuffers() was only required when freeglut was incorrectly + handling promotion to double-buffering. + +2003-09-22 rkrolib + + * src/freeglut_main.c: Moved the #include/#ifdef/#define stuff up to the + top. + + Changed #ifdef to #if, per Nigel(?)'s comment. Ooops. + +2003-09-22 Christopher John Purnell + + * progs/demos/Fractals/Makefile.am, + progs/demos/Fractals_random/Makefile.am, + progs/demos/Lorenz/Makefile.am, progs/demos/One/Makefile.am: Fix to + allow demos to compile before freeglut has been installed. + +2003-09-22 James Jones + + * progs/demos/Fractals_random/fractals_random.c: Add an idle function to + ensure that the screen gets drawn even when callbacks are not + generated by the mouse/keyboard. + +2003-09-21 James Jones + + * progs/demos/Fractals/fractals.c, + progs/demos/Fractals_random/fractals_random.c: Note the possible + buffer overflow in window_title + * progs/demos/Fractals/fractals.c: Fix the window title. + * progs/demos/Fractals_random/fractals_random.c: Fix window title, and + ensure that the random integer is not forced to be zero (Thanks + Richard Rauch!) + +2003-09-20 James Jones + + * src/freeglut_main.c: Richard Rauch's patch to ensure that freeglut + does not use 100% CPU even while idling. + * src/freeglut_font.c: Resolution for bug 809561 reported by Nigel + Stewart, regarding a possible array underflow error of -1 in the event + of "character" being zero. + +2003-09-14 Christopher John Purnell + + * configure.in, progs/demos/Fractals/Makefile.am, + progs/demos/Fractals_random/Makefile.am, + progs/demos/Lorenz/Makefile.am, progs/demos/One/Makefile.am, + src/Makefile.am: Removed unused AC_PROG_RANLIB from configure.in Added + passing of $(X_CFLAGS) to compiler. + +2003-09-14 James Jones + + * include/GL/glut.h: Resolve bug 806008 -- let Microsoft's compiler know + to use Windows libraries even if not using our project files. + +2003-09-13 James Jones + + * ChangeLog: Taking care of keeping things mostly up-to-date + * TODO: Most everything's been resolved for the 2.0.0 release. + * src/freeglut_joystick.c: Thierry Thomas said that FreeBSD has no + machine/joystick.h, instead a sys/joystick.h. I've made the change -- + here's hoping it works. + * progs/demos/One/one.c: Removed the incorrect relative path for + including freeglut.h + * progs/demos/Fractals/Makefile.am, + progs/demos/Fractals_random/Makefile.am, + progs/demos/Lorenz/Makefile.am, progs/demos/One/Makefile.am: Made all + demos compile. Thanks to Thierry Thomas for reporting bug 802809, + which alerted that *none* of the demos compiled automatically! + * src/freeglut_main.c: Nigel Stewart's joystick fix (for hopefully all + platforms), SourceForge bug 805481 + * progs/demos/Lorenz/lorenz.dsp, progs/demos/One/one.dsp: Fix location + of the include files from a fixed to relative path. Closes bug 805477 + * freeglut.dsp, freeglut.dsw, freeglut_static.dsp, freeglutstatic.dsw: + Add dos line endings. Fixes bug 805476 + +2003-09-10 Christopher John Purnell + + * src/freeglut_joystick.c: A minor fix to that last commit. + * src/freeglut_joystick.c: Removed some remaining glib depandancy. + +2003-09-10 James Jones + + * src/freeglut_main.c: Re-add catches for the case in which a menu + callback destroys the menu. - John Fay + +2003-09-09 Christopher John Purnell + + * src/freeglut_main.c: More to fix a deinitialization related crash. + * src/freeglut_structure.c: Fix for a deinitialization related crash. + +2003-09-08 James Jones + + * src/freeglut_main.c, src/freeglut_structure.c: Menus should deallocate + better now - John Fay + +2003-09-05 James Jones + + * Makefile.am: Add freeglut_static.dsp to the releases + +2003-09-03 Christopher John Purnell + + * src/freeglut_gamemode.c: Moved #ifdef for non XFree86 X11 compile. + +2003-09-02 Christopher John Purnell + + * src/freeglut_window.c: Fix to stop fgSetWindow(NULL) crashing on X11. + +2003-08-29 James Jones + + * src/freeglut_main.c, src/freeglut_menu.c, src/freeglut_structure.c: + These change a bunch of assignments to calls to set the current window + correctly, and also (possibly) fixes most of the remaining menu + problem. - John Fay + * src/freeglut_main.c: Another typecast bugfix from John Fay + +2003-08-28 Christopher John Purnell + + * src/freeglut_init.c: Changed #ifdef to #if + +2003-08-28 James Jones + + * src/freeglut_font.c: change the GLUT stroke function arguments from + "const char *" to "const unsigned char *" - John Fay + * include/GL/freeglut_ext.h, include/GL/glut.h: Changes stroke function + arguments from "const char*" to "const unsigned char *" - John Fay + +2003-08-28 Christopher John Purnell + + * freeglut-1.3: Removing files from old freeglut-1.3 directory. + +2003-08-28 James Jones + + * src/freeglut_callbacks.c, src/freeglut_geometry.c, + src/freeglut_init.c, src/freeglut_joystick.c, src/freeglut_main.c, + src/freeglut_menu.c, src/freeglut_structure.c: Casting changes, John + Fay + +2003-08-27 James Jones + + * src/freeglut_init.c, src/freeglut_internal.h, src/freeglut_main.c, + src/freeglut_menu.c: Major overhaul to the menu system, by John Fay + +2003-08-27 Christopher John Purnell + + * include/GL/freeglut.h, include/GL/freeglut_ext.h, include/GL/glut.h: + Added double underscores to the header included macros. + +2003-08-20 Christopher John Purnell + + * src/freeglut_gamemode.c: Minor typo fix + +2003-08-19 Christopher John Purnell + + * src/freeglut_gamemode.c: Moving that "#if TARGET_HOST_UNIX_X11" to the + correct place. + +2003-08-17 Christopher John Purnell + + * ChangeLog, src/freeglut_gamemode.c, src/freeglut_internal.h, + src/freeglut_window.c: Game mode fixes from Bernhard Kaindl and Eric + Espie. + +2003-08-05 Christopher John Purnell + + * src/Makefile.am, src/freeglut_menu.c, src/freeglut_window.c, + src/mwmborder.c: Using override_redirect instead of motif wm hints. It + now rasies the menu windows before showing them. Move the show to + after the reshape and position so we don't get a flash of the menu + window at it's old size and position. + * src/mwmborder.c: I suspect a lot of people will not have motif + installed. + +2003-08-05 Eric Sandall + + * ChangeLog, src/Makefile.am, src/freeglut_window.c: (98) + src/Makefile.am:34 Added mwmborder.c (99) src/freeglut_window.c:67 + Removed #included "mwmborder.c" + * ChangeLog, src/freeglut_main.c: src/freeglut_main.c:816 and :1571, set + the current window (John F. Fay) + +2003-08-04 Christopher John Purnell + + * src/freeglut_state.c: Added X11 code for + glutGet(GLUT_WINDOW_BORDER_WIDTH) and + glutGet(GLUT_WINDOW_HEADER_HEIGHT). + * src/freeglut_internal.h, src/freeglut_state.c: Replacing + glutGet(GLUT_WINDOW_X) and glutGet(GLUT_WINDOW_Y) on X11 with + something that works. Also a minor correction to the xf86vidmode + autoconf stuff. + +2003-08-04 James Jones + + * src/freeglut_window.c: Keep the X11 decoration-zapping code confined + to X11-using platforms! Oops! + * src/freeglut_window.c, src/mwmborder.c: Menus' decorations are removed + on Linux. Not sure if we want the mwmborder.c a separate file or not; + doing it separate for right now. Makefile was not updated, since the + .c is just #included. + +2003-08-03 Christopher John Purnell + + * configure.in: Got rid of configure warnings when using a newer + autoconf + +2003-08-02 Christopher John Purnell + + * src/freeglut_glutfont_definitions.c, src/freeglut_internal.h: Putting + stuff back that was undone with the menu code committed. + +2003-08-02 James Jones + + * src/freeglut_callbacks.c, src/freeglut_display.c, + src/freeglut_glutfont_definitions.c, src/freeglut_init.c, + src/freeglut_internal.h, src/freeglut_main.c, src/freeglut_menu.c, + src/freeglut_state.c, src/freeglut_structure.c, src/freeglut_window.c: + Major menu changes (they appear in their own window, have own + rendering context) by John Fay and a little by James C. Jones. They + work perfectly on Win32, and work... on Linux. + +2003-08-01 Christopher John Purnell + + * configure.in, src/Makefile.am, src/freeglut_glutfont_definitions.c, + src/freeglut_internal.h: Added autoconf detection for the xf86 vid + mode extensions. + +2003-08-01 Eric Sandall + + * ChangeLog, src/freeglut_window.c: src/freeglut_window.c:551 Removed + extra carriage return for Windows users (John F. Fay) + * ChangeLog: Credit Dave Reed for fix + * ChangeLog, src/freeglut_internal.h: src/freeglut_initial.c:91 Added + check for SOLARIS OS + +2003-07-23 Christopher John Purnell + + * include/GL/glut.h, src/Makefile.am, src/freeglut_font.c, + src/freeglut_glutfont_definitions.c: This should put an end to the + font binary compatibility issue. + +2003-07-23 Eric Sandall + + * ChangeLog, src/freeglut_window.c: src/freeglut_window.c Windowing + fixes from John F. + * ChangeLog, doc/Makefile.am: doc/Makefile.am:4 Removed trailing + backslash and added an empty last line + +2003-07-23 Brian Paul + + * doc/download.html: no change, testing CVS + +2003-07-22 Brian Paul + + * doc/download.html: no change, just testing CVS + +2003-07-22 Eric Sandall + + * ChangeLog, freeglut.lsm: freeglut.lsm:3 Removed 'beta' label for next + release, thanks to Bernhard Kaindl. + +2003-07-21 Christopher John Purnell + + * src/Makefile.am: The version info had the revision and the age + transposed. + +2003-07-21 Eric Sandall + + * ChangeLog, src/Makefile.am: src/Makefile.am:38 Changed versioning to + 11:0:8 thanks to Bernhard Kaindl + +2003-07-17 Eric Sandall + + * ChangeLog, freeglut.dsp, freeglut_static.dsp: Applied John F. Fay's + fixes to freeglut.dsp and freeglut_static.dsp + * ChangeLog, src/freeglut_state.c: Changed the overlay + (freeglut_state.c:662) to return FALSE, as it's not imp lemented yet + +2003-07-12 Andreas Umbach + + * src/Makefile.am: renamed freeglut library to glut, bumped version info + to 3:8:0 + * configure.in: bumped version number to 2.0.0 + * Makefile.am, configure.in, doc/Makefile.am, include/GL/Makefile.am, + progs/Makefile.am, progs/demos/Fractals/Makefile.am, + progs/demos/Fractals_random/Makefile.am, + progs/demos/Lorenz/Makefile.am, progs/demos/Makefile.am, + progs/demos/One/Makefile.am, src/Makefile.am: changes for make dist + * freeglut13.plg: MSVC generated file + +2003-07-11 Christopher John Purnell + + * include/GL/glut.h, src/freeglut_font.c: Fix for the font binary + compatibility problem. + +2003-07-10 Christopher John Purnell + + * src/Makefile.am: Changed to build libfreeglut.so.2.0.0 + +2003-07-10 James Jones + + * TODO, freeglut.dsp, freeglut_static.dsp: Changes to TODO, Windows + files - from John Fay + * progs/demos/Fractals_random/Fractals_random.dsp: Changes by John Fay + * progs/demos/Fractals/Fractals.dsp, progs/demos/Fractals/fractals.c: + Changes to the Fractals demo by John Fay + * progs/demos/One/one.dsp: Initial project file from John Fay + * progs/demos/Lorenz/lorenz.c, progs/demos/Lorenz/lorenz.dsp: + Modifications from John Fay + +2003-07-07 Christopher John Purnell + + * src/freeglut_main.c: glutMainLoopEvent() was not closing windows + properly. Moved call to fgCloseWindows() from glutMainLoop() to the + end of glutMainLoopEvent(). + +2003-07-03 Eric Sandall + + * ChangeLog, src/freeglut_misc.c: Removed unused char *ptr from + freeglut_misc.c + +2003-07-02 Christopher John Purnell + + * src/freeglut_main.c: It was crashing on and event for a unknown + window. + +2003-07-02 Brian Paul + + * src/freeglut_misc.c: rewrite of glutExtensionSupported - works + correctly now + +2003-07-02 Eric Sandall + + * ChangeLog: * Removed tests directory + * ChangeLog, Makefile.am, configure.in, progs/demos/One, + progs/demos/One/Makefile.am, progs/demos/One/one.c, tests: * Removed + genfonts/genstrokes code, updated configure.in and Makefile.in + + * Moved tests/one.c into progs/demos/One/one.c, updated configure.in + and Makefile.in + * genfonts: Removed genfonts + +2003-07-02 Christopher John Purnell + + * genfonts/to_stroke.y: Added some semicolons that yacc was warning + about. + +2003-07-01 James Jones + + * AUTHORS: John Fay commanded me to add my name to the file. He's crazy, + but that's okay. + +2003-07-01 Eric Sandall + + * ChangeLog, src/freeglut_misc.c: Fixed the 'ptr + len' problem in + freeglut_misc.c:90 + +2003-07-01 Brian Paul + + * doc/freeglut_user_interface.html: version bumps + * tests/Makefile.am: bump version to 2.0 + * src/Makefile.am, src/freeglutdll.def: bump versions to 2.0 + * src/freeglut_gamemode.c: xf86VidMode error checking (Andrew + Lentvorski) + +2003-06-30 Brian Paul + + * progs/demos/Lorenz, progs/demos/Lorenz/lorenz.c, + progs/demos/Lorenz/lorenz.dsp: Lorenz attractor demo (John Fay) + * freeglut.dsp, freeglut_static.dsp: updates from John Fay + +2003-06-28 Eric Sandall + + * ChangeLog, include/GL/Makefile.am: Now installs freeglut_ext.h and + glut.h to /usr/include/GL (was missing before) + +2003-06-27 Brian Paul + + * include/GL/freeglut_ext.h, src/freeglut_init.c, + src/freeglut_internal.h, src/freeglut_main.c, src/freeglut_state.c, + src/freeglut_stroke_mono_roman.c: XF86 game mode fixes, context + sharing option. (John Fay) + +2003-06-25 Eric Sandall + + * ChangeLog: Added another of my changes (freeglut.kdevelop) and fixed + the version number for my MS VS change (*.dsp) + +2003-06-25 Brian Paul + + * src/freeglut_internal.h: version bumps + * freeglut.lsm, include/GL/glut.h, src/freeglut_stroke_mono_roman.c, + src/freeglut_stroke_roman.c: Assorted version 2.0.0 updates (John + Fay). + * doc/freeglut_user_interface.html: updated version, italicize freeglut + (John Fay) + +2003-06-25 Eric Sandall + + * ChangeLog, freeglut.dsp, freeglut_static.dsp: Added 'freeglut_ext.c' + to the project files 'freeglut.dsp' and 'freeglut_static.dsp' (New + list #10) + +2003-06-24 Andreas Umbach + + * ChangeLog: Fixed autogen.sh and removed aclocal.m4 + * aclocal.m4: this file is autogenerated by aclocal + * autogen.sh: fixed aclocal / autoheader order; some cosmetics + +2003-06-24 Eric Sandall + + * freeglut.kdevelop: Project file for Gideon (KDevelop 3.0) + +2003-06-23 Eric Sandall + + * ChangeLog, Makefile.am, TODO, configure.in, freeglut.dsp, + freeglut.kdevprj, freeglut13.dsp, freeglut13.plg, freeglut_static.dsp, + freeglutdll.dsp, src, src/Makefile.am, src/freeglut_callbacks.c, + src/freeglut_cursor.c, src/freeglut_display.c, src/freeglut_ext.c, + src/freeglut_font.c, src/freeglut_font_data.c, + src/freeglut_gamemode.c, src/freeglut_geometry.c, src/freeglut_init.c, + src/freeglut_internal.h, src/freeglut_joystick.c, src/freeglut_main.c, + src/freeglut_menu.c, src/freeglut_misc.c, src/freeglut_overlay.c, + src/freeglut_state.c, src/freeglut_stroke_mono_roman.c, + src/freeglut_stroke_roman.c, src/freeglut_structure.c, + src/freeglut_teapot.c, src/freeglut_videoresize.c, + src/freeglut_window.c, src/freeglutdll.def, src/templates, + src/templates/cpp_template, src/templates/header_template, + tests/Makefile.am: Changed all references to the 'freeglut-1.3' + directory to 'src', copied 'freeglut-1.3' to 'src' and added all files + from 'src' to the repository (TODO #34). + * ChangeLog: Updated ChangeLog with my aclocal.m4 change + * aclocal.m4: Updated aclocal.m4 with aclocal 1.7.3 (was created with + aclocal 1.5) + +2003-06-23 Brian Paul + + * freeglut-1.3/freeglut_geometry.c: adjusted precision (John Fay) + * doc/freeglut_user_interface.html, freeglut-1.3/freeglut_display.c, + freeglut-1.3/freeglut_gamemode.c, freeglut-1.3/freeglut_geometry.c, + freeglut-1.3/freeglut_teapot.c, include/GL/freeglut_ext.h, + include/GL/glut.h: Assorted updates from John Fay. + +2003-06-20 Eric Sandall + + * TODO: Updated TODO from John Fay + +2003-06-20 Brian Paul + + * progs, progs/demos, progs/demos/Fractals, + progs/demos/Fractals/Fractals.dsp, progs/demos/Fractals/fractals.c, + progs/demos/Fractals/fractals.dat, progs/demos/Fractals_random, + progs/demos/Fractals_random/Fractals_random.dsp, + progs/demos/Fractals_random/fractals.dat, + progs/demos/Fractals_random/fractals_random.c: Fractal demo (John Fay) + +2003-06-20 Eric Sandall + + * ChangeLog: Added the autogen.sh addition to ChangeLog + * autogen.sh: Initial version of autogen.sh, tested here and creates the + correct files + +2003-06-20 Brian Paul + + * freeglut-1.3/freeglut_gamemode.c, freeglut-1.3/freeglut_state.c: + Windows patches (Eero Pajarre) + * NEWS: list the 1.4 release (fill in date) - this is a cvs check-in + test + +2003-06-19 Don Heyse + + * freeglut-1.3/freeglut_joystick.c: Oops, missed the + fghJoystickRawRead() fix for FreeBSD. + +2003-06-19 Brian Paul + + * doc/freeglut_user_interface.html, freeglut-1.3/freeglut_display.c, + freeglut-1.3/freeglut_ext.c, freeglut-1.3/freeglut_internal.h, + freeglut-1.3/freeglut_main.c: s/FreeGLUT/freeglut/ + +2003-06-19 Don Heyse + + * freeglut-1.3/freeglut_joystick.c: Applied tthierry's patch to fix + compiling on FreeBSD. + +2003-06-19 Brian Paul + + * freeglut-1.3/freeglut_internal.h: added VERSION_MAJOR/MINOR/PATCH + * doc/freeglut_user_interface.html: restore text lost from previous + check-in + * include/GL/glut.h: s/FREEGLUT_VERSION_1_3/FREEGLUT_VERSION_1_4/ + +2003-06-19 Eric Sandall + + * include/GL/freeglut_ext.h, include/GL/glut.h: GLUT_VERSION updates + from John Fay + +2003-06-18 Eric Sandall + + * AUTHORS: Forgot a file...looked so innocous just sitting there... :) + * ChangeLog, doc/freeglut_user_interface.html, + freeglut-1.3/freeglut_callbacks.c, freeglut-1.3/freeglut_ext.c, + freeglut-1.3/freeglut_internal.h, freeglut-1.3/freeglut_menu.c, + freeglut-1.3/freeglut_structure.c, freeglut-1.3/freeglut_teapot.c, + freeglut-1.3/freeglut_window.c, include/GL/freeglut_ext.h: * Hopefully + I did THIS one right (used 'cvs update' to Merge) + + Authors - The first update in quite a while + + ChangeLog - Added the recent changes + + freeglut_callbacks.c - Added Aleksandar Donev's menu destruction + callback + + freeglut_internal.h - Added the user data to the structures and made + the menu state/status callbacks window-independent + + freeglut_menu.c - Removed several OpenGL compiler warnings and added + A. Donev's menu user data functions + + freeglut_structure.c - Added Aleksandar Donev's menu destruction + callback + + freeglut_teapot.c - Removed or suppressed several compiler warnings + + freeglut_window.c - Updated the window positioning code and added A. + Donev's window user data + + freeglut_ext.h - Added the menu destruction callback and user data + functions + * freeglut-1.3/freeglut_ext.h: * Removed freeglut_ext.h (wasn't supposed + to be added) + +2003-06-18 Brian Paul + + * doc/freeglut_user_interface.html, freeglut-1.3/freeglut_internal.h, + freeglut-1.3/freeglut_state.c, include/GL/freeglut_ext.h, + include/GL/glut.h: Added FREEGLUT_VERSION_1_3. Added GLUT_VERSION for + glutGet(). Added glutGet() documentation. + * freeglut-1.3/freeglut_display.c, freeglut-1.3/freeglut_ext.h, + freeglut-1.3/freeglut_init.c, freeglut-1.3/freeglut_internal.h, + freeglut-1.3/freeglut_main.c, freeglut-1.3/freeglut_state.c, + freeglut-1.3/freeglut_structure.c, freeglut-1.3/freeglut_window.c: + remove DOS-style CR characters + * doc/freeglut_user_interface.html: added glutGetProcAddress and + GLUT_FPS info + * ChangeLog: added glutGetProcAddress() and GLUT_FPS + +2003-06-17 Brian Paul + + * freeglut-1.3/freeglut_display.c, freeglut-1.3/freeglut_init.c, + freeglut-1.3/freeglut_internal.h: restore GLUT_FPS env var feature + lost in previous check-in + +2003-06-17 Eric Sandall + + * ChangeLog: * Updated ChangeLog + * freeglut-1.3/freeglut_main.c, freeglut-1.3/freeglut_structure.c: Set + #4: * Fixes a couple of compiler warnings and other bugs. * + freeglut_main.c: Removes a compiler warning * freeglut_structure.c: + Sets the current window before calling the window closure callback * + Possibly other changes + * freeglut-1.3/freeglut_ext.h: * Rest of Set #3 + * freeglut-1.3/freeglut_state.c: Set #3: Fixes for window positioning + problem Windows + * freeglut-1.3/freeglut_init.c: Eero Pajarre's GLUT_ICON code for + Windows + * freeglut-1.3/freeglut_display.c, freeglut-1.3/freeglut_internal.h, + freeglut-1.3/freeglut_window.c: First group of patches: Adds + single-buffered rendering (or its emulation) in Windows. + +2003-06-17 Brian Paul + + * freeglut-1.3/freeglut_display.c, freeglut-1.3/freeglut_init.c, + freeglut-1.3/freeglut_internal.h: added GLUT_FPS env var option + * freeglut-1.3/Makefile.am, freeglut-1.3/freeglut_ext.c, + include/GL/freeglut_ext.h: added glutGetProcAddress() + +2003-06-12 Don Heyse + + * freeglut-1.3/freeglut_main.c: Fix the keyboard up callback and a + compiler warning. + * freeglut-1.3/freeglut_structure.c: Set the current window before + calling the window closure callback. + * freeglut-1.3/freeglut_state.c, include/GL/freeglut_ext.h: John's + window positioning corrections. + * freeglut-1.3/freeglut_init.c: Eero Pajarre's icon code. + * freeglut-1.3/freeglut_display.c, freeglut-1.3/freeglut_internal.h, + freeglut-1.3/freeglut_window.c: Single buffered rendering for Windows. + +2003-06-02 Don Heyse + + * doc/freeglut_user_interface.html: John Documented InitWindowPosition + extensions and added some kbd fn info. + * ChangeLog: Documented Johns changes from May 03. + * freeglut-1.3/freeglut_state.c: Do not allow glutGet to reposition the + window 1 pixel toward bottom right. + * freeglut-1.3/freeglut_main.c: Pass mouse pos to Windows kbd callback. + Resequenced a few things for UNIX. + +2003-03-23 Christopher John Purnell + + * freeglut-1.3/freeglut_gamemode.c: Applied patch to fix GameMode issues + supplied by Bernhard Kaindl. + +2003-03-12 Don Heyse + + * include/GL/glut.h: Switch to ANSI C comments. + * freeglut-1.3/freeglut_cursor.c, freeglut-1.3/freeglut_display.c, + freeglut-1.3/freeglut_font.c, freeglut-1.3/freeglut_geometry.c, + freeglut-1.3/freeglut_internal.h, freeglut-1.3/freeglut_joystick.c, + freeglut-1.3/freeglut_main.c, freeglut-1.3/freeglut_structure.c, + freeglut-1.3/freeglut_window.c: Switch to ANSI C comments. Removed + always true tests on unsigned char. Single buffering fix.. + +2003-02-13 Don Heyse + + * freeglut.dsp, freeglut.dsw, freeglut_static.dsp: Switching to John + Fays version of the VC++ project files. + +2003-02-08 Steve Baker + + * freeglut-1.3/freeglut_display.c, freeglut-1.3/freeglut_joystick.c: + Removed erroneous GPL license comments. + +2003-02-07 Don Heyse + + * freeglut-1.3/freeglut_callbacks.c, freeglut-1.3/freeglut_cursor.c, + freeglut-1.3/freeglut_display.c, freeglut-1.3/freeglut_font_data.c, + freeglut-1.3/freeglut_gamemode.c, freeglut-1.3/freeglut_geometry.c, + freeglut-1.3/freeglut_init.c, freeglut-1.3/freeglut_joystick.c, + freeglut-1.3/freeglut_misc.c, freeglut-1.3/freeglut_overlay.c, + freeglut-1.3/freeglut_stroke_mono_roman.c, + freeglut-1.3/freeglut_stroke_roman.c, freeglut-1.3/freeglut_teapot.c, + freeglut-1.3/freeglut_videoresize.c: Moved freeglut_internal.h to the + freeglut source code private directory. + * freeglut-1.3/freeglut_structure.c: SubWindow border thickness fix. + Overlay changes in glutGet. + * freeglut-1.3/freeglut_main.c, freeglut-1.3/freeglut_menu.c, + freeglut-1.3/freeglut_state.c, freeglut-1.3/freeglut_window.c: Johns + changes for layers, fgSetWindow, and fgSetupPixelFormat. + * freeglut-1.3/freeglut_font.c: John fixed a bug that make bitmap font + one pixel wider than its drawn. + * freeglut-1.3/freeglut_internal.h, include/GL/freeglut_internal.h: + Moved freeglut_internal.h to the private directory with the other + freeglut sources. + * include/GL/freeglut.h, include/GL/freeglut_ext.h, include/GL/glut.h: + Broke freeglut.h into glut.h and freeglut_ext.h + +2003-01-06 Don Heyse + + * freeglut-1.3/freeglutdll.def: Exports file for Win32 dll. One EXPORT + for each FGAPI line in freeglut.h + +2003-01-04 Steve Baker + + * aclocal.m4, freeglut-1.3/freeglut_joystick.c: Cleanup joystick + deallocation. + +2002-12-10 Don Heyse + + * freeglut.dsw, freeglutdll.dsp: Allow DLL and static library build on + Windows. + * include/GL/freeglut.h: Added check for FREEGLUT_DLL to allow static & + DLL build on Windows. + +2002-12-04 Don Heyse + + * freeglut-1.3/freeglut_font_data.c: More bitmap font spacing fixes from + John. + +2002-11-29 Don Heyse + + * freeglut-1.3/freeglut_init.c: Fixed Win95 crash when getenv("DISPLAY") + returned NULL ptr. + * freeglut-1.3/freeglut_font_data.c: The lowercase t in helvetica12 was + too skinny. + * freeglut-1.3/freeglut_font.c, freeglut-1.3/freeglut_font_data.c: + Adjusted character spacing on a few fonts. + * ChangeLog: Many updates from John Fay. + * freeglutstatic.dsw: Added Visual C++ 6 Static library project for John + Fay. + +2002-11-28 Don Heyse + + * freeglut.dsp: Visual C++ 6 project file for static freeglut lib. + * include/GL/freeglut.h, include/GL/freeglut_internal.h: Many updates + from John Fay. (freeglut.h may need a small change to allow Win32 DLL + build again) + * freeglut-1.3/freeglut_geometry.c: Many updates from John Fay. + * freeglut-1.3/freeglut_callbacks.c, freeglut-1.3/freeglut_cursor.c, + freeglut-1.3/freeglut_font.c, freeglut-1.3/freeglut_font_data.c, + freeglut-1.3/freeglut_gamemode.c, freeglut-1.3/freeglut_init.c, + freeglut-1.3/freeglut_main.c, freeglut-1.3/freeglut_menu.c, + freeglut-1.3/freeglut_misc.c, freeglut-1.3/freeglut_state.c, + freeglut-1.3/freeglut_stroke_mono_roman.c, + freeglut-1.3/freeglut_stroke_roman.c, + freeglut-1.3/freeglut_structure.c, freeglut-1.3/freeglut_window.c: + Many updates from John Fay. + * freeglut-1.3/freeglut_joystick.c: Fixes from freeglut_portable patch. + Memory leak fix from John. Return_if_fail fix. + +2002-11-26 Don Heyse + + * doc/freeglut_user_interface.html: Added on behalf of John Fay. + +2002-10-22 Don Heyse + + * freeglut-1.3/freeglut_geometry.c: Implemented tetrahedra, octahedra, + dodecahedra, and icosahedra. Checked in on behalf of John F. Fay + . + +2002-05-20 Don Heyse + + * freeglut-1.3/freeglut_font.c: Fixed previous fix so it compiles. + +2002-05-20 Christopher John Purnell + + * freeglut-1.3/freeglut_font.c: My bad. + +2002-05-18 Christopher John Purnell + + * freeglut-1.3/Makefile.am, freeglut-1.3/freeglut_font.c, + freeglut-1.3/freeglut_stroke_mono_roman.c, + freeglut-1.3/freeglut_stroke_roman.c, genfonts/Roman_M.src, + genfonts/lex.l, genfonts/to_stroke.y, genfonts/wfont.h, + include/GL/freeglut.h, include/GL/freeglut_internal.h: Added stroke + fonts. + +2002-05-17 Christopher John Purnell + + * freeglut-1.3/freeglut_cursor.c, freeglut-1.3/freeglut_display.c, + freeglut-1.3/freeglut_overlay.c, freeglut-1.3/freeglut_teapot.c, + freeglut-1.3/freeglut_videoresize.c, tests/one.c: Removed some DOS + line ends. + +2002-05-16 Christopher John Purnell + + * freeglut-1.3/freeglut_main.c: Removed one last glib call. + +2002-01-20 Steve Baker + + * README, freeglut-1.3/.deps/freeglut_callbacks.P, + freeglut-1.3/.deps/freeglut_cursor.P, + freeglut-1.3/.deps/freeglut_display.P, + freeglut-1.3/.deps/freeglut_font.P, + freeglut-1.3/.deps/freeglut_font_data.P, + freeglut-1.3/.deps/freeglut_gamemode.P, + freeglut-1.3/.deps/freeglut_geometry.P, + freeglut-1.3/.deps/freeglut_init.P, + freeglut-1.3/.deps/freeglut_joystick.P, + freeglut-1.3/.deps/freeglut_main.P, + freeglut-1.3/.deps/freeglut_menu.P, + freeglut-1.3/.deps/freeglut_misc.P, + freeglut-1.3/.deps/freeglut_overlay.P, + freeglut-1.3/.deps/freeglut_state.P, + freeglut-1.3/.deps/freeglut_structure.P, + freeglut-1.3/.deps/freeglut_teapot.P: Removed a bunch of '.P' files + that don't belong in the CVS archive. + +2001-08-05 Christopher John Purnell + + * freeglut-1.3/freeglut_callbacks.c, freeglut-1.3/freeglut_main.c, + freeglut-1.3/freeglut_window.c, include/GL/freeglut_internal.h: Added + keyup events code. Added missing specal keys. Made menu callbacks + global. + * freeglut-1.3/freeglut_window.c: More position tweeks. + +2001-08-04 Christopher John Purnell + + * freeglut-1.3/freeglut_main.c, include/GL/freeglut.h: Fixed redisplay + bug. Fixed modifier values. + * freeglut-1.3/freeglut_window.c: Improved window positioning. + +2001-07-30 Christopher John Purnell + + * freeglut-1.3/freeglut_main.c, freeglut-1.3/freeglut_structure.c: A + stupid bug fixed. + +2001-07-30 Andreas Umbach + + * freeglut-1.3/freeglut_init.c, freeglut-1.3/freeglut_main.c: one more + g_assert removed + * include/GL/freeglut_internal.h: removed glib dependencies from win32 + * freeglut-1.3/freeglut_gamemode.c, freeglut-1.3/freeglut_init.c, + freeglut-1.3/freeglut_main.c, freeglut-1.3/freeglut_window.c: - + removed glib dependencies from win32 code + +2001-07-29 Christopher John Purnell + + * freeglut-1.3/freeglut_structure.c: Fixed bug list code. + * freeglut-1.3/Makefile.am, freeglut-1.3/freeglut_callbacks.c, + freeglut-1.3/freeglut_font.c, freeglut-1.3/freeglut_font_data.c, + freeglut-1.3/freeglut_gamemode.c, freeglut-1.3/freeglut_geometry.c, + freeglut-1.3/freeglut_init.c, freeglut-1.3/freeglut_joystick.c, + freeglut-1.3/freeglut_main.c, freeglut-1.3/freeglut_menu.c, + freeglut-1.3/freeglut_misc.c, freeglut-1.3/freeglut_state.c, + freeglut-1.3/freeglut_structure.c, freeglut-1.3/freeglut_window.c, + genfonts/Makefile.am, genfonts/genfonts.c, genfonts/genstroke.c, + include/GL/freeglut.h, include/GL/freeglut_internal.h: Removed glib + dependency + * configure.in, freeglut-1.3/Makefile.am, genfonts/Makefile.am: The + build system now looks for X. + +2001-07-27 Steve Baker + + * doc, doc/download.html, doc/freeglut.html, doc/freeglut_logo.png, + doc/index.html, doc/ogl_sm.png, doc/progress.html, doc/structure.html: + Added documents. + * genfonts/.deps, tests/.deps: Removed some more files that don't belong + in CVS + * configure, freeglut-1.3/Makefile, freeglut-1.3/Makefile.in, + genfonts/Makefile, genfonts/Makefile.in, include/GL/Makefile, + include/GL/Makefile.in, include/Makefile, include/Makefile.in, + tests/Makefile, tests/Makefile.in: Removed files checked in in error. + * freeglut-1.3/.deps, freeglut-1.3/.deps/freeglut_callbacks.P, + freeglut-1.3/.deps/freeglut_cursor.P, + freeglut-1.3/.deps/freeglut_display.P, + freeglut-1.3/.deps/freeglut_font.P, + freeglut-1.3/.deps/freeglut_font_data.P, + freeglut-1.3/.deps/freeglut_gamemode.P, + freeglut-1.3/.deps/freeglut_geometry.P, + freeglut-1.3/.deps/freeglut_init.P, + freeglut-1.3/.deps/freeglut_joystick.P, + freeglut-1.3/.deps/freeglut_main.P, + freeglut-1.3/.deps/freeglut_menu.P, + freeglut-1.3/.deps/freeglut_misc.P, + freeglut-1.3/.deps/freeglut_overlay.P, + freeglut-1.3/.deps/freeglut_state.P, + freeglut-1.3/.deps/freeglut_structure.P, + freeglut-1.3/.deps/freeglut_teapot.P, + freeglut-1.3/.deps/freeglut_videoresize.P, + freeglut-1.3/.deps/freeglut_window.P, freeglut-1.3/Makefile, + freeglut-1.3/Makefile.in: Initial revision + * ., AUTHORS, COPYING, ChangeLog, INSTALL, Makefile.am, NEWS, README, + TODO, acconfig.h, aclocal.m4, configure, configure.in, freeglut-1.3, + freeglut-1.3/Makefile.am, freeglut-1.3/freeglut_callbacks.c, + freeglut-1.3/freeglut_cursor.c, freeglut-1.3/freeglut_display.c, + freeglut-1.3/freeglut_font.c, freeglut-1.3/freeglut_font_data.c, + freeglut-1.3/freeglut_gamemode.c, freeglut-1.3/freeglut_geometry.c, + freeglut-1.3/freeglut_init.c, freeglut-1.3/freeglut_joystick.c, + freeglut-1.3/freeglut_main.c, freeglut-1.3/freeglut_menu.c, + freeglut-1.3/freeglut_misc.c, freeglut-1.3/freeglut_overlay.c, + freeglut-1.3/freeglut_state.c, freeglut-1.3/freeglut_structure.c, + freeglut-1.3/freeglut_teapot.c, freeglut-1.3/freeglut_videoresize.c, + freeglut-1.3/freeglut_window.c, freeglut-1.3/templates, + freeglut-1.3/templates/cpp_template, + freeglut-1.3/templates/header_template, freeglut.dsw, + freeglut.kdevprj, freeglut.lsm, freeglut13.dsp, freeglut13.plg, + genfonts, genfonts/.deps, genfonts/.deps/genfonts.P, + genfonts/.deps/genstroke.P, genfonts/Makefile, genfonts/Makefile.am, + genfonts/Makefile.in, genfonts/Roman.src, genfonts/Roman_M.src, + genfonts/genfonts.c, genfonts/genstroke.c, include, include/GL, + include/GL/Makefile, include/GL/Makefile.am, include/GL/Makefile.in, + include/GL/freeglut.h, include/GL/freeglut_internal.h, + include/Makefile, include/Makefile.am, include/Makefile.in, + install-sh, mkinstalldirs, stamp-h, stamp-h.in, tests, tests/.deps, + tests/.deps/one.P, tests/Makefile, tests/Makefile.am, + tests/Makefile.in, tests/one.c: Initial revision + diff --git a/FreeGLUTConfig.cmake.in b/FreeGLUTConfig.cmake.in new file mode 100644 index 0000000..ac36b6c --- /dev/null +++ b/FreeGLUTConfig.cmake.in @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/FreeGLUTTargets.cmake") diff --git a/README.android b/README.android new file mode 100644 index 0000000..439f85d --- /dev/null +++ b/README.android @@ -0,0 +1,3 @@ + + See http://freeglut.sourceforge.net/docs/android.php + diff --git a/README.blackberry b/README.blackberry new file mode 100644 index 0000000..7e0eaa4 --- /dev/null +++ b/README.blackberry @@ -0,0 +1,23 @@ +# ------------------------------------------------------------------------------ +# BlackBerry CMake toolchain file, for use with the BlackBerry 10 NDK +# Requires cmake 2.6.3 or newer (2.8.3 or newer is recommended). +# +# Usage Linux: +# $ source /absolute/path/to/the/bbndk/bbndk-env.sh +# $ mkdir build +# $ cd build +# $ cmake .. -DCMAKE_TOOLCHAIN_FILE="../blackberry.toolchain.cmake" -DBLACKBERRY_ARCHITECTURE=arm -DFREEGLUT_GLES=ON -DFREEGLUT_BUILD_DEMOS=NO -DCMAKE_VERBOSE_MAKEFILE=TRUE -G "Eclipse CDT4 - Unix Makefiles" +# $ make -j8 +# +# Usage Mac: +# Same as the steps on Linux +# +# Usage Windows: +# > /absolute/path/to/the/bbndk/bbndk-env.bat +# > mkdir build +# > cd build +# > cmake .. -DCMAKE_TOOLCHAIN_FILE="../blackberry.toolchain.cmake" -DBLACKBERRY_ARCHITECTURE=arm -DFREEGLUT_GLES=ON -DFREEGLUT_BUILD_DEMOS=NO -DCMAKE_VERBOSE_MAKEFILE=TRUE -G "Eclipse CDT4 - Unix Makefiles" +# > make -j8 +# + +To change which version of OpenGL to use, call glutInitContextVersion(1, 0) for OpenGL ES 1.x, glutInitContextVersion(2, 0) for OpenGL ES 2.0, or glutInitContextVersion(3, 0) for OpenGL ES 3.0. \ No newline at end of file diff --git a/README.cmake b/README.cmake new file mode 100644 index 0000000..4b3962d --- /dev/null +++ b/README.cmake @@ -0,0 +1,80 @@ +How to build freeglut with CMake on Windows (MS Visual Studio) +-------------------------------------------------------------- +1. Download CMake (http://www.cmake.org/cmake/resources/software.html). + Get one of the releases from the binary distribution section. +2. Run the CMake installer, install wherever you like. +3. Launch CMake via Start > Program Files > CMake 2.8 > CMake (GUI) + (note that the shortcut put by the installer on your desktop does NOT + point to the CMake GUI program!) +4. In the "Where is the source code" box, type or browse to the root + directory of your freeglut source (so that's /freeglut, not + /freeglut/src). +5. In the "Where to build the binaries" box, type or browse to any + folder you like - this will be where the Visual Studio solution will be + generated. This folder does not have to exist yet. +6. Hit the Configure button near the bottom of the window. +7. Pick your target compiler, make sure that its installed on your + system of course! +8. Answer Ok when asked if you want to create the build directory. +9. Wait for the configure process to finish. +10. The screen will now have some configuration options on it, for + instance specifying whether you want to build static and/or shared + libraries (see below for a complete list). When you've selected your + options, click the Configure button again. +11. The Generate button at the bottom will now be enabled. Click Generate. +12. The build files will now be generated in the location you picked. + +You can now navigate to the build directory you specified in step 5. +Open the freeglut.sln file that was generated in your build directory, +and compile as usual + + +How to build freeglut on UNIX +----------------------------- +- Make sure you have cmake installed. Examples: + - Debian/Ubuntu: apt-get install cmake + - Fedora: yum install cmake + - FreeBSD: cd /usr/ports/devel/cmake && make install + Or directly from their website: + http://www.cmake.org/cmake/resources/software.html +- Make sure you have the basics for compiling code, such as C compiler + (e.g., GCC) and the make package. +- Also make sure you have packages installed that provide the relevant + header files for opengl (e.g., libgl1-mesa-dev on Debian/Ubuntu) and + the chosen backend : + - X11: x11 (e.g., libx11-dev, libxrandr-devel on Debian/Ubuntu) and + XInput (libxi-dev / libXi-devel) + - Wayland: wayland (e.g., libwayland-dev and libegl1-mesa-dev on + Debian/Ubuntu) and xkbcommon (libxkbcommon-dev /libxkbcommon-devel) +- Run 'cmake .' (or 'cmake . -DFREEGLUT_WAYLAND=ON' for Wayland) in the + freeglut directory to generate the makefile. +- Run 'make' to build, and 'make install' to install freeglut. +- If you wish to change any build options run 'ccmake .' + + +Breakdown of CMake configuration options +---------------------------------------- +CMAKE_BUILD_TYPE [Empty, Debug, Release] Can be overriden by + passing it as a make variable during build. +CMAKE_INSTALL_PREFIX Installation prefix (e.g. /usr/local on UNIX) +FREEGLUT_BUILD_DEMOS [ON, OFF] Controls whether the demos are + built or not. +FREEGLUT_BUILD_SHARED_LIBS [ON, OFF] Build freeglut as a shared library +FREEGLUT_BUILD_STATIC_LIBS [ON, OFF] Build freeglut as a static library +FREEGLUT_GLES [ON, OFF] Link with GLEs libraries instead + of OpenGL +FREEGLUT_WAYLAND [ON, OFF] Link with Wayland libraries instead + of X11 +FREEGLUT_PRINT_ERRORS [ON, OFF] Controls whether errors are + default handled or not when user does not + provide an error callback +FREEGLUT_PRINT_WARNINGS [ON, OFF] Controls whether warnings are + default handled or not when user does not + provide an warning callback +FREEGLUT_REPLACE_GLUT [ON, OFF] For non-Windows platforms, + freeglut is by default built as -lglut. if + off, built as -lfreeglut. On Windows, + libraries are always built as freeglut. +INSTALL_PDB [ON, OFF] MSVC only: controls whether debug + information files are included with the + install or not diff --git a/README.cygwin_mingw b/README.cygwin_mingw new file mode 100644 index 0000000..2830d71 --- /dev/null +++ b/README.cygwin_mingw @@ -0,0 +1,209 @@ +Glut then! + +By Jean-Seb on Friday July 10, 2009, 00:18 +Translated by Babelfish with a scrub from John F. Fay. For points of confusion +please refer to the original French version. + +Freeglut is an open-source evolution of GLUT. +Under Windows, one can use it with Cygwin. +Easy? Yes, if one agrees to distribute "cygwin1.dll". +Let us help freeglut gain its independence ! +Update 10/7/2009: generation of a library for linking without the DLL. + + +Grabbing the sources + + * Download the sources for version 2.6.0 which integrates recent changes. + * Using version 2.6 is better than the 2.4-stable branch because many + bugs have been corrected. + * You will find the sources on the site of Freeglut: + o http://freeglut.sourceforge.net/ + + +Goals + + * We will create a DLL for Cygwin, and an independent static library + * We will also create a dynamic library, allowing linking with the DLL. + + +List of generated files + + * freeglut.dll: a traditional DLL for the dynamic linkage. + * libfreeglut.a: the static library. The final program is autonomous (at + least for OpenGL). + * libfreeglutdll.a: the dynamic library. The final program needs + freeglut.dll. + + +Preparation + + * Extract the files from the freeglut archive. + * Go in the directory src (located at the root of the Freeglut directory), + and create a "Gl" sub-directory + o In this sub-directory, copy the files of the directory "include/Gl" + + * Why is it necessary to create a "Gl" directory for compilation? + o I needed it to simplify things during my tests. + o If not you can create the repertories directly, and copy the files + as indicated in the point installation (see below). + + * Do a little housekeeping in /lib: + o Erase all the references to the glut, so as not to conflict with the + linking. + o This stage is optional, you can also choose to do the housekeeping + only after a successful compilation of Freeglut. + o In your enthusiasm to clean things up, be careful not to erase the + library glu32.lib (not to be confused with glut32.lib). + + +Compilation + + * Forget the "./configure, make, make install" triptych. + o It does not go at all with Cygwin. + + * Here Makefile which will make the deal: + +#Makefile for Freeglut 2.6.0-rc and Cygwin +#To place in the directory 'src/Common' + +sources=$ (wildcard *.c) +objs=$ (sources: .c=.o) +libname=freeglut + + +CFLAGS=-O2 - DTARGET_HOST_MS_WINDOWS - DX_DISPLAY_MISSING - DFREEGLUT_STATIC - I./ +LDFLAGS=-lopengl32 - lgdi32 - lwinmm + +nocyg=-mno-cygwin - mwindows + +all: $ (objs) + #construction DLL related to cygwin1.dll + gcc $(nocyg) $(objs) -shared $(LDFLAGS) -o $(libname).dll + nm $(libname).dll | awk 'BEGIN { print "EXPORTS" } /T _glut/ {sub( /^.*T _/, "\t"); print}' > $(libname).def + dlltool --dllname $(libname).dll --input-def $(libname).def --output-lib lib$(libname)dll.a + + #construction static library independent of cygwin + ar cr lib$(libname).a $(objs) + #pas inevitably obligatory (creation of an index to accelerate the accesses) + ranlib lib$(libname).a + +%.o: %.c + gcc $(nocyg) -c $(CFLAGS) $< + +clean: + rm -f *.o $(libname).dll $(libname).def lib$(libname)dll.a lib$(libname).a + + + + +Some remarks on the Makefile + + * This makefile creates a DLL, a static library (a file, in other words) and + the dynamic library which will allow the use of the DLL. + + * Do not try to strip the static library! You may not be able to compile + applications with static library any more. + o On the other hand, you can strip the final executable obtained after + compiling your application. + + * I chose to call the DLL and the libraries by their "true names": + freeglut.dll libfreeglutdll.a and libfreeglut.a. + o Script configures recreated (for reasons of compatibility with the + old GLUT library) glut.dll and libglut.a. + o During the my tests, I had conflicts with an authentic "glut" which + trailed in my "/lib". I decided to call the things by their name, in + order to avoid confusions. + o Nothing prevents you from renaming the DLL, if you need to use GLUT + programs which you cannot recompile. + + * The dynamic library is generated starting from the DLL. + o For reasons of brevity, I used awk. It generates the export file + used by dlltool. + o The only notable thing is the selection of the functions whose name + starts with _glut, in order to avoid including in the dynamic + library the functions that are not related to freeglut. + o then, one uses dlltool in a very traditional way. + +nm $(libname).dll | awk 'BEGIN { print "EXPORTS" } /T _glut/ {sub( /^.*T _/, "\t"); print}' > $(libname).def +dlltool --dllname $(libname).dll --input-def $(libname).def --output-lib lib$(libname)dll.a + + + + +Installation + + * Copy libfreeglut.a, libfreeglutdll.a into the Cygwin directory /lib. + * Copy freglut.dll in the system32 of Windows (this is practical, but not + clean!). + * Copy the files headers of Freeglut (/include/gl) into the Cygwin directory + /usr/include/Gl. + * Copy the files headers (always /include/gl) into /usr/include/mingw/Gl: + this is used for compilations with the flag - mno-cygwin, which uses the + includes in mingw. + o You may need to erase the old GLUT include files if you installed it + with Cygwin. + + +Use of the library + + * We will test with the program shapes, found in progs/demonstrations/shapes + o -mno-cygwin is used to force the use of Mingw without the large + dependence cygwin1.dll. + o -mwindows is only used to remove the horrible Shell window (very + useful for the settling, on the other hand). + o -L. (note the period after the "L"): I left libfreeglut.a, + libfreeglutdll.a and freeglut.dll in the test directory, at the time + of the tests. + + +Compilation of the static freeglut library, without cygwin + + * All the simplicity lies in the define: -DFREEGLUT_STATIC + o It serves to obtain good decoration of the function names in the + imports of the lib Freeglut. + o You can test without and use a hex editor to see the differences + in the objects. + * attention with the order of the libraries: -lfreeglut (static) must be + before the declaration of the dynamic libraries. + + * gcc shapes.c -L. -lfreeglut -lopengl32 -lwinmm -lgdi32 -mno-cygwin -mwindows -DFREEGLUT_STATIC + + +Compilation with DLL freeglut, without cygwin + + * For the define, see the notices above + * The order of the libraries is no longer important. + + * gcc shapes.c -L. -lopengl32 -lwinmm -lgdi32 -lfreeglut -mno-cygwin -DFREEGLUT_STATIC + + +Compilation with DLL freeglut, Cygwin + + * This example is given only for reference, the topic of this ticket being + to get rid of Cygwin. + o Let us say that can be used to make the point (and later). + + * gcc shapes.c -L. -lopengl32 -lwinmm -lgdi32 -lfreeglut + + + +Where are the dooooocs? + + * Freeglut is delivered with its documentation, more very up to date. + o It seems that there is a problem with the original GLUT + documentation. Not only it does not correspond completely to the + operation of Freeglut, but moreover, its author (Mark Kilgard) + copyrighted it. Its distribution is thus difficult. + + * Jocelyn Fréchot undertook a levelling of the docs for version 2.6.0. One can find them on his site for the moment: + o http://jocelyn.frechot.free.fr/freeglut/ + + +Something survived... + + * I also tested the recompiling of the demonstrations of the original lib + GLUT (peace with its ashes). + o Nothing in particular to be announced. + + * Thank you with all the courageous maintainers for Freeglut, that one + believed dead, but which still move. diff --git a/README.macosx b/README.macosx new file mode 100644 index 0000000..d7030f9 --- /dev/null +++ b/README.macosx @@ -0,0 +1,48 @@ +Freeglut on MacOS X +=================== + +Currently freeglut does not support the native Cocoa API and the OpenGL +framework which works with it, but rather relies on X11 (XQuartz) and the Mesa +OpenGL and GLX libraries. + +The simplest way to set up the prerequisites for building and using freeglut is +with the homebrew package management system: https://brew.sh + +Build instructions +------------------ + +Prerequisites: + - If you don't already have homebrew, go to https://brew.sh and follow their + instructions. + - If you don't already have a compiler toolchain installed, download the Xcode + commandline tools from the apple store and install them first. + - If you don't have XQuartz installed, get it from https://www.xquartz.org + - Use homebrew to install cmake, and all the necessary libraries: + `brew install cmake libx11 libxi libxrandr libxxf86vm pkg-config mesa` + +Build freeglut: + - Create a build directory under the freeglut directory and change into it: + `mkdir build && cd build` + - Run cmake to generate the makefile: + `cmake -DFREEGLUT_BUILD_DEMOS=OFF -DOPENGL_gl_LIBRARY=/usr/local/lib/libGL.dylib ..` + - Run `make` to build freeglut, and `make install` to install it. + +Usage +----- + +To use freeglut in your program **do not** include ``; that header +is part of Apple's GLUT framework. Use `#include ` instead as usual, +or `#include ` if you wish to take advantage of the extended +freeglut API. + +Similarly, to link with freeglut **do not** use `-framework GLUT` in your +linker command line. Instead use the standard `-lglut` argument, as you would +on any other UNIX system. + +Known issues +------------ + +Some versions of XQuartz do not map the option keys to ALT by default, making +it impossible to get the `GLUT_ACTIVE_ALT` bit set in the bitmask returned by +`glutGetModifiers`. To change this behavior go to the XQuartz preferences and +enable the "Option keys send Alt_L and Alt_R" checkbox in the "input" tab. diff --git a/README.md b/README.md new file mode 100644 index 0000000..8b2c66f --- /dev/null +++ b/README.md @@ -0,0 +1,97 @@ +freeglut +======== + +![GNU/Linux (X11) build status](https://github.com/FreeGLUTProject/freeglut/actions/workflows/build_gnulinux_x11.yml/badge.svg) +![Windows build status](https://github.com/FreeGLUTProject/freeglut/actions/workflows/build_win_msvc.yml/badge.svg) +![MacOS X (X11) build status](https://github.com/FreeGLUTProject/freeglut/actions/workflows/build_macosx_x11.yml/badge.svg) + +OVERVIEW +-------- + +Freeglut, the Free OpenGL Utility Toolkit, is meant to be a free alternative to +Mark Kilgard's GLUT library. Freeglut is free software, distributed under an +MIT/X11 style license. You are free to use, modify, and redistribute freeglut +with or without modifications (see COPYING for details). + +In short, freeglut can be used by OpenGL programs to perform those tasks which +would normally require platform-specific code. Tasks like creating a window, +creating an OpenGL context and binding it to the window, and processing input +events. Freeglut provides a concise and elegant API to handle those tasks, in a +platform-independent manner, keeping the application simple and portable. + +One of the main goals of freeglut, is maximum compatibility. Freeglut is both +source and binary-compatible with the original GLUT, and can be used as a +drop-in replacement for it. We take great care to maintain a stable API and ABI, +and to introduce any new features and improvements in a way which does not +compromise compatibility. + +Freeglut can be used with a wide range of OpenGL implementations, from the very +early OpenGL 1.0 on SGI computers, to the very latest modern OpenGL versions on +current GPUs. It can be used to create a classic OpenGL context, or a versioned +core profile or compatibility context. Freeglut can also be used with OpenGL ES, +on desktop or mobile devices. + + +PORTS +----- + +Currently supported platforms: + - UNIX systems with X11 or Wayland (such as GNU/Linux, FreeBSD, IRIX, etc) + - MS Windows + - macOS with XQuartz (no native Cocoa support yet) + - Android (NDK) + - BlackBerry + +Consult the platform-specific readme files for details on the level of support +and build instructions. + + +INSTALLATION +------------ + +Freeglut relies on cmake (minimum 3.0.0) to generate build files for all the +different supported platforms and toolchains. + +See [`README.cmake`](README.cmake) as a starting point, as well as the other `README` +files for further info. + +For those cases where using cmake is inconvenient, we also provide a set of +unofficial, unsupported, possibly unmaintained, but potentially useful, +alternative build files. See [`altbuild/README.md`](altbuild/README.md) for details. + + +CONTRIBUTING +------------ + +Patches and pull requests for bugfixes and new features are certainly welcome. +Please send patches to the freeglut-developer mailing list (see CONTACT below). + +Feel free to report any bugs you encounter, using the github *issues* system. + +Older bug reports and feature requests are still reachable on: + - https://sourceforge.net/p/freeglut/bugs/ + - https://sourceforge.net/p/freeglut/feature-requests/ + +But you are encouraged to use github issues for new ones. + +Alternatively you can also send bug reports and feature requests to the +freeglut-developer mailing list if you prefer. Extended discussions about new +features and design issues for large contributions, are best suited to the +mailing list. + + +CONTACT +------- + +FreeGLUT website: http://freeglut.sourceforge.net + +FreeGLUT mailing lists: + - developer: https://lists.sourceforge.net/lists/listinfo/freeglut-developer + - bugs: https://lists.sourceforge.net/lists/listinfo/freeglut-bugs + - announce: https://lists.sourceforge.net/lists/listinfo/freeglut-announce + + You need to subscribe before posting to any of our mailing lists. Make sure + to avoid selecting "daily digest mode" if you intend to post, so that you can + reply properly to specific messages. Also, please do not top-post, and try to + send properly formated emails (text, hard-wrapped at 72 columns, no binary or + large attachements). diff --git a/README.mingw_cross b/README.mingw_cross new file mode 100644 index 0000000..517734a --- /dev/null +++ b/README.mingw_cross @@ -0,0 +1,49 @@ +Cross-compilation from GNU/Linux (static and shared DLL) +======================================================== + +Install MinGW, and specify which MinGW you're using: + +- on Debian/Ubuntu, mingw-w64, 64-bit executables: + + apt-get install mingw-w64 + GNU_HOST=x86_64-w64-mingw32 + +- on Debian/Ubuntu, mingw-w64, 32-bit executables: + + apt-get install mingw-w64 + GNU_HOST=i686-w64-mingw32 + +- on Fedora, mingw32, 32-bit executables: + + yum install mingw32-gcc + GNU_HOST=i686-pc-mingw32 + +- on Debian/Ubuntu, mingw32 (deprecated): + + apt-get install mingw32 + GNU_HOST=i586-mingw32msvc + + +With CMake +---------- + +Cross-compile with: + + mkdir cross-woe/ && cd cross-woe/ + cmake \ + -D GNU_HOST=$GNU_HOST \ + -D CMAKE_TOOLCHAIN_FILE=mingw_cross_toolchain.cmake \ + -D CMAKE_INSTALL_PREFIX=/freeglut \ + .. + make -j4 + make install DESTDIR=$(pwd) + +Everything is now in the new 'freeglut/' directory. +The .dll is in 'freeglut/lib/'. + + +Compiling your code +------------------- + +Compilation of your own programs is done as usual. +See README.cygwin_mingw for details. diff --git a/README.win32 b/README.win32 new file mode 100644 index 0000000..87247b1 --- /dev/null +++ b/README.win32 @@ -0,0 +1,91 @@ +NB +================================== +For ancient 16bit compatibility, windef.h (included through windows.h in +freeglut_std.h) defines near and far. Its best to avoid using variables +with these names in your own program. + +Installing the Libraries with MSVC +================================== + +To install "freeglut" on your system so that your other projects will see it, +you will need to copy various files to various locations. + + - The header files "freeglut.h", "freeglut_ext.h", "freeglut_std.h", and + "glut.h" (distributed in the directory "freeglut\freeglut\include\GL") + need to be copied to a "GL" directory under the MSVC include directory. + The MSVC include directory generally has a path similar to + "C:\Program Files\Microsoft Visual Studio\VC98\Include" + The "GL" subdirectory under that will probably already have the header + files "gl.h", "glaux.h", and "glu.h". + - The library file "freeglut.lib" or "freeglut_static.lib" (from the + corresponding debug or release directory) needs to be copied into the + MSVC library directory. This usually has a path similar to: + "%ProgramFiles%\Microsoft SDKs\Windows\v7.0A\Lib" - x86 32 bits LIB's + "%ProgramFiles(x86)%\Microsoft SDKs\Windows\v7.0A\Lib" - x64 32 bits LIB's + "%ProgramFiles(x86)%\Microsoft SDKs\Windows\v7.0A\Lib\x64" - x64 64 bits LIB's + Note that there is no "GL" subdirectory here. This directory should + already have the files "opengl32.lib", "glu32.lib", and "glaux.lib". + - If you are using the DLL version of "freeglut", the file "freeglut.dll" + needs to be copied from the Debug or the Release directory into the + DLL directory. This usually has a path similar to + "%SystemRoot%\System32\" - x86 32 bits DLL's + "%SystemRoot%\SysWOW64\" - x64 32 bits DLL's + "%SystemRoot%\System32\" - x64 64 bits DLL's + and will probably already have the files "opengl32.dll" and "glu32.dll". + + +Building and Installing the Libraries with Open Watcom +====================================================== + +Start a command prompt and change directory to the freeglut installation +directory. Type "wmake -f Makefile.wat all" to build the DLL and static +libraries in both debug and release versions. + +To install "freeglut" on your system so that your other projects will see it, +you will need to copy various files to various locations. + + - The header files "freeglut.h", "freeglut_ext.h", "freeglut_std.h", and + "glut.h" (distributed in the directory "freeglut\freeglut\include\GL") + need to be copied to a "GL" directory under the Open Watcom 32-bit + Windows include directory. This usually has a path similar to + "C:\WATCOM\h\nt\GL" + - The library file "freeglut.lib" or "freeglut_static.lib" (from the + corresponding debug or release directory) needs to be copied into the + Open Watcom 32-bit Windows library directory. This usually has a path + similar to + "C:\WATCOM\lib386\nt" + - If you are using the DLL version of "freeglut", the file "freeglut.dll" + needs to be copied from the Debug or the Release directory into the + DLL directory. This usually has a path similar to + "C:\Windows\System32" + and will probably already have the files "opengl32.dll" and "glu32.dll". + + +Unlike the *nix release, the library names are NOT automatic replacements for +the GLUT library names. You may rename them manually if you wish, but this is +not necessary as the header file includes a pragma telling the compiler which +library file to look for. + + +Building and Installing the Libraries with Cygwin +================================================= + +To build "freeglut" under Cygwin, you have two choices: + +- You can build a normal Cygwin library, which depends on Cygwin's X11 + libraries. To do this, you can just use the normal autotools incantation: + ./configure && make install + +- Alternatively, you can build a DLL which does not depend on X11 and links + against the opengl32 DLL. To do this, configure need a few more flags: + ./configure CPPFLAGS=-mno-cygwin LDFLAGS=-mno-cygwin --without-x && make install + + +If you don't have MSVC, Open Watcom or Cygwin +============================================= + +The "freeglut" developers' community discussed the possibility of distributing +binaries and decided against it. If you need Windows library files, please +contact John F. Fay at or put a request on the +"freeglut" developers' mailing list . + diff --git a/altbuild/Makefile b/altbuild/Makefile new file mode 100644 index 0000000..d97d406 --- /dev/null +++ b/altbuild/Makefile @@ -0,0 +1,76 @@ +# Simple UNIX makefile +# Builds freeglut as a static library. + +# ------- options -------- + +# installation prefix +PREFIX = /usr/local + +# subdirectory for libraries (lib, lib32, lib64?) +LIBDIR = lib + +# optimization flags +opt = -O3 + +# debug symbols +#dbg = -g + +# libraries to link when building the demo program (make demo). You might need +# to adjust these, depending on the choices in config.h +demo_libs = $(liba) -lGL -lX11 -lXmu -lXext -lXi -lXrandr -lXxf86vm -lm + +# ---- end of options ---- + +coreobj = src/fg_gl2.o src/fg_misc.o src/fg_input_devices.o src/fg_ext.o \ + src/fg_joystick.o src/fg_init.o src/fg_callbacks.o \ + src/fg_menu.o src/fg_stroke_roman.o src/fg_structure.o src/fg_overlay.o \ + src/fg_window.o src/fg_state.o src/fg_videoresize.o src/fg_spaceball.o \ + src/fg_cursor.o src/fg_main.o src/fg_gamemode.o \ + src/fg_stroke_mono_roman.o src/fg_geometry.o src/fg_font.o src/fg_display.o \ + src/fg_font_data.o src/fg_teapot.o + +x11obj = src/x11/fg_state_x11_glx.o src/x11/fg_glutfont_definitions_x11.o \ + src/x11/fg_joystick_x11.o src/x11/fg_structure_x11.o src/x11/fg_cursor_x11.o \ + src/x11/fg_state_x11.o src/x11/fg_main_x11.o src/x11/fg_spaceball_x11.o \ + src/x11/fg_input_devices_x11.o src/x11/fg_ext_x11.o src/x11/fg_window_x11_glx.o \ + src/x11/fg_gamemode_x11.o src/x11/fg_init_x11.o src/x11/fg_menu_x11.o \ + src/x11/fg_xinput_x11.o src/x11/fg_window_x11.o src/x11/fg_display_x11_glx.o \ + src/x11/fg_cmap_x11.o + +obj = $(coreobj) $(x11obj) + +liba = libglut.a +incpath = -I. -Isrc -Iinclude -I/usr/local/include -I/usr/X11R6/include +libpath = -L/usr/local/lib -L/usr/X11R6/lib + +CFLAGS = -O2 $(incpath) -DHAVE_CONFIG_H +LDFLAGS = $(libpath) + + +$(liba): $(obj) + $(AR) rcs $@ $(obj) + +demo: progs/demos/3dview/3dview.o $(liba) + $(CC) -o $@ progs/demos/3dview/3dview.o $(LDFLAGS) $(demo_libs) + +.c.o: + $(CC) -o $@ $(CFLAGS) -c $< + +.PHONY: clean +clean: + rm -f $(obj) $(liba) demo + +.PHONY: install +install: $(liba) + mkdir -p $(DESTDIR)$(PREFIX)/$(LIBDIR) $(DESTDIR)$(PREFIX)/include/GL + cp include/GL/* $(DESTDIR)$(PREFIX)/include/GL + cp $(liba) $(DESTDIR)$(PREFIX)/$(LIBDIR)/$(liba) + +.PHONY: uninstall +uninstall: + rm -f $(DESTDIR)$(PREFIX)/$(LIBDIR)/$(liba) + rm -f $(DESTDIR)$(PREFIX)/include/GL/glut.h + rm -f $(DESTDIR)$(PREFIX)/include/GL/freeglut.h + rm -f $(DESTDIR)$(PREFIX)/include/GL/freeglut_std.h + rm -f $(DESTDIR)$(PREFIX)/include/GL/freeglut_ext.h + rm -f $(DESTDIR)$(PREFIX)/include/GL/freeglut_ucall.h diff --git a/altbuild/README.md b/altbuild/README.md new file mode 100644 index 0000000..d22da25 --- /dev/null +++ b/altbuild/README.md @@ -0,0 +1,66 @@ +Simple build files for freeglut +=============================== +This directory includes a number of simple ways to build freeglut, without +relying on extra tools. + +The official build system used by freeglut is cmake, with the current minimum +cmake version required being set to 3.0. Installing and using cmake 3.0 or later +to generate build files might be difficult or inconvenient in some cases. +Installing modern versions of cmake on very old UNIX systems might be difficult +or impossible. And finding the exact cmake version which still supports +generating project files for a certain old IDE, dropped from current cmake, can +be annoying. + +None of the files in this directory are officially supported! Some of them might +be completely unmaintained, broken, or out of date. Please report any issues, +but be warned that you may have to fix them yourself. + +The simple build files in this directory do not build the demo programs, and do +not provide the same flexibility of build options as the official cmake build. +Most of them just build a default configuration of freeglut as a static library +and that's it. + +Configuration +------------- +Before using any of these build files, first you'll need to select one of the +`config.h.*` files provided, copy it to the project root directory with the name +`config.h`. The following config files are available: + + - config.h.unix: Modern UNIX with X11 (GNU/Linux, FreeBSD, etc). + - config.h.msvc6: Windows build with MS Visual C/C++ 6.0. + - config.h.irix5: IRIX 5.x build with the SGI compiler. + - config.h.irix6: IRIX 6.x build with the SGI compiler. + +You can edit the `config.h` file to remove unnecessary dependencies (and their +corresponding features). For example, some old X servers do not have the XRandR +extension, or you may not wish to install libXrandr, in which case you should +disable it by deleting the `#define HAVE_X11_EXTENSIONS_XRANDR_H` line, or +changing `define` to `undef`. + +Simple UNIX Makefile +-------------------- +This should build freeglut on many different UNIX systems with their native +make utility. + + - Copy `Makefile` to the project root directory. + - Copy the appropriate `config.h.*` file to the project root directory renamed + to `config.h`. + - `make` to build. + - `make install` to install. Change the `PREFIX` variable at the top of the + `Makefile` to change the installation prefix. + +You can also attempt to build a simple statically linked demo program, by typing +`make demo`. But be warned that you might need to modify the `demo_libs` +variable at the top of the `Makefile` to adjust for whatever options are +selected in the `config.h` you used to build freeglut. + +MS Visual Studio 6.0 project +---------------------------- +Project files for building freeglut on 32bit windows, using MSVC6. + + - Copy `config.h.msvc6` to the project root directory renamed to `config.h`. + - Open the `freeglut.dsw` "workspace" file with visual studio 6. + - Select build all from the build menu. + +The MSVC6 project builds freeglut as both a static library and a DLL, and also +builds a simple statically linked demo program. diff --git a/altbuild/config.h.irix5 b/altbuild/config.h.irix5 new file mode 100644 index 0000000..0f2a4ea --- /dev/null +++ b/altbuild/config.h.irix5 @@ -0,0 +1,23 @@ +/* freeglut configuration file for building on SGI IRIX 5.x + * + * #define to enable, #undef or delete line to disable + * + * Copy to the freeglut root directory as config.h along with altbuild/Makefile + */ +#define HAVE_SYS_TYPES_H +#define HAVE_UNISTD_H +#define HAVE_SYS_TIME_H +#define HAVE_SYS_PARAM_H +#define HAVE_SYS_IOCTL_H +#define HAVE_FCNTL_H +#define HAVE_ERRNO_H +#define HAVE_GETTIMEOFDAY +#define HAVE_VFPRINTF +#define HAVE_ULONG_LONG + +/* inttypes.h conflicts with sys/types.h */ +#undef HAVE_INTTYPES_H + +/* warning and errors printed? */ +#define FREEGLUT_PRINT_WARNINGS +#define FREEGLUT_PRINT_ERRORS diff --git a/altbuild/config.h.irix6 b/altbuild/config.h.irix6 new file mode 100644 index 0000000..f81a9a5 --- /dev/null +++ b/altbuild/config.h.irix6 @@ -0,0 +1,35 @@ +/* freeglut configuration file for IRIX 6.x (tested 6.5.26) + * + * #define to enable, #undef or delete line to disable + * + * Copy to the freeglut root directory as config.h along with altbuild/Makefile + */ + +/* warning and errors printed? */ +#define FREEGLUT_PRINT_WARNINGS +#define FREEGLUT_PRINT_ERRORS + +/* all of these should be available on relatively modern UNIX systems */ +#define HAVE_SYS_TYPES_H /* sys/types.h */ +#define HAVE_UNISTD_H /* unistd.h */ +#define HAVE_SYS_TIME_H /* sys/time.h */ +#define HAVE_SYS_PARAM_H /* sys/param.h */ +#define HAVE_SYS_IOCTL_H /* sys/ioctl.h */ +#define HAVE_FCNTL_H /* fcntl.h */ +#define HAVE_ERRNO_H /* errno.h */ +#define HAVE_GETTIMEOFDAY /* gettimeofday() */ +#define HAVE_VFPRINTF /* vfprintf() */ +#define HAVE_INTTYPES_H /* inttypes.h */ +#define HAVE_ULONG_LONG /* unsigned long long */ +#undef HAVE_STDINT_H /* stdint.h - not available with MIPSpro cc */ + +/* don't need, XParseGeometry is in libX11 */ +#undef NEED_XPARSEGEOMETRY_IMPL +/* __int64 fallback is for msvc */ +#undef HAVE_U__INT64 +/* SGI X server does not support xf86vm, xrandr, and xinput2 */ +#undef HAVE_X11_EXTENSIONS_XF86VMODE_H +#undef HAVE_X11_EXTENSIONS_XRANDR_H +#undef HAVE_X11_EXTENSIONS_XINPUT2_H +/* USB HID, is only needed needed for joystick on BSD */ +#undef HAVE_USBHID_H diff --git a/altbuild/config.h.msvc6 b/altbuild/config.h.msvc6 new file mode 100644 index 0000000..6babe21 --- /dev/null +++ b/altbuild/config.h.msvc6 @@ -0,0 +1,14 @@ +/* freeglut configuration file for Windows with MS Visual C 6.0 + * + * Copy to the freeglut root dir as config.h, and open altbuild/freeglut.dsw + * Do not move the dsw/dsp project files, leave them in altbuild. + */ +#define HAVE_SYS_TYPES_H +#define HAVE_FCNTL_H +#define HAVE_ERRNO_H +#define NEED_XPARSEGEOMETRY_IMPL +#define HAVE_U__INT64 + +/* warning and errors printed? */ +#define FREEGLUT_PRINT_WARNINGS +#define FREEGLUT_PRINT_ERRORS diff --git a/altbuild/config.h.unix b/altbuild/config.h.unix new file mode 100644 index 0000000..238dcce --- /dev/null +++ b/altbuild/config.h.unix @@ -0,0 +1,37 @@ +/* freeglut configuration file for GNU/Linux and BSD + * + * #define to enable, #undef or delete line to disable + * + * Copy to the freeglut root directory as config.h along with altbuild/Makefile + */ + +/* XFree86 Video Mode extension, used for game mode, requires libXxf86vm */ +#define HAVE_X11_EXTENSIONS_XF86VMODE_H +/* XR&R extension, used for game mode, requires libXrandr */ +#define HAVE_X11_EXTENSIONS_XRANDR_H +/* XInput2 extension, used for joystick input, requires libXi */ +#define HAVE_X11_EXTENSIONS_XINPUT2_H +/* USB HID, needed for joystick on BSD, requires libusbhid */ +#define HAVE_USBHID_H +/* warning and errors printed? */ +#define FREEGLUT_PRINT_WARNINGS +#define FREEGLUT_PRINT_ERRORS + +/* all of these should be available on relatively modern UNIX systems */ +#define HAVE_SYS_TYPES_H /* sys/types.h */ +#define HAVE_UNISTD_H /* unistd.h */ +#define HAVE_SYS_TIME_H /* sys/time.h */ +#define HAVE_SYS_PARAM_H /* sys/param.h */ +#define HAVE_SYS_IOCTL_H /* sys/ioctl.h */ +#define HAVE_FCNTL_H /* fcntl.h */ +#define HAVE_ERRNO_H /* errno.h */ +#define HAVE_GETTIMEOFDAY /* gettimeofday() */ +#define HAVE_VFPRINTF /* vfprintf() */ +#define HAVE_STDINT_H /* stdint.h - might not be available, undef if not found */ +#define HAVE_INTTYPES_H /* inttypes.h */ +#define HAVE_ULONG_LONG /* unsigned long long */ + +/* don't need, XParseGeometry is in libX11 */ +#undef NEED_XPARSEGEOMETRY_IMPL +/* __int64 fallback is for msvc */ +#undef HAVE_U__INT64 diff --git a/altbuild/demo.dsp b/altbuild/demo.dsp new file mode 100644 index 0000000..1808243 --- /dev/null +++ b/altbuild/demo.dsp @@ -0,0 +1,102 @@ +# Microsoft Developer Studio Project File - Name="demo" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=demo - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "demo.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "demo.mak" CFG="demo - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "demo - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "demo - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "demo - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "FREEGLUT_STATIC" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /libpath:"Release" + +!ELSEIF "$(CFG)" == "demo - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "FREEGLUT_STATIC" /FR /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"Debug" + +!ENDIF + +# Begin Target + +# Name "demo - Win32 Release" +# Name "demo - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\progs\demos\3dview\3dview.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/altbuild/freeglut.dsp b/altbuild/freeglut.dsp new file mode 100644 index 0000000..c017908 --- /dev/null +++ b/altbuild/freeglut.dsp @@ -0,0 +1,318 @@ +# Microsoft Developer Studio Project File - Name="freeglut" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=freeglut - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "freeglut.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "freeglut.mak" CFG="freeglut - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "freeglut - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "freeglut - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "freeglut - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FREEGLUT_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /I "../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FREEGLUT_EXPORTS" /D "HAVE_CONFIG_H" /D _WIN32_WINNT=0x0500 /D WINVER=0x0500 /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 + +!ELSEIF "$(CFG)" == "freeglut - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FREEGLUT_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I ".." /I "../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FREEGLUT_EXPORTS" /D "HAVE_CONFIG_H" /D _WIN32_WINNT=0x0500 /D WINVER=0x0500 /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"Debug/freeglutd.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "freeglut - Win32 Release" +# Name "freeglut - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\config.h +# End Source File +# Begin Source File + +SOURCE=..\src\fg_callback_macros.h +# End Source File +# Begin Source File + +SOURCE=..\src\fg_callbacks.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_cmap_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_cursor.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_cursor_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_display.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_display_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_ext.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_ext_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_font.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_font_data.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_gamemode.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_gamemode_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_geometry.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_gl2.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_gl2.h +# End Source File +# Begin Source File + +SOURCE=..\src\fg_init.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_init.h +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_init_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_input_devices.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_input_devices_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_internal.h +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_internal_mswin.h +# End Source File +# Begin Source File + +SOURCE=..\src\fg_joystick.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_joystick_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_main.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_main_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_menu.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_menu_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_misc.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_overlay.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_spaceball.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_spaceball_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_state.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_state_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_stroke_mono_roman.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_stroke_roman.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_structure.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_structure_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_teapot.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_teapot_data.h +# End Source File +# Begin Source File + +SOURCE=..\src\fg_version.h +# End Source File +# Begin Source File + +SOURCE=..\src\fg_videoresize.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_window.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_window_mswin.c +# End Source File +# Begin Source File + +SOURCE=.\freeglutdll.def +# End Source File +# Begin Source File + +SOURCE=..\src\util\xparsegeometry_repl.c +# End Source File +# Begin Source File + +SOURCE=..\src\util\xparsegeometry_repl.h +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\include\Gl\freeglut.h +# End Source File +# Begin Source File + +SOURCE=..\include\Gl\freeglut_ext.h +# End Source File +# Begin Source File + +SOURCE=..\include\Gl\freeglut_std.h +# End Source File +# Begin Source File + +SOURCE=..\include\Gl\freeglut_ucall.h +# End Source File +# Begin Source File + +SOURCE=..\include\Gl\glut.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/altbuild/freeglut.dsw b/altbuild/freeglut.dsw new file mode 100644 index 0000000..507d713 --- /dev/null +++ b/altbuild/freeglut.dsw @@ -0,0 +1,59 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "demo"=.\demo.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name freeglut_static + End Project Dependency + Begin Project Dependency + Project_Dep_Name freeglut + End Project Dependency +}}} + +############################################################################### + +Project: "freeglut"=.\freeglut.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "freeglut_static"=.\freeglut_static.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/altbuild/freeglut_static.dsp b/altbuild/freeglut_static.dsp new file mode 100644 index 0000000..1a594c2 --- /dev/null +++ b/altbuild/freeglut_static.dsp @@ -0,0 +1,304 @@ +# Microsoft Developer Studio Project File - Name="freeglut_static" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=freeglut_static - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "freeglut_static.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "freeglut_static.mak" CFG="freeglut_static - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "freeglut_static - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "freeglut_static - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "freeglut_static - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release_static" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release_static" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I ".." /I "../include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "FREEGLUT_STATIC" /D "HAVE_CONFIG_H" /D _WIN32_WINNT=0x0500 /D WINVER=0x0500 /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "freeglut_static - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug_static" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug_static" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".." /I "../include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "FREEGLUT_STATIC" /D "HAVE_CONFIG_H" /D _WIN32_WINNT=0x0500 /D WINVER=0x0500 /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Debug\freeglut_staticd.lib" + +!ENDIF + +# Begin Target + +# Name "freeglut_static - Win32 Release" +# Name "freeglut_static - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\config.h +# End Source File +# Begin Source File + +SOURCE=..\src\fg_callback_macros.h +# End Source File +# Begin Source File + +SOURCE=..\src\fg_callbacks.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_cmap_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_cursor.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_cursor_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_display.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_display_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_ext.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_ext_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_font.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_font_data.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_gamemode.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_gamemode_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_geometry.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_gl2.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_gl2.h +# End Source File +# Begin Source File + +SOURCE=..\src\fg_init.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_init.h +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_init_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_input_devices.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_input_devices_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_internal.h +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_internal_mswin.h +# End Source File +# Begin Source File + +SOURCE=..\src\fg_joystick.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_joystick_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_main.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_main_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_menu.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_menu_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_misc.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_overlay.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_spaceball.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_spaceball_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_state.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_state_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_stroke_mono_roman.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_stroke_roman.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_structure.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_structure_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_teapot.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_teapot_data.h +# End Source File +# Begin Source File + +SOURCE=..\src\fg_version.h +# End Source File +# Begin Source File + +SOURCE=..\src\fg_videoresize.c +# End Source File +# Begin Source File + +SOURCE=..\src\fg_window.c +# End Source File +# Begin Source File + +SOURCE=..\src\mswin\fg_window_mswin.c +# End Source File +# Begin Source File + +SOURCE=..\src\util\xparsegeometry_repl.c +# End Source File +# Begin Source File + +SOURCE=..\src\util\xparsegeometry_repl.h +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\include\Gl\freeglut.h +# End Source File +# Begin Source File + +SOURCE=..\include\Gl\freeglut_ext.h +# End Source File +# Begin Source File + +SOURCE=..\include\Gl\freeglut_std.h +# End Source File +# Begin Source File + +SOURCE=..\include\Gl\freeglut_ucall.h +# End Source File +# Begin Source File + +SOURCE=..\include\Gl\glut.h +# End Source File +# End Group +# End Target +# End Project diff --git a/altbuild/freeglutdll.def b/altbuild/freeglutdll.def new file mode 100644 index 0000000..9a13b45 --- /dev/null +++ b/altbuild/freeglutdll.def @@ -0,0 +1,165 @@ +VERSION 3.4 +EXPORTS + glutInit + glutInitWindowPosition + glutInitWindowSize + glutInitDisplayMode + glutInitDisplayString + glutMainLoop + glutMainLoopEvent + glutLeaveMainLoop + glutCreateWindow + glutCreateSubWindow + glutDestroyWindow + glutSetWindow + glutGetWindow + glutSetWindowData + glutGetWindowData + glutSetWindowTitle + glutSetIconTitle + glutReshapeWindow + glutPositionWindow + glutShowWindow + glutHideWindow + glutIconifyWindow + glutPushWindow + glutPopWindow + glutFullScreen + glutPostWindowRedisplay + glutPostRedisplay + glutSwapBuffers + glutWarpPointer + glutSetCursor + glutEstablishOverlay + glutRemoveOverlay + glutUseLayer + glutPostOverlayRedisplay + glutPostWindowOverlayRedisplay + glutShowOverlay + glutHideOverlay + glutCreateMenu + glutDestroyMenu + glutGetMenu + glutSetMenu + glutGetMenuData + glutSetMenuData + glutAddMenuEntry + glutAddSubMenu + glutChangeToMenuEntry + glutChangeToSubMenu + glutRemoveMenuItem + glutAttachMenu + glutDetachMenu + glutTimerFunc + glutIdleFunc + glutKeyboardFunc + glutSpecialFunc + glutReshapeFunc + glutPositionFunc + glutVisibilityFunc + glutDisplayFunc + glutMouseFunc + glutMouseWheelFunc + glutMotionFunc + glutPassiveMotionFunc + glutEntryFunc + glutCloseFunc + glutWMCloseFunc + glutKeyboardUpFunc + glutSpecialUpFunc + glutJoystickFunc + glutMenuStateFunc + glutMenuStatusFunc + glutMenuDestroyFunc + glutOverlayDisplayFunc + glutWindowStatusFunc + glutSpaceballMotionFunc + glutSpaceballRotateFunc + glutSpaceballButtonFunc + glutButtonBoxFunc + glutDialsFunc + glutTabletMotionFunc + glutTabletButtonFunc + glutSetOption + glutGet + glutDeviceGet + glutGetModifiers + glutLayerGet + glutBitmapCharacter + glutBitmapWidth + glutStrokeCharacter + glutStrokeWidth + glutBitmapLength + glutStrokeLength + glutBitmapHeight + glutStrokeHeight + glutBitmapString + glutStrokeString + glutWireCube + glutSolidCube + glutWireSphere + glutSolidSphere + glutWireCone + glutSolidCone + glutWireTorus + glutSolidTorus + glutWireDodecahedron + glutSolidDodecahedron + glutWireOctahedron + glutSolidOctahedron + glutWireTetrahedron + glutSolidTetrahedron + glutWireIcosahedron + glutSolidIcosahedron + glutWireRhombicDodecahedron + glutSolidRhombicDodecahedron + glutWireSierpinskiSponge + glutSolidSierpinskiSponge + glutWireTeapot + glutSolidTeapot + glutWireTeacup + glutSolidTeacup + glutWireTeaspoon + glutSolidTeaspoon + glutWireCylinder + glutSolidCylinder + glutGameModeString + glutEnterGameMode + glutLeaveGameMode + glutGameModeGet + glutVideoResizeGet + glutSetupVideoResizing + glutStopVideoResizing + glutVideoResize + glutVideoPan + glutSetColor + glutGetColor + glutCopyColormap + glutIgnoreKeyRepeat + glutSetKeyRepeat + glutForceJoystickFunc + glutExtensionSupported + glutReportErrors + glutGetProcAddress + glutExit + glutFullScreenToggle + glutLeaveFullScreen + glutSetMenuFont + glutGetModeValues + glutInitContextFlags + glutInitContextVersion + glutInitContextProfile + glutInitErrorFunc + glutInitWarningFunc + __glutInitWithExit + __glutCreateWindowWithExit + __glutCreateMenuWithExit + glutMultiButtonFunc + glutMultiEntryFunc + glutMultiMotionFunc + glutMultiPassiveFunc + glutInitContextFunc + glutAppStatusFunc + glutSetVertexAttribCoord3 + glutSetVertexAttribNormal + glutSetVertexAttribTexCoord2 diff --git a/android/Android.mk b/android/Android.mk new file mode 100644 index 0000000..24bed93 --- /dev/null +++ b/android/Android.mk @@ -0,0 +1,9 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := freeglut-gles +LOCAL_SRC_FILES := lib/libfreeglut-gles.a +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include + +include $(PREBUILT_STATIC_LIBRARY) diff --git a/android/README b/android/README new file mode 100644 index 0000000..e7ebf04 --- /dev/null +++ b/android/README @@ -0,0 +1,2 @@ +- Android.mk : used to create a module compatible with the NDK build + system. See ../README.android for details. diff --git a/android_toolchain.cmake b/android_toolchain.cmake new file mode 100644 index 0000000..ef3bb61 --- /dev/null +++ b/android_toolchain.cmake @@ -0,0 +1,6 @@ +# CMake toolchain file, cf. README.android +SET(CMAKE_SYSTEM_NAME Linux) # Tell CMake we're cross-compiling +include(CMakeForceCompiler) +# Prefix detection only works with compiler id "GNU" +CMAKE_FORCE_C_COMPILER(arm-linux-androideabi-gcc GNU) +SET(ANDROID TRUE) diff --git a/blackberry.toolchain.cmake b/blackberry.toolchain.cmake new file mode 100644 index 0000000..4518d0f --- /dev/null +++ b/blackberry.toolchain.cmake @@ -0,0 +1,244 @@ +# ------------------------------------------------------------------------------ +# BlackBerry CMake toolchain file, for use with the BlackBerry 10 NDK +# Requires cmake 2.6.3 or newer (2.8.3 or newer is recommended). +# +# Usage Linux: +# $ source /absolute/path/to/the/bbndk/bbndk-env.sh +# $ mkdir build +# $ cd build +# $ cmake .. -DCMAKE_TOOLCHAIN_FILE="../blackberry.toolchain.cmake" -DBLACKBERRY_ARCHITECTURE=arm -DFREEGLUT_GLES=ON -DFREEGLUT_BUILD_DEMOS=NO -DCMAKE_VERBOSE_MAKEFILE=TRUE -G "Eclipse CDT4 - Unix Makefiles" +# $ make -j8 +# +# Usage Mac: +# Same as the steps on Linux +# +# Usage Windows: +# > /absolute/path/to/the/bbndk/bbndk-env.bat +# > mkdir build +# > cd build +# > cmake .. -DCMAKE_TOOLCHAIN_FILE="../blackberry.toolchain.cmake" -DBLACKBERRY_ARCHITECTURE=arm -DFREEGLUT_GLES=ON -DFREEGLUT_BUILD_DEMOS=NO -DCMAKE_VERBOSE_MAKEFILE=TRUE -G "Eclipse CDT4 - Unix Makefiles" +# > make -j8 +# + +cmake_minimum_required( VERSION 2.6.3 ) + +if( DEFINED CMAKE_CROSSCOMPILING ) + # Subsequent toolchain loading is not really needed + return() +endif() + +set( BLACKBERRY_TOOLCHAIN_ROOT "$ENV{QNX_HOST}" ) +set( BLACKBERRY_TARGET_ROOT "$ENV{QNX_TARGET}" ) +set( CMAKE_SYSTEM_NAME Linux ) +set( CMAKE_SYSTEM_VERSION 1 ) + +# Check for PlayBook +if( EXISTS "${BLACKBERRY_TARGET_ROOT}/x86/lib/gcc/4.4.2" ) + set( PLAYBOOK True ) +endif() + +# Check for for GCC 4.8.2 +if( EXISTS "${BLACKBERRY_TARGET_ROOT}/x86/lib/gcc/4.8.2" ) + set( BB_GCC_482 True ) +endif() + +# STL version: by default gnustl_static will be used +set( BLACKBERRY_USE_STLPORT FALSE CACHE BOOL "Experimental: use stlport_static instead of gnustl_static") +mark_as_advanced( BLACKBERRY_USE_STLPORT ) + +# Detect host platform +set( TOOL_OS_SUFFIX "" ) +if( CMAKE_HOST_APPLE ) + set( BLACKBERRY_NDK_HOST_SYSTEM_NAME "darwin-x86" ) +elseif( CMAKE_HOST_WIN32 ) + set( BLACKBERRY_NDK_HOST_SYSTEM_NAME "windows" ) + set( TOOL_OS_SUFFIX ".exe" ) +elseif( CMAKE_HOST_UNIX ) + set(BLACKBERRY_NDK_HOST_SYSTEM_NAME "linux-x86" ) +else() + message( FATAL_ERROR "Cross-compilation on your platform is not supported by this cmake toolchain" ) +endif() + +# Specify the cross compiler +set( CMAKE_C_COMPILER "$ENV{QNX_HOST}/usr/bin/qcc${TOOL_OS_SUFFIX}" CACHE PATH "gcc" ) +set( CMAKE_CXX_COMPILER "$ENV{QNX_HOST}/usr/bin/qcc${TOOL_OS_SUFFIX}" CACHE PATH "g++" ) +set( CMAKE_ASM_COMPILER "$ENV{QNX_HOST}/usr/bin/qcc${TOOL_OS_SUFFIX}" CACHE PATH "Assembler" ) +if( CMAKE_VERSION VERSION_LESS 2.8.5 ) + set( CMAKE_ASM_COMPILER_ARG1 "-c" ) +endif() + +# There may be a way to make cmake reduce these TODO +if( BLACKBERRY_ARCHITECTURE STREQUAL "arm" ) + set( NEUTRINO_ARCH "v7" ) +else() + set( NEUTRINO_ARCH "" ) +endif() +set( CMAKE_STRIP "$ENV{QNX_HOST}/usr/bin/nto${BLACKBERRY_ARCHITECTURE}-strip${TOOL_OS_SUFFIX}" CACHE PATH "strip" ) +set( CMAKE_AR "$ENV{QNX_HOST}/usr/bin/nto${BLACKBERRY_ARCHITECTURE}-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" ) +set( CMAKE_LINKER "$ENV{QNX_HOST}/usr/bin/nto${BLACKBERRY_ARCHITECTURE}${NEUTRINO_ARCH}-ld${TOOL_OS_SUFFIX}" CACHE PATH "linker" ) +set( CMAKE_NM "$ENV{QNX_HOST}/usr/bin/nto${BLACKBERRY_ARCHITECTURE}${NEUTRINO_ARCH}-nm${TOOL_OS_SUFFIX}" CACHE PATH "nm" ) +set( CMAKE_OBJCOPY "$ENV{QNX_HOST}/usr/bin/nto${BLACKBERRY_ARCHITECTURE}${NEUTRINO_ARCH}-objcopy${TOOL_OS_SUFFIX}" CACHE PATH "objcopy" ) +set( CMAKE_OBJDUMP "$ENV{QNX_HOST}/usr/bin/nto${BLACKBERRY_ARCHITECTURE}${NEUTRINO_ARCH}-objdump${TOOL_OS_SUFFIX}" CACHE PATH "objdump" ) +set( CMAKE_RANLIB "$ENV{QNX_HOST}/usr/bin/nto${BLACKBERRY_ARCHITECTURE}-ranlib${TOOL_OS_SUFFIX}" CACHE PATH "ranlib" ) + +# Installer +#if( APPLE ) +# find_program( CMAKE_INSTALL_NAME_TOOL NAMES install_name_tool ) +# if( NOT CMAKE_INSTALL_NAME_TOOL ) +# message( FATAL_ERROR "Could not find install_name_tool, please check your #installation." ) +# endif() +# mark_as_advanced( CMAKE_INSTALL_NAME_TOOL ) +# endif() + +# Setup output directories +set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_SOURCE_DIR} CACHE PATH "root for library output, set this to change where android libs are installed to" ) +set( CMAKE_INSTALL_PREFIX "${BLACKBERRY_TOOLCHAIN_ROOT}/user" CACHE STRING "path for installing" ) + +if( EXISTS "${CMAKE_SOURCE_DIR}/jni/CMakeLists.txt" ) + set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for applications" ) +else() + set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin" CACHE PATH "Output directory for applications" ) +endif() + +# Includes +if( PLAYBOOK ) + list( APPEND BLACKBERRY_SYSTEM_INCLUDE_DIRS "${BLACKBERRY_TARGET_ROOT}/usr/include" ) +else() + list( APPEND BLACKBERRY_SYSTEM_INCLUDE_DIRS "${BLACKBERRY_TARGET_ROOT}/qnx6/usr/include" ) +endif() + +# Flags and preprocessor definitions +set( BB_USING_GCC_482 False ) +if( PLAYBOOK ) + set( BLACKBERRY_COMP_DEF "-D__PLAYBOOK__" ) + set( BLACKBERRY_COMP_VERSION "4.4.2" ) +else() + set( BLACKBERRY_COMP_DEF "-D__QNX__" ) + if( BB_GCC_482 AND BLACKBERRY_USE_GCC_4_8 ) + set( BLACKBERRY_COMP_VERSION "4.8.2" ) + set( BB_USING_GCC_482 True ) + else() + set( BLACKBERRY_COMP_VERSION "4.6.3" ) + endif() +endif() +if( BLACKBERRY_ARCHITECTURE STREQUAL "arm" ) + set( BLACKBERRY_COMP_TARGET "gcc_ntoarmv7le" ) +else() + set( BLACKBERRY_COMP_TARGET "gcc_ntox86" ) +endif() +set( BLACKBERRY_CXX_COMP_LIB "" ) +if( BLACKBERRY_DINKUM ) + set( DINKUM 1 ) + if( BB_USING_GCC_482 ) + set( BLACKBERRY_COMP_TARGET "${BLACKBERRY_COMP_TARGET}_cpp" ) + else() + set( BLACKBERRY_CXX_COMP_LIB "-Y_cpp" ) + endif() +else() + set( DINKUM 0 ) + if( BB_USING_GCC_482 ) + set( BLACKBERRY_COMP_TARGET "${BLACKBERRY_COMP_TARGET}_gpp" ) + else() + set( BLACKBERRY_CXX_COMP_LIB "-Y_gpp" ) + endif() +endif() +set( BLACKBERRY_CC_FLAGS " -V${BLACKBERRY_COMP_VERSION},${BLACKBERRY_COMP_TARGET} ${BLACKBERRY_COMP_DEF}" ) +set( BLACKBERRY_CXX_FLAGS " -V${BLACKBERRY_COMP_VERSION},${BLACKBERRY_COMP_TARGET} ${BLACKBERRY_CXX_COMP_LIB} ${BLACKBERRY_COMP_DEF}" ) +set( BLACKBERRY 1 ) + +# NDK flags +if( DINKUM ) + set( CMAKE_CXX_FLAGS "${BLACKBERRY_CXX_FLAGS} -DBLACKBERRY_DINKUM=1" ) + set( CMAKE_C_FLAGS "${BLACKBERRY_CC_FLAGS} -DBLACKBERRY_DINKUM=1" ) +else() + set( CMAKE_CXX_FLAGS "${BLACKBERRY_CXX_FLAGS}" ) + set( CMAKE_C_FLAGS "${BLACKBERRY_CC_FLAGS}" ) +endif() +set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions" ) +set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fexceptions" ) + +# Release and Debug flags +if( BLACKBERRY_ARCHITECTURE STREQUAL "arm" ) + set( CMAKE_CXX_FLAGS_RELEASE "-mthumb -O3" ) + set( CMAKE_C_FLAGS_RELEASE "-mthumb -O3" ) + set( CMAKE_CXX_FLAGS_DEBUG "-marm -Os -finline-limit=64" ) + set( CMAKE_C_FLAGS_DEBUG "-marm -Os -finline-limit=64" ) +else() + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i486" ) + set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i486" ) +endif() + +# Cache flags +set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags" ) +set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "c flags" ) +set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}" CACHE STRING "c++ Release flags" ) +set( CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}" CACHE STRING "c Release flags" ) +set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING "c++ Debug flags" ) +set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" CACHE STRING "c Debug flags" ) +set( CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "linker flags" ) +SET( CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "" CACHE STRING "linker flags") +SET( CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "" CACHE STRING "linker flags") +set( CMAKE_MODULE_LINKER_FLAGS "" CACHE STRING "linker flags" ) +set( CMAKE_EXE_LINKER_FLAGS "-lstdc++" CACHE STRING "linker flags" ) + +# Finish flags +set( BLACKBERRY_CXX_FLAGS "${BLACKBERRY_CXX_FLAGS}" CACHE INTERNAL "Extra BlackBerry compiler flags") +set( BLACKBERRY_LINKER_FLAGS "${BLACKBERRY_LINKER_FLAGS}" CACHE INTERNAL "Extra BlackBerry linker flags") +set( CMAKE_CXX_FLAGS "${BLACKBERRY_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" ) +set( CMAKE_C_FLAGS "${BLACKBERRY_CXX_FLAGS} ${CMAKE_C_FLAGS}" ) + +# Global flags for cmake client scripts to change behavior +set( BLACKBERRY True ) +# Find the Target environment +set( CMAKE_FIND_ROOT_PATH "${CMAKE_SOURCE_DIR}" "${BLACKBERRY_TARGET_ROOT}" "${CMAKE_INSTALL_PREFIX}" "${CMAKE_INSTALL_PREFIX}/share" ) +# Search for libraries and includes in the ndk toolchain +set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) +set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) +set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) + +# Macro to find packages on the host OS +macro( find_host_package ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) + if( CMAKE_HOST_WIN32 ) + SET( WIN32 1 ) + SET( UNIX ) + elseif( CMAKE_HOST_APPLE ) + SET( APPLE 1 ) + SET( UNIX ) + endif() + find_package( ${ARGN} ) + SET( WIN32 ) + SET( APPLE ) + SET( UNIX 1 ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) +endmacro() + +# Macro to find programs on the host OS +macro( find_host_program ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) + if( CMAKE_HOST_WIN32 ) + SET( WIN32 1 ) + SET( UNIX ) + elseif( CMAKE_HOST_APPLE ) + SET( APPLE 1 ) + SET( UNIX ) + endif() + find_program( ${ARGN} ) + SET( WIN32 ) + SET( APPLE ) + SET( UNIX 1 ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) +endmacro() + +# We are doing cross compiling, reset the OS information of the Building system +UNSET( APPLE ) +UNSET( WIN32 ) +UNSET( UNIX ) diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..7da6007 --- /dev/null +++ b/config.h.in @@ -0,0 +1,24 @@ +#cmakedefine HAVE_X11_EXTENSIONS_XF86VMODE_H +#cmakedefine HAVE_X11_EXTENSIONS_XRANDR_H +#cmakedefine HAVE_X11_EXTENSIONS_XINPUT2_H +#cmakedefine HAVE_SYS_TYPES_H +#cmakedefine HAVE_UNISTD_H +#cmakedefine HAVE_SYS_TIME_H +#cmakedefine HAVE_STDBOOL_H +#cmakedefine HAVE_SYS_PARAM_H +#cmakedefine HAVE_SYS_IOCTL_H +#cmakedefine HAVE_FCNTL_H +#cmakedefine HAVE_ERRNO_H +#cmakedefine HAVE_USBHID_H +#cmakedefine HAVE_GETTIMEOFDAY +#cmakedefine HAVE_VFPRINTF +#cmakedefine HAVE_DOPRNT +#cmakedefine NEED_XPARSEGEOMETRY_IMPL +#cmakedefine HAVE_STDINT_H +#cmakedefine HAVE_INTTYPES_H +#cmakedefine HAVE_ULONG_LONG +#cmakedefine HAVE_U__INT64 + +/* warning and errors printed? */ +#cmakedefine FREEGLUT_PRINT_WARNINGS +#cmakedefine FREEGLUT_PRINT_ERRORS diff --git a/freeglut.pc.in b/freeglut.pc.in new file mode 100644 index 0000000..bc9249c --- /dev/null +++ b/freeglut.pc.in @@ -0,0 +1,10 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +libdir=@CMAKE_INSTALL_FULL_LIBDIR@ +includedir=${prefix}/include + +Name: glut +Description: A freely licensed and improved alternative to the GLUT library +Version: @VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@ +Libs: -L${libdir} -l@PC_LIBNAME@ +Libs.private: @PC_LIBS_PRIVATE@ +Cflags: -I${includedir} @PC_CFLAGS@ diff --git a/freeglut.rc.in b/freeglut.rc.in new file mode 100755 index 0000000..08177fa --- /dev/null +++ b/freeglut.rc.in @@ -0,0 +1,40 @@ + +/* 0 ICON DISCARDABLE "OpenGL.ico" */ + +1 VERSIONINFO + FILEVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,0 + PRODUCTVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080904b0" + BEGIN + /* VALUE "Comments", "\0" */ + /* VALUE "CompanyName", "\0" */ + VALUE "FileDescription", "Freeglut OpenGL Utility Toolkit\0" + VALUE "FileVersion", "@VERSION_MAJOR@, @VERSION_MINOR@, @VERSION_PATCH@, 0\0" + VALUE "InternalName", "freeglutdll\0" + VALUE "LegalCopyright", "Copyright © 1999-2000 Pawel W. Olszta, 2000-2012 Stephen J. Baker\0" + /* VALUE "LegalTrademarks", "\0" */ + VALUE "OriginalFilename", "freeglut.dll\0" + /* VALUE "PrivateBuild", "\0" */ + VALUE "ProductName", "Freeglut OpenGL Utility Toolkit\0" + VALUE "ProductVersion", "@VERSION_MAJOR@, @VERSION_MINOR@, @VERSION_PATCH@, 0\0" + /* VALUE "SpecialBuild", "\0" */ + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x809, 1200 + END +END + diff --git a/include/GL/freeglut.h b/include/GL/freeglut.h new file mode 100644 index 0000000..0e6f8c6 --- /dev/null +++ b/include/GL/freeglut.h @@ -0,0 +1,22 @@ +#ifndef __FREEGLUT_H__ +#define __FREEGLUT_H__ + +/* + * freeglut.h + * + * The freeglut library include file + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "freeglut_std.h" +#include "freeglut_ext.h" + +/*** END OF FILE ***/ + +#endif /* __FREEGLUT_H__ */ diff --git a/include/GL/freeglut_ext.h b/include/GL/freeglut_ext.h new file mode 100644 index 0000000..32bdcf3 --- /dev/null +++ b/include/GL/freeglut_ext.h @@ -0,0 +1,295 @@ +#ifndef __FREEGLUT_EXT_H__ +#define __FREEGLUT_EXT_H__ + +/* + * freeglut_ext.h + * + * The non-GLUT-compatible extensions to the freeglut library include file + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Thu Dec 2 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifdef __cplusplus + extern "C" { +#endif + +/* + * Additional GLUT Key definitions for the Special key function + */ +#define GLUT_KEY_NUM_LOCK 0x006D +#define GLUT_KEY_BEGIN 0x006E +#define GLUT_KEY_DELETE 0x006F +#define GLUT_KEY_SHIFT_L 0x0070 +#define GLUT_KEY_SHIFT_R 0x0071 +#define GLUT_KEY_CTRL_L 0x0072 +#define GLUT_KEY_CTRL_R 0x0073 +#define GLUT_KEY_ALT_L 0x0074 +#define GLUT_KEY_ALT_R 0x0075 +#define GLUT_KEY_SUPER_L 0x0076 +#define GLUT_KEY_SUPER_R 0x0077 + +/* + * Additional GLUT modifiers + */ +#define GLUT_ACTIVE_SUPER 0x0008 + +/* + * GLUT API Extension macro definitions -- behaviour when the user clicks on an "x" to close a window + */ +#define GLUT_ACTION_EXIT 0 +#define GLUT_ACTION_GLUTMAINLOOP_RETURNS 1 +#define GLUT_ACTION_CONTINUE_EXECUTION 2 + +/* + * Create a new rendering context when the user opens a new window? + */ +#define GLUT_CREATE_NEW_CONTEXT 0 +#define GLUT_USE_CURRENT_CONTEXT 1 + +/* + * Direct/Indirect rendering context options (has meaning only in Unix/X11) + */ +#define GLUT_FORCE_INDIRECT_CONTEXT 0 +#define GLUT_ALLOW_DIRECT_CONTEXT 1 +#define GLUT_TRY_DIRECT_CONTEXT 2 +#define GLUT_FORCE_DIRECT_CONTEXT 3 + +/* + * GLUT API Extension macro definitions -- the glutGet parameters + */ +#define GLUT_INIT_STATE 0x007C + +#define GLUT_ACTION_ON_WINDOW_CLOSE 0x01F9 + +#define GLUT_WINDOW_BORDER_WIDTH 0x01FA +#define GLUT_WINDOW_BORDER_HEIGHT 0x01FB +#define GLUT_WINDOW_HEADER_HEIGHT 0x01FB /* Docs say it should always have been GLUT_WINDOW_BORDER_HEIGHT, keep this for backward compatibility */ + +#define GLUT_VERSION 0x01FC + +#define GLUT_RENDERING_CONTEXT 0x01FD +#define GLUT_DIRECT_RENDERING 0x01FE + +#define GLUT_FULL_SCREEN 0x01FF + +#define GLUT_SKIP_STALE_MOTION_EVENTS 0x0204 + +#define GLUT_GEOMETRY_VISUALIZE_NORMALS 0x0205 + +#define GLUT_STROKE_FONT_DRAW_JOIN_DOTS 0x0206 /* Draw dots between line segments of stroke fonts? */ + +#define GLUT_ALLOW_NEGATIVE_WINDOW_POSITION 0x0207 /* GLUT doesn't allow negative window positions by default */ + +#define GLUT_WINDOW_SRGB 0x007D + +/* + * New tokens for glutInitDisplayMode. + * Only one GLUT_AUXn bit may be used at a time. + * Value 0x0400 is defined in OpenGLUT. + */ +#define GLUT_AUX 0x1000 + +#define GLUT_AUX1 0x1000 +#define GLUT_AUX2 0x2000 +#define GLUT_AUX3 0x4000 +#define GLUT_AUX4 0x8000 + +/* + * Context-related flags, see fg_state.c + * Set the requested OpenGL version + */ +#define GLUT_INIT_MAJOR_VERSION 0x0200 +#define GLUT_INIT_MINOR_VERSION 0x0201 +#define GLUT_INIT_FLAGS 0x0202 +#define GLUT_INIT_PROFILE 0x0203 + +/* + * Flags for glutInitContextFlags, see fg_init.c + */ +#define GLUT_DEBUG 0x0001 +#define GLUT_FORWARD_COMPATIBLE 0x0002 + + +/* + * Flags for glutInitContextProfile, see fg_init.c + */ +#define GLUT_CORE_PROFILE 0x0001 +#define GLUT_COMPATIBILITY_PROFILE 0x0002 + +/* +* GLUT API Extension macro definitions -- Spaceball button definitions +*/ + +#define GLUT_SPACEBALL_BUTTON_A 0x0001 +#define GLUT_SPACEBALL_BUTTON_B 0x0002 +#define GLUT_SPACEBALL_BUTTON_C 0x0004 +#define GLUT_SPACEBALL_BUTTON_D 0x0008 +#define GLUT_SPACEBALL_BUTTON_E 0x0010 + +/* + * Process loop function, see fg_main.c + */ +FGAPI void FGAPIENTRY glutMainLoopEvent( void ); +FGAPI void FGAPIENTRY glutLeaveMainLoop( void ); +FGAPI void FGAPIENTRY glutExit ( void ); + +/* + * Window management functions, see fg_window.c + */ +FGAPI void FGAPIENTRY glutFullScreenToggle( void ); +FGAPI void FGAPIENTRY glutLeaveFullScreen( void ); + +/* + * Menu functions + */ +FGAPI void FGAPIENTRY glutSetMenuFont( int menuID, void* font ); + +/* + * Window-specific callback functions, see fg_callbacks.c + */ +FGAPI void FGAPIENTRY glutMouseWheelFunc( void (* callback)( int, int, int, int ) ); +FGAPI void FGAPIENTRY glutPositionFunc( void (* callback)( int, int ) ); +FGAPI void FGAPIENTRY glutCloseFunc( void (* callback)( void ) ); +FGAPI void FGAPIENTRY glutWMCloseFunc( void (* callback)( void ) ); +/* And also a destruction callback for menus */ +FGAPI void FGAPIENTRY glutMenuDestroyFunc( void (* callback)( void ) ); + +/* + * State setting and retrieval functions, see fg_state.c + */ +FGAPI void FGAPIENTRY glutSetOption ( GLenum option_flag, int value ); +FGAPI int * FGAPIENTRY glutGetModeValues(GLenum mode, int * size); +/* A.Donev: User-data manipulation */ +FGAPI void* FGAPIENTRY glutGetWindowData( void ); +FGAPI void FGAPIENTRY glutSetWindowData(void* data); +FGAPI void* FGAPIENTRY glutGetMenuData( void ); +FGAPI void FGAPIENTRY glutSetMenuData(void* data); + +/* + * Font stuff, see fg_font.c + */ +FGAPI int FGAPIENTRY glutBitmapHeight( void* font ); +FGAPI GLfloat FGAPIENTRY glutStrokeHeight( void* font ); +FGAPI void FGAPIENTRY glutBitmapString( void* font, const unsigned char *string ); +FGAPI void FGAPIENTRY glutStrokeString( void* font, const unsigned char *string ); + +/* + * Geometry functions, see fg_geometry.c + */ +FGAPI void FGAPIENTRY glutWireRhombicDodecahedron( void ); +FGAPI void FGAPIENTRY glutSolidRhombicDodecahedron( void ); +FGAPI void FGAPIENTRY glutWireSierpinskiSponge ( int num_levels, double offset[3], double scale ); +FGAPI void FGAPIENTRY glutSolidSierpinskiSponge ( int num_levels, double offset[3], double scale ); +FGAPI void FGAPIENTRY glutWireCylinder( double radius, double height, GLint slices, GLint stacks); +FGAPI void FGAPIENTRY glutSolidCylinder( double radius, double height, GLint slices, GLint stacks); + +/* + * Rest of functions for rendering Newell's teaset, found in fg_teapot.c + * NB: front facing polygons have clockwise winding, not counter clockwise + */ +FGAPI void FGAPIENTRY glutWireTeacup( double size ); +FGAPI void FGAPIENTRY glutSolidTeacup( double size ); +FGAPI void FGAPIENTRY glutWireTeaspoon( double size ); +FGAPI void FGAPIENTRY glutSolidTeaspoon( double size ); + +/* + * Extension functions, see fg_ext.c + */ +typedef void (*GLUTproc)(); +FGAPI GLUTproc FGAPIENTRY glutGetProcAddress( const char *procName ); + +/* + * Multi-touch/multi-pointer extensions + */ + +#define GLUT_HAS_MULTI 1 + +/* TODO: add device_id parameter, + cf. http://sourceforge.net/mailarchive/forum.php?thread_name=20120518071314.GA28061%40perso.beuc.net&forum_name=freeglut-developer */ +FGAPI void FGAPIENTRY glutMultiEntryFunc( void (* callback)( int, int ) ); +FGAPI void FGAPIENTRY glutMultiButtonFunc( void (* callback)( int, int, int, int, int ) ); +FGAPI void FGAPIENTRY glutMultiMotionFunc( void (* callback)( int, int, int ) ); +FGAPI void FGAPIENTRY glutMultiPassiveFunc( void (* callback)( int, int, int ) ); + +/* + * Joystick functions, see fg_joystick.c + */ +/* USE OF THESE FUNCTIONS IS DEPRECATED !!!!! */ +/* If you have a serious need for these functions in your application, please either + * contact the "freeglut" developer community at freeglut-developer@lists.sourceforge.net, + * switch to the OpenGLUT library, or else port your joystick functionality over to PLIB's + * "js" library. + */ +int glutJoystickGetNumAxes( int ident ); +int glutJoystickGetNumButtons( int ident ); +int glutJoystickNotWorking( int ident ); +float glutJoystickGetDeadBand( int ident, int axis ); +void glutJoystickSetDeadBand( int ident, int axis, float db ); +float glutJoystickGetSaturation( int ident, int axis ); +void glutJoystickSetSaturation( int ident, int axis, float st ); +void glutJoystickSetMinRange( int ident, float *axes ); +void glutJoystickSetMaxRange( int ident, float *axes ); +void glutJoystickSetCenter( int ident, float *axes ); +void glutJoystickGetMinRange( int ident, float *axes ); +void glutJoystickGetMaxRange( int ident, float *axes ); +void glutJoystickGetCenter( int ident, float *axes ); + +/* + * Initialization functions, see fg_init.c + */ +/* to get the typedef for va_list */ +#include +FGAPI void FGAPIENTRY glutInitContextVersion( int majorVersion, int minorVersion ); +FGAPI void FGAPIENTRY glutInitContextFlags( int flags ); +FGAPI void FGAPIENTRY glutInitContextProfile( int profile ); +FGAPI void FGAPIENTRY glutInitErrorFunc( void (* callback)( const char *fmt, va_list ap ) ); +FGAPI void FGAPIENTRY glutInitWarningFunc( void (* callback)( const char *fmt, va_list ap ) ); + +/* OpenGL >= 2.0 support */ +FGAPI void FGAPIENTRY glutSetVertexAttribCoord3( GLint attrib ); +FGAPI void FGAPIENTRY glutSetVertexAttribNormal( GLint attrib ); +FGAPI void FGAPIENTRY glutSetVertexAttribTexCoord2( GLint attrib ); + +/* Mobile platforms lifecycle */ +FGAPI void FGAPIENTRY glutInitContextFunc( void (* callback)( void ) ); +FGAPI void FGAPIENTRY glutAppStatusFunc( void (* callback)( int ) ); +/* state flags that can be passed to callback set by glutAppStatusFunc */ +#define GLUT_APPSTATUS_PAUSE 0x0001 +#define GLUT_APPSTATUS_RESUME 0x0002 + +/* + * GLUT API macro definitions -- the display mode definitions + */ +#define GLUT_CAPTIONLESS 0x0400 +#define GLUT_BORDERLESS 0x0800 +#define GLUT_SRGB 0x1000 + +/* User-argument callbacks and implementation */ +#include "freeglut_ucall.h" + +#ifdef __cplusplus + } +#endif + +/*** END OF FILE ***/ + +#endif /* __FREEGLUT_EXT_H__ */ diff --git a/include/GL/freeglut_std.h b/include/GL/freeglut_std.h new file mode 100644 index 0000000..a658c7c --- /dev/null +++ b/include/GL/freeglut_std.h @@ -0,0 +1,653 @@ +#ifndef __FREEGLUT_STD_H__ +#define __FREEGLUT_STD_H__ + +/* + * freeglut_std.h + * + * The GLUT-compatible part of the freeglut library include file + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Thu Dec 2 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifdef __cplusplus + extern "C" { +#endif + +/* + * Under windows, we have to differentiate between static and dynamic libraries + */ +#ifdef _WIN32 +/* #pragma may not be supported by some compilers. + * Discussion by FreeGLUT developers suggests that + * Visual C++ specific code involving pragmas may + * need to move to a separate header. 24th Dec 2003 + */ + +/* Define FREEGLUT_LIB_PRAGMAS to 1 to include library + * pragmas or to 0 to exclude library pragmas. + * The default behavior depends on the compiler/platform. + */ +# ifndef FREEGLUT_LIB_PRAGMAS +# if ( defined(_MSC_VER) || defined(__WATCOMC__) ) && !defined(_WIN32_WCE) +# define FREEGLUT_LIB_PRAGMAS 1 +# else +# define FREEGLUT_LIB_PRAGMAS 0 +# endif +# endif + +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN 1 +# endif +# ifndef NOMINMAX +# define NOMINMAX +# endif +# include + +/* Windows static library */ +# ifdef FREEGLUT_STATIC + +# define FGAPI +# define FGAPIENTRY + + /* Link with Win32 static freeglut lib */ +# if FREEGLUT_LIB_PRAGMAS +# ifdef NDEBUG +# pragma comment (lib, "freeglut_static.lib") +# else +# pragma comment (lib, "freeglut_staticd.lib") +# endif +# endif + +/* Windows shared library (DLL) */ +# else + +# define FGAPIENTRY __stdcall +# if defined(FREEGLUT_EXPORTS) +# define FGAPI __declspec(dllexport) +# else +# define FGAPI __declspec(dllimport) + + /* Link with Win32 shared freeglut lib */ +# if FREEGLUT_LIB_PRAGMAS +# ifdef NDEBUG +# pragma comment (lib, "freeglut.lib") +# else +# pragma comment (lib, "freeglutd.lib") +# endif +# endif + +# endif + +# endif + +/* Drag in other Windows libraries as required by FreeGLUT */ +# if FREEGLUT_LIB_PRAGMAS +# pragma comment (lib, "glu32.lib") /* link OpenGL Utility lib */ +# pragma comment (lib, "opengl32.lib") /* link Microsoft OpenGL lib */ +# pragma comment (lib, "gdi32.lib") /* link Windows GDI lib */ +# pragma comment (lib, "winmm.lib") /* link Windows MultiMedia lib */ +# pragma comment (lib, "user32.lib") /* link Windows user lib */ +# endif + +#else + +/* Non-Windows definition of FGAPI and FGAPIENTRY */ +# define FGAPI +# define FGAPIENTRY + +#endif + +/* + * The freeglut and GLUT API versions + */ +#define FREEGLUT 1 +#define GLUT_API_VERSION 4 +#define GLUT_XLIB_IMPLEMENTATION 13 +/* Deprecated: + cf. http://sourceforge.net/mailarchive/forum.php?thread_name=CABcAi1hw7cr4xtigckaGXB5X8wddLfMcbA_rZ3NAuwMrX_zmsw%40mail.gmail.com&forum_name=freeglut-developer */ +#define FREEGLUT_VERSION_2_0 1 + +/* + * Always include OpenGL and GLU headers + */ +/* Note: FREEGLUT_GLES is only used to cleanly bootstrap headers + inclusion here; use GLES constants directly + (e.g. GL_ES_VERSION_2_0) for all other needs */ +#ifdef FREEGLUT_GLES +# include +# include +# include +#elif __APPLE__ +# include +# include +#else +# include +# include +#endif + +/* + * GLUT API macro definitions -- the special key codes: + */ +#define GLUT_KEY_F1 0x0001 +#define GLUT_KEY_F2 0x0002 +#define GLUT_KEY_F3 0x0003 +#define GLUT_KEY_F4 0x0004 +#define GLUT_KEY_F5 0x0005 +#define GLUT_KEY_F6 0x0006 +#define GLUT_KEY_F7 0x0007 +#define GLUT_KEY_F8 0x0008 +#define GLUT_KEY_F9 0x0009 +#define GLUT_KEY_F10 0x000A +#define GLUT_KEY_F11 0x000B +#define GLUT_KEY_F12 0x000C +#define GLUT_KEY_LEFT 0x0064 +#define GLUT_KEY_UP 0x0065 +#define GLUT_KEY_RIGHT 0x0066 +#define GLUT_KEY_DOWN 0x0067 +#define GLUT_KEY_PAGE_UP 0x0068 +#define GLUT_KEY_PAGE_DOWN 0x0069 +#define GLUT_KEY_HOME 0x006A +#define GLUT_KEY_END 0x006B +#define GLUT_KEY_INSERT 0x006C + +/* + * GLUT API macro definitions -- mouse state definitions + */ +#define GLUT_LEFT_BUTTON 0x0000 +#define GLUT_MIDDLE_BUTTON 0x0001 +#define GLUT_RIGHT_BUTTON 0x0002 +#define GLUT_DOWN 0x0000 +#define GLUT_UP 0x0001 +#define GLUT_LEFT 0x0000 +#define GLUT_ENTERED 0x0001 + +/* + * GLUT API macro definitions -- the display mode definitions + */ +#define GLUT_RGB 0x0000 +#define GLUT_RGBA 0x0000 +#define GLUT_INDEX 0x0001 +#define GLUT_SINGLE 0x0000 +#define GLUT_DOUBLE 0x0002 +#define GLUT_ACCUM 0x0004 +#define GLUT_ALPHA 0x0008 +#define GLUT_DEPTH 0x0010 +#define GLUT_STENCIL 0x0020 +#define GLUT_MULTISAMPLE 0x0080 +#define GLUT_STEREO 0x0100 +#define GLUT_LUMINANCE 0x0200 + +/* + * GLUT API macro definitions -- windows and menu related definitions + */ +#define GLUT_MENU_NOT_IN_USE 0x0000 +#define GLUT_MENU_IN_USE 0x0001 +#define GLUT_NOT_VISIBLE 0x0000 +#define GLUT_VISIBLE 0x0001 +#define GLUT_HIDDEN 0x0000 +#define GLUT_FULLY_RETAINED 0x0001 +#define GLUT_PARTIALLY_RETAINED 0x0002 +#define GLUT_FULLY_COVERED 0x0003 + +/* + * GLUT API macro definitions -- fonts definitions + * + * Steve Baker suggested to make it binary compatible with GLUT: + */ +#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__WATCOMC__) +# define GLUT_STROKE_ROMAN ((void *)0x0000) +# define GLUT_STROKE_MONO_ROMAN ((void *)0x0001) +# define GLUT_BITMAP_9_BY_15 ((void *)0x0002) +# define GLUT_BITMAP_8_BY_13 ((void *)0x0003) +# define GLUT_BITMAP_TIMES_ROMAN_10 ((void *)0x0004) +# define GLUT_BITMAP_TIMES_ROMAN_24 ((void *)0x0005) +# define GLUT_BITMAP_HELVETICA_10 ((void *)0x0006) +# define GLUT_BITMAP_HELVETICA_12 ((void *)0x0007) +# define GLUT_BITMAP_HELVETICA_18 ((void *)0x0008) +#else + /* + * I don't really know if it's a good idea... But here it goes: + */ + extern void* glutStrokeRoman; + extern void* glutStrokeMonoRoman; + extern void* glutBitmap9By15; + extern void* glutBitmap8By13; + extern void* glutBitmapTimesRoman10; + extern void* glutBitmapTimesRoman24; + extern void* glutBitmapHelvetica10; + extern void* glutBitmapHelvetica12; + extern void* glutBitmapHelvetica18; + + /* + * Those pointers will be used by following definitions: + */ +# define GLUT_STROKE_ROMAN ((void *) &glutStrokeRoman) +# define GLUT_STROKE_MONO_ROMAN ((void *) &glutStrokeMonoRoman) +# define GLUT_BITMAP_9_BY_15 ((void *) &glutBitmap9By15) +# define GLUT_BITMAP_8_BY_13 ((void *) &glutBitmap8By13) +# define GLUT_BITMAP_TIMES_ROMAN_10 ((void *) &glutBitmapTimesRoman10) +# define GLUT_BITMAP_TIMES_ROMAN_24 ((void *) &glutBitmapTimesRoman24) +# define GLUT_BITMAP_HELVETICA_10 ((void *) &glutBitmapHelvetica10) +# define GLUT_BITMAP_HELVETICA_12 ((void *) &glutBitmapHelvetica12) +# define GLUT_BITMAP_HELVETICA_18 ((void *) &glutBitmapHelvetica18) +#endif + +/* + * GLUT API macro definitions -- the glutGet parameters + */ +#define GLUT_WINDOW_X 0x0064 +#define GLUT_WINDOW_Y 0x0065 +#define GLUT_WINDOW_WIDTH 0x0066 +#define GLUT_WINDOW_HEIGHT 0x0067 +#define GLUT_WINDOW_BUFFER_SIZE 0x0068 +#define GLUT_WINDOW_STENCIL_SIZE 0x0069 +#define GLUT_WINDOW_DEPTH_SIZE 0x006A +#define GLUT_WINDOW_RED_SIZE 0x006B +#define GLUT_WINDOW_GREEN_SIZE 0x006C +#define GLUT_WINDOW_BLUE_SIZE 0x006D +#define GLUT_WINDOW_ALPHA_SIZE 0x006E +#define GLUT_WINDOW_ACCUM_RED_SIZE 0x006F +#define GLUT_WINDOW_ACCUM_GREEN_SIZE 0x0070 +#define GLUT_WINDOW_ACCUM_BLUE_SIZE 0x0071 +#define GLUT_WINDOW_ACCUM_ALPHA_SIZE 0x0072 +#define GLUT_WINDOW_DOUBLEBUFFER 0x0073 +#define GLUT_WINDOW_RGBA 0x0074 +#define GLUT_WINDOW_PARENT 0x0075 +#define GLUT_WINDOW_NUM_CHILDREN 0x0076 +#define GLUT_WINDOW_COLORMAP_SIZE 0x0077 +#define GLUT_WINDOW_NUM_SAMPLES 0x0078 +#define GLUT_WINDOW_STEREO 0x0079 +#define GLUT_WINDOW_CURSOR 0x007A + +#define GLUT_SCREEN_WIDTH 0x00C8 +#define GLUT_SCREEN_HEIGHT 0x00C9 +#define GLUT_SCREEN_WIDTH_MM 0x00CA +#define GLUT_SCREEN_HEIGHT_MM 0x00CB +#define GLUT_MENU_NUM_ITEMS 0x012C +#define GLUT_DISPLAY_MODE_POSSIBLE 0x0190 +#define GLUT_INIT_WINDOW_X 0x01F4 +#define GLUT_INIT_WINDOW_Y 0x01F5 +#define GLUT_INIT_WINDOW_WIDTH 0x01F6 +#define GLUT_INIT_WINDOW_HEIGHT 0x01F7 +#define GLUT_INIT_DISPLAY_MODE 0x01F8 +#define GLUT_ELAPSED_TIME 0x02BC +#define GLUT_WINDOW_FORMAT_ID 0x007B + +/* + * GLUT API macro definitions -- the glutDeviceGet parameters + */ +#define GLUT_HAS_KEYBOARD 0x0258 +#define GLUT_HAS_MOUSE 0x0259 +#define GLUT_HAS_SPACEBALL 0x025A +#define GLUT_HAS_DIAL_AND_BUTTON_BOX 0x025B +#define GLUT_HAS_TABLET 0x025C +#define GLUT_NUM_MOUSE_BUTTONS 0x025D +#define GLUT_NUM_SPACEBALL_BUTTONS 0x025E +#define GLUT_NUM_BUTTON_BOX_BUTTONS 0x025F +#define GLUT_NUM_DIALS 0x0260 +#define GLUT_NUM_TABLET_BUTTONS 0x0261 +#define GLUT_DEVICE_IGNORE_KEY_REPEAT 0x0262 +#define GLUT_DEVICE_KEY_REPEAT 0x0263 +#define GLUT_HAS_JOYSTICK 0x0264 +#define GLUT_OWNS_JOYSTICK 0x0265 +#define GLUT_JOYSTICK_BUTTONS 0x0266 +#define GLUT_JOYSTICK_AXES 0x0267 +#define GLUT_JOYSTICK_POLL_RATE 0x0268 + +/* + * GLUT API macro definitions -- the glutLayerGet parameters + */ +#define GLUT_OVERLAY_POSSIBLE 0x0320 +#define GLUT_LAYER_IN_USE 0x0321 +#define GLUT_HAS_OVERLAY 0x0322 +#define GLUT_TRANSPARENT_INDEX 0x0323 +#define GLUT_NORMAL_DAMAGED 0x0324 +#define GLUT_OVERLAY_DAMAGED 0x0325 + +/* + * GLUT API macro definitions -- the glutVideoResizeGet parameters + */ +#define GLUT_VIDEO_RESIZE_POSSIBLE 0x0384 +#define GLUT_VIDEO_RESIZE_IN_USE 0x0385 +#define GLUT_VIDEO_RESIZE_X_DELTA 0x0386 +#define GLUT_VIDEO_RESIZE_Y_DELTA 0x0387 +#define GLUT_VIDEO_RESIZE_WIDTH_DELTA 0x0388 +#define GLUT_VIDEO_RESIZE_HEIGHT_DELTA 0x0389 +#define GLUT_VIDEO_RESIZE_X 0x038A +#define GLUT_VIDEO_RESIZE_Y 0x038B +#define GLUT_VIDEO_RESIZE_WIDTH 0x038C +#define GLUT_VIDEO_RESIZE_HEIGHT 0x038D + +/* + * GLUT API macro definitions -- the glutUseLayer parameters + */ +#define GLUT_NORMAL 0x0000 +#define GLUT_OVERLAY 0x0001 + +/* + * GLUT API macro definitions -- the glutGetModifiers parameters + */ +#define GLUT_ACTIVE_SHIFT 0x0001 +#define GLUT_ACTIVE_CTRL 0x0002 +#define GLUT_ACTIVE_ALT 0x0004 + +/* + * GLUT API macro definitions -- the glutSetCursor parameters + */ +#define GLUT_CURSOR_RIGHT_ARROW 0x0000 +#define GLUT_CURSOR_LEFT_ARROW 0x0001 +#define GLUT_CURSOR_INFO 0x0002 +#define GLUT_CURSOR_DESTROY 0x0003 +#define GLUT_CURSOR_HELP 0x0004 +#define GLUT_CURSOR_CYCLE 0x0005 +#define GLUT_CURSOR_SPRAY 0x0006 +#define GLUT_CURSOR_WAIT 0x0007 +#define GLUT_CURSOR_TEXT 0x0008 +#define GLUT_CURSOR_CROSSHAIR 0x0009 +#define GLUT_CURSOR_UP_DOWN 0x000A +#define GLUT_CURSOR_LEFT_RIGHT 0x000B +#define GLUT_CURSOR_TOP_SIDE 0x000C +#define GLUT_CURSOR_BOTTOM_SIDE 0x000D +#define GLUT_CURSOR_LEFT_SIDE 0x000E +#define GLUT_CURSOR_RIGHT_SIDE 0x000F +#define GLUT_CURSOR_TOP_LEFT_CORNER 0x0010 +#define GLUT_CURSOR_TOP_RIGHT_CORNER 0x0011 +#define GLUT_CURSOR_BOTTOM_RIGHT_CORNER 0x0012 +#define GLUT_CURSOR_BOTTOM_LEFT_CORNER 0x0013 +#define GLUT_CURSOR_INHERIT 0x0064 +#define GLUT_CURSOR_NONE 0x0065 +#define GLUT_CURSOR_FULL_CROSSHAIR 0x0066 + +/* + * GLUT API macro definitions -- RGB color component specification definitions + */ +#define GLUT_RED 0x0000 +#define GLUT_GREEN 0x0001 +#define GLUT_BLUE 0x0002 + +/* + * GLUT API macro definitions -- additional keyboard and joystick definitions + */ +#define GLUT_KEY_REPEAT_OFF 0x0000 +#define GLUT_KEY_REPEAT_ON 0x0001 +#define GLUT_KEY_REPEAT_DEFAULT 0x0002 + +#define GLUT_JOYSTICK_BUTTON_A 0x0001 +#define GLUT_JOYSTICK_BUTTON_B 0x0002 +#define GLUT_JOYSTICK_BUTTON_C 0x0004 +#define GLUT_JOYSTICK_BUTTON_D 0x0008 + +/* + * GLUT API macro definitions -- game mode definitions + */ +#define GLUT_GAME_MODE_ACTIVE 0x0000 +#define GLUT_GAME_MODE_POSSIBLE 0x0001 +#define GLUT_GAME_MODE_WIDTH 0x0002 +#define GLUT_GAME_MODE_HEIGHT 0x0003 +#define GLUT_GAME_MODE_PIXEL_DEPTH 0x0004 +#define GLUT_GAME_MODE_REFRESH_RATE 0x0005 +#define GLUT_GAME_MODE_DISPLAY_CHANGED 0x0006 + +/* + * Initialization functions, see fglut_init.c + */ +FGAPI void FGAPIENTRY glutInit( int* pargc, char** argv ); +FGAPI void FGAPIENTRY glutInitWindowPosition( int x, int y ); +FGAPI void FGAPIENTRY glutInitWindowSize( int width, int height ); +FGAPI void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode ); +FGAPI void FGAPIENTRY glutInitDisplayString( const char* displayMode ); + +/* + * Process loop function, see fg_main.c + */ +FGAPI void FGAPIENTRY glutMainLoop( void ); + +/* + * Window management functions, see fg_window.c + */ +FGAPI int FGAPIENTRY glutCreateWindow( const char* title ); +FGAPI int FGAPIENTRY glutCreateSubWindow( int window, int x, int y, int width, int height ); +FGAPI void FGAPIENTRY glutDestroyWindow( int window ); +FGAPI void FGAPIENTRY glutSetWindow( int window ); +FGAPI int FGAPIENTRY glutGetWindow( void ); +FGAPI void FGAPIENTRY glutSetWindowTitle( const char* title ); +FGAPI void FGAPIENTRY glutSetIconTitle( const char* title ); +FGAPI void FGAPIENTRY glutReshapeWindow( int width, int height ); +FGAPI void FGAPIENTRY glutPositionWindow( int x, int y ); +FGAPI void FGAPIENTRY glutShowWindow( void ); +FGAPI void FGAPIENTRY glutHideWindow( void ); +FGAPI void FGAPIENTRY glutIconifyWindow( void ); +FGAPI void FGAPIENTRY glutPushWindow( void ); +FGAPI void FGAPIENTRY glutPopWindow( void ); +FGAPI void FGAPIENTRY glutFullScreen( void ); + +/* + * Display-related functions, see fg_display.c + */ +FGAPI void FGAPIENTRY glutPostWindowRedisplay( int window ); +FGAPI void FGAPIENTRY glutPostRedisplay( void ); +FGAPI void FGAPIENTRY glutSwapBuffers( void ); + +/* + * Mouse cursor functions, see fg_cursor.c + */ +FGAPI void FGAPIENTRY glutWarpPointer( int x, int y ); +FGAPI void FGAPIENTRY glutSetCursor( int cursor ); + +/* + * Overlay stuff, see fg_overlay.c + */ +FGAPI void FGAPIENTRY glutEstablishOverlay( void ); +FGAPI void FGAPIENTRY glutRemoveOverlay( void ); +FGAPI void FGAPIENTRY glutUseLayer( GLenum layer ); +FGAPI void FGAPIENTRY glutPostOverlayRedisplay( void ); +FGAPI void FGAPIENTRY glutPostWindowOverlayRedisplay( int window ); +FGAPI void FGAPIENTRY glutShowOverlay( void ); +FGAPI void FGAPIENTRY glutHideOverlay( void ); + +/* + * Menu stuff, see fg_menu.c + */ +FGAPI int FGAPIENTRY glutCreateMenu( void (* callback)( int menu ) ); +FGAPI void FGAPIENTRY glutDestroyMenu( int menu ); +FGAPI int FGAPIENTRY glutGetMenu( void ); +FGAPI void FGAPIENTRY glutSetMenu( int menu ); +FGAPI void FGAPIENTRY glutAddMenuEntry( const char* label, int value ); +FGAPI void FGAPIENTRY glutAddSubMenu( const char* label, int subMenu ); +FGAPI void FGAPIENTRY glutChangeToMenuEntry( int item, const char* label, int value ); +FGAPI void FGAPIENTRY glutChangeToSubMenu( int item, const char* label, int value ); +FGAPI void FGAPIENTRY glutRemoveMenuItem( int item ); +FGAPI void FGAPIENTRY glutAttachMenu( int button ); +FGAPI void FGAPIENTRY glutDetachMenu( int button ); + +/* + * Global callback functions, see fg_callbacks.c + */ +FGAPI void FGAPIENTRY glutTimerFunc( unsigned int time, void (* callback)( int ), int value ); +FGAPI void FGAPIENTRY glutIdleFunc( void (* callback)( void ) ); + +/* + * Window-specific callback functions, see fg_callbacks.c + */ +FGAPI void FGAPIENTRY glutKeyboardFunc( void (* callback)( unsigned char, int, int ) ); +FGAPI void FGAPIENTRY glutSpecialFunc( void (* callback)( int, int, int ) ); +FGAPI void FGAPIENTRY glutReshapeFunc( void (* callback)( int, int ) ); +FGAPI void FGAPIENTRY glutVisibilityFunc( void (* callback)( int ) ); +FGAPI void FGAPIENTRY glutDisplayFunc( void (* callback)( void ) ); +FGAPI void FGAPIENTRY glutMouseFunc( void (* callback)( int, int, int, int ) ); +FGAPI void FGAPIENTRY glutMotionFunc( void (* callback)( int, int ) ); +FGAPI void FGAPIENTRY glutPassiveMotionFunc( void (* callback)( int, int ) ); +FGAPI void FGAPIENTRY glutEntryFunc( void (* callback)( int ) ); + +FGAPI void FGAPIENTRY glutKeyboardUpFunc( void (* callback)( unsigned char, int, int ) ); +FGAPI void FGAPIENTRY glutSpecialUpFunc( void (* callback)( int, int, int ) ); +FGAPI void FGAPIENTRY glutJoystickFunc( void (* callback)( unsigned int, int, int, int ), int pollInterval ); +FGAPI void FGAPIENTRY glutMenuStateFunc( void (* callback)( int ) ); +FGAPI void FGAPIENTRY glutMenuStatusFunc( void (* callback)( int, int, int ) ); +FGAPI void FGAPIENTRY glutOverlayDisplayFunc( void (* callback)( void ) ); +FGAPI void FGAPIENTRY glutWindowStatusFunc( void (* callback)( int ) ); + +FGAPI void FGAPIENTRY glutSpaceballMotionFunc( void (* callback)( int, int, int ) ); +FGAPI void FGAPIENTRY glutSpaceballRotateFunc( void (* callback)( int, int, int ) ); +FGAPI void FGAPIENTRY glutSpaceballButtonFunc( void (* callback)( int, int ) ); +FGAPI void FGAPIENTRY glutButtonBoxFunc( void (* callback)( int, int ) ); +FGAPI void FGAPIENTRY glutDialsFunc( void (* callback)( int, int ) ); +FGAPI void FGAPIENTRY glutTabletMotionFunc( void (* callback)( int, int ) ); +FGAPI void FGAPIENTRY glutTabletButtonFunc( void (* callback)( int, int, int, int ) ); + +/* + * State setting and retrieval functions, see fg_state.c + */ +FGAPI int FGAPIENTRY glutGet( GLenum query ); +FGAPI int FGAPIENTRY glutDeviceGet( GLenum query ); +FGAPI int FGAPIENTRY glutGetModifiers( void ); +FGAPI int FGAPIENTRY glutLayerGet( GLenum query ); + +/* + * Font stuff, see fg_font.c + */ +FGAPI void FGAPIENTRY glutBitmapCharacter( void* font, int character ); +FGAPI int FGAPIENTRY glutBitmapWidth( void* font, int character ); +FGAPI void FGAPIENTRY glutStrokeCharacter( void* font, int character ); +FGAPI int FGAPIENTRY glutStrokeWidth( void* font, int character ); +FGAPI GLfloat FGAPIENTRY glutStrokeWidthf( void* font, int character ); /* GLUT 3.8 */ +FGAPI int FGAPIENTRY glutBitmapLength( void* font, const unsigned char* string ); +FGAPI int FGAPIENTRY glutStrokeLength( void* font, const unsigned char* string ); +FGAPI GLfloat FGAPIENTRY glutStrokeLengthf( void* font, const unsigned char *string ); /* GLUT 3.8 */ + +/* + * Geometry functions, see fg_geometry.c + */ + +FGAPI void FGAPIENTRY glutWireCube( double size ); +FGAPI void FGAPIENTRY glutSolidCube( double size ); +FGAPI void FGAPIENTRY glutWireSphere( double radius, GLint slices, GLint stacks ); +FGAPI void FGAPIENTRY glutSolidSphere( double radius, GLint slices, GLint stacks ); +FGAPI void FGAPIENTRY glutWireCone( double base, double height, GLint slices, GLint stacks ); +FGAPI void FGAPIENTRY glutSolidCone( double base, double height, GLint slices, GLint stacks ); +FGAPI void FGAPIENTRY glutWireTorus( double innerRadius, double outerRadius, GLint sides, GLint rings ); +FGAPI void FGAPIENTRY glutSolidTorus( double innerRadius, double outerRadius, GLint sides, GLint rings ); +FGAPI void FGAPIENTRY glutWireDodecahedron( void ); +FGAPI void FGAPIENTRY glutSolidDodecahedron( void ); +FGAPI void FGAPIENTRY glutWireOctahedron( void ); +FGAPI void FGAPIENTRY glutSolidOctahedron( void ); +FGAPI void FGAPIENTRY glutWireTetrahedron( void ); +FGAPI void FGAPIENTRY glutSolidTetrahedron( void ); +FGAPI void FGAPIENTRY glutWireIcosahedron( void ); +FGAPI void FGAPIENTRY glutSolidIcosahedron( void ); + +/* + * Teapot rendering functions, found in fg_teapot.c + * NB: front facing polygons have clockwise winding, not counter clockwise + */ +FGAPI void FGAPIENTRY glutWireTeapot( double size ); +FGAPI void FGAPIENTRY glutSolidTeapot( double size ); + +/* + * Game mode functions, see fg_gamemode.c + */ +FGAPI void FGAPIENTRY glutGameModeString( const char* string ); +FGAPI int FGAPIENTRY glutEnterGameMode( void ); +FGAPI void FGAPIENTRY glutLeaveGameMode( void ); +FGAPI int FGAPIENTRY glutGameModeGet( GLenum query ); + +/* + * Video resize functions, see fg_videoresize.c + */ +FGAPI int FGAPIENTRY glutVideoResizeGet( GLenum query ); +FGAPI void FGAPIENTRY glutSetupVideoResizing( void ); +FGAPI void FGAPIENTRY glutStopVideoResizing( void ); +FGAPI void FGAPIENTRY glutVideoResize( int x, int y, int width, int height ); +FGAPI void FGAPIENTRY glutVideoPan( int x, int y, int width, int height ); + +/* + * Colormap functions, see fg_misc.c + */ +FGAPI void FGAPIENTRY glutSetColor( int color, GLfloat red, GLfloat green, GLfloat blue ); +FGAPI GLfloat FGAPIENTRY glutGetColor( int color, int component ); +FGAPI void FGAPIENTRY glutCopyColormap( int window ); + +/* + * Misc keyboard and joystick functions, see fg_misc.c + */ +FGAPI void FGAPIENTRY glutIgnoreKeyRepeat( int ignore ); +FGAPI void FGAPIENTRY glutSetKeyRepeat( int repeatMode ); +FGAPI void FGAPIENTRY glutForceJoystickFunc( void ); + +/* + * Misc functions, see fg_misc.c + */ +FGAPI int FGAPIENTRY glutExtensionSupported( const char* extension ); +FGAPI void FGAPIENTRY glutReportErrors( void ); + +/* Comment from glut.h of classic GLUT: + + Win32 has an annoying issue where there are multiple C run-time + libraries (CRTs). If the executable is linked with a different CRT + from the GLUT DLL, the GLUT DLL will not share the same CRT static + data seen by the executable. In particular, atexit callbacks registered + in the executable will not be called if GLUT calls its (different) + exit routine). GLUT is typically built with the + "/MD" option (the CRT with multithreading DLL support), but the Visual + C++ linker default is "/ML" (the single threaded CRT). + + One workaround to this issue is requiring users to always link with + the same CRT as GLUT is compiled with. That requires users supply a + non-standard option. GLUT 3.7 has its own built-in workaround where + the executable's "exit" function pointer is covertly passed to GLUT. + GLUT then calls the executable's exit function pointer to ensure that + any "atexit" calls registered by the application are called if GLUT + needs to exit. + + Note that the __glut*WithExit routines should NEVER be called directly. + To avoid the atexit workaround, #define GLUT_DISABLE_ATEXIT_HACK. */ + +/* to get the prototype for exit() */ +#include + +#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) && !defined(__WATCOMC__) +FGAPI void FGAPIENTRY __glutInitWithExit(int *argcp, char **argv, void (__cdecl *exitfunc)(int)); +FGAPI int FGAPIENTRY __glutCreateWindowWithExit(const char *title, void (__cdecl *exitfunc)(int)); +FGAPI int FGAPIENTRY __glutCreateMenuWithExit(void (* func)(int), void (__cdecl *exitfunc)(int)); +#ifndef FREEGLUT_BUILDING_LIB +#if defined(__GNUC__) +#define FGUNUSED __attribute__((unused)) +#else +#define FGUNUSED +#endif +static void FGAPIENTRY FGUNUSED glutInit_ATEXIT_HACK(int *argcp, char **argv) { __glutInitWithExit(argcp, argv, exit); } +#define glutInit glutInit_ATEXIT_HACK +static int FGAPIENTRY FGUNUSED glutCreateWindow_ATEXIT_HACK(const char *title) { return __glutCreateWindowWithExit(title, exit); } +#define glutCreateWindow glutCreateWindow_ATEXIT_HACK +static int FGAPIENTRY FGUNUSED glutCreateMenu_ATEXIT_HACK(void (* func)(int)) { return __glutCreateMenuWithExit(func, exit); } +#define glutCreateMenu glutCreateMenu_ATEXIT_HACK +#endif +#endif + +#ifdef __cplusplus + } +#endif + +/*** END OF FILE ***/ + +#endif /* __FREEGLUT_STD_H__ */ + diff --git a/include/GL/freeglut_ucall.h b/include/GL/freeglut_ucall.h new file mode 100644 index 0000000..1ef2ae7 --- /dev/null +++ b/include/GL/freeglut_ucall.h @@ -0,0 +1,113 @@ +#ifndef __FREEGLUT_UCALL_H__ +#define __FREEGLUT_UCALL_H__ + +/* + * freeglut_ucall.h + * + * Callbacks with user data arguments. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifdef __cplusplus + extern "C" { +#endif + +/* + * Menu stuff, see fg_menu.c + */ +FGAPI int FGAPIENTRY glutCreateMenuUcall( void (* callback)( int menu, void* user_data ), void* user_data ); + +/* + * Global callback functions, see fg_callbacks.c + */ +FGAPI void FGAPIENTRY glutTimerFuncUcall( unsigned int time, void (* callback)( int, void* ), int value, void* user_data ); +FGAPI void FGAPIENTRY glutIdleFuncUcall( void (* callback)( void* ), void* user_data ); + +/* + * Window-specific callback functions, see fg_callbacks.c + */ +FGAPI void FGAPIENTRY glutKeyboardFuncUcall( void (* callback)( unsigned char, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutSpecialFuncUcall( void (* callback)( int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutReshapeFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutVisibilityFuncUcall( void (* callback)( int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutDisplayFuncUcall( void (* callback)( void* ), void* user_data ); +FGAPI void FGAPIENTRY glutMouseFuncUcall( void (* callback)( int, int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutMotionFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutPassiveMotionFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutEntryFuncUcall( void (* callback)( int, void* ), void* user_data ); + +FGAPI void FGAPIENTRY glutKeyboardUpFuncUcall( void (* callback)( unsigned char, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutSpecialUpFuncUcall( void (* callback)( int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutJoystickFuncUcall( void (* callback)( unsigned int, int, int, int, void* ), int pollInterval, void* user_data ); +FGAPI void FGAPIENTRY glutMenuStatusFuncUcall( void (* callback)( int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutOverlayDisplayFuncUcall( void (* callback)( void* ), void* user_data ); +FGAPI void FGAPIENTRY glutWindowStatusFuncUcall( void (* callback)( int, void* ), void* user_data ); + +FGAPI void FGAPIENTRY glutSpaceballMotionFuncUcall( void (* callback)( int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutSpaceballRotateFuncUcall( void (* callback)( int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutSpaceballButtonFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutButtonBoxFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutDialsFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutTabletMotionFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutTabletButtonFuncUcall( void (* callback)( int, int, int, int, void* ), void* user_data ); + +FGAPI void FGAPIENTRY glutMouseWheelFuncUcall( void (* callback)( int, int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutPositionFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutCloseFuncUcall( void (* callback)( void* ), void* user_data ); +FGAPI void FGAPIENTRY glutWMCloseFuncUcall( void (* callback)( void* ), void* user_data ); +FGAPI void FGAPIENTRY glutMenuDestroyFuncUcall( void (* callback)( void* ), void* user_data ); + +/* + * Multi-touch/multi-pointer extensions + */ +FGAPI void FGAPIENTRY glutMultiEntryFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutMultiButtonFuncUcall( void (* callback)( int, int, int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutMultiMotionFuncUcall( void (* callback)( int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutMultiPassiveFuncUcall( void (* callback)( int, int, int, void* ), void* user_data ); + +/* + * Initialization functions, see fg_init.c + */ +#include +FGAPI void FGAPIENTRY glutInitErrorFuncUcall( void (* callback)( const char *fmt, va_list ap, void* user_data ), void* user_data ); +FGAPI void FGAPIENTRY glutInitWarningFuncUcall( void (* callback)( const char *fmt, va_list ap, void* user_data ), void* user_data ); + +/* Mobile platforms lifecycle */ +FGAPI void FGAPIENTRY glutInitContextFuncUcall( void (* callback)( void* ), void* user_data ); +FGAPI void FGAPIENTRY glutAppStatusFuncUcall( void (* callback)( int, void* ), void* user_data ); + +/* + * Continued "hack" from GLUT applied to Ucall functions. + * For more info, see bottom of freeglut_std.h + */ + +/* to get the prototype for exit() */ +#include + +#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) && !defined(__WATCOMC__) +FGAPI int FGAPIENTRY __glutCreateMenuUcallWithExit(void(*func)(int, void*), void(__cdecl *exitfunc)(int), void* user_data); +#ifndef FREEGLUT_BUILDING_LIB +#if defined(__GNUC__) +#define FGUNUSED __attribute__((unused)) +#else +#define FGUNUSED +#endif +static int FGAPIENTRY FGUNUSED glutCreateMenuUcall_ATEXIT_HACK(void(*func)(int, void*), void* user_data) { return __glutCreateMenuUcallWithExit(func, exit, user_data); } +#define glutCreateMenuUcall glutCreateMenuUcall_ATEXIT_HACK +#endif +#endif + +#ifdef __cplusplus + } +#endif + +/*** END OF FILE ***/ + +#endif /* __FREEGLUT_UCALL_H__ */ + diff --git a/include/GL/glut.h b/include/GL/glut.h new file mode 100644 index 0000000..6191f77 --- /dev/null +++ b/include/GL/glut.h @@ -0,0 +1,21 @@ +#ifndef __GLUT_H__ +#define __GLUT_H__ + +/* + * glut.h + * + * The freeglut library include file + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "freeglut_std.h" + +/*** END OF FILE ***/ + +#endif /* __GLUT_H__ */ diff --git a/mingw_cross_toolchain.cmake b/mingw_cross_toolchain.cmake new file mode 100644 index 0000000..fa4ddba --- /dev/null +++ b/mingw_cross_toolchain.cmake @@ -0,0 +1,7 @@ +# CMake toolchain file, cf. README.mingw_cross +SET(CMAKE_SYSTEM_NAME Windows) +IF("${GNU_HOST}" STREQUAL "") + SET(GNU_HOST x86_64-w64-mingw32) +ENDIF() +SET(CMAKE_C_COMPILER ${GNU_HOST}-gcc) +SET(CMAKE_RC_COMPILER ${GNU_HOST}-windres) diff --git a/progs/demos/3dview/3dview.c b/progs/demos/3dview/3dview.c new file mode 100644 index 0000000..2599429 --- /dev/null +++ b/progs/demos/3dview/3dview.c @@ -0,0 +1,309 @@ +/* 3D view manipulation demo + * Written by John Tsiombikas + * + * Demonstrates how to use freeglut callbacks to manipulate a 3D view, similarly + * to how a modelling program or a model viewer would operate. + * + * Rotate: drag with the left mouse button. + * Scale: drag up/down with the right mouse button. + * Pan: drag with the middle mouse button. + * + * Press space to animate the scene and update the display continuously, press + * again to return to updating only when the view needs to change. + * Press escape or q to exit. + */ +#include +#include +#include +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#ifdef _MSC_VER +#pragma warning (disable: 4305 4244) +#endif + +static const char *helpprompt[] = {"Press F1 for help", 0}; +static const char *helptext[] = { + "Rotate: left mouse drag", + " Scale: right mouse drag up/down", + " Pan: middle mouse drag", + "", + "Toggle fullscreen: f", + "Toggle animation: space", + "Quit: escape", + 0 +}; + +void idle(void); +void display(void); +void print_help(void); +void reshape(int x, int y); +void keypress(unsigned char key, int x, int y); +void skeypress(int key, int x, int y); +void mouse(int bn, int st, int x, int y); +void motion(int x, int y); + +int win_width, win_height; +float cam_theta, cam_phi = 25, cam_dist = 8; +float cam_pan[3]; +int mouse_x, mouse_y; +int bnstate[8]; +int anim, help; +long anim_start; +long nframes; + +#ifndef GL_FRAMEBUFFER_SRGB +#define GL_FRAMEBUFFER_SRGB 0x8db9 +#endif + +#ifndef GL_MULTISAMPLE +#define GL_MULTISAMPLE 0x809d +#endif + +int main(int argc, char **argv) +{ + glutInit(&argc, argv); + glutInitWindowSize(800, 600); + glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); + glutCreateWindow("freeglut 3D view demo"); + + glutDisplayFunc(display); + glutReshapeFunc(reshape); + glutKeyboardFunc(keypress); + glutSpecialFunc(skeypress); + glutMouseFunc(mouse); + glutMotionFunc(motion); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + + glutMainLoop(); + return 0; +} + +void idle(void) +{ + glutPostRedisplay(); +} + +void display(void) +{ + long tm; + float lpos[] = {-1, 2, 3, 0}; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0, 0, -cam_dist); + glRotatef(cam_phi, 1, 0, 0); + glRotatef(cam_theta, 0, 1, 0); + glTranslatef(cam_pan[0], cam_pan[1], cam_pan[2]); + + glLightfv(GL_LIGHT0, GL_POSITION, lpos); + + glPushMatrix(); + if(anim) { + tm = glutGet(GLUT_ELAPSED_TIME) - anim_start; + glRotatef(tm / 10.0f, 1, 0, 0); + glRotatef(tm / 10.0f, 0, 1, 0); + } + glutSolidTorus(0.3, 1, 16, 24); + glPopMatrix(); + + glutSolidSphere(0.4, 16, 8); + + glPushMatrix(); + glTranslatef(-2.5, 0, 0); + glutSolidCube(1.5); + glPopMatrix(); + + glPushMatrix(); + glTranslatef(2.5, -1, 0); + glRotatef(-90, 1, 0, 0); + glutSolidCone(1.1, 2, 16, 2); + glPopMatrix(); + + glPushMatrix(); + glTranslatef(0, -0.5, 2.5); + glFrontFace(GL_CW); + glutSolidTeapot(1.0); + glFrontFace(GL_CCW); + glPopMatrix(); + + glBegin(GL_QUADS); + glNormal3f(0, 1, 0); + glVertex3f(-5, -1.3, 5); + glVertex3f(5, -1.3, 5); + glVertex3f(5, -1.3, -5); + glVertex3f(-5, -1.3, -5); + glEnd(); + + print_help(); + + glutSwapBuffers(); + nframes++; +} + +void print_help(void) +{ + int i; + const char *s, **text; + + glPushAttrib(GL_ENABLE_BIT); + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, win_width, 0, win_height, -1, 1); + + text = help ? helptext : helpprompt; + + for(i=0; text[i]; i++) { + glColor3f(0, 0.1, 0); + glRasterPos2f(7, win_height - (i + 1) * 20 - 2); + s = text[i]; + while(*s) { + glutBitmapCharacter(GLUT_BITMAP_9_BY_15, *s++); + } + glColor3f(0, 0.9, 0); + glRasterPos2f(5, win_height - (i + 1) * 20); + s = text[i]; + while(*s) { + glutBitmapCharacter(GLUT_BITMAP_9_BY_15, *s++); + } + } + + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + + glPopAttrib(); +} + +#define ZNEAR 0.5f +void reshape(int x, int y) +{ + float vsz, aspect = (float)x / (float)y; + win_width = x; + win_height = y; + + glViewport(0, 0, x, y); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + vsz = 0.4663f * ZNEAR; + glFrustum(-aspect * vsz, aspect * vsz, -vsz, vsz, 0.5, 500.0); +} + +void keypress(unsigned char key, int x, int y) +{ + static int fullscr; + static int prev_xsz, prev_ysz; + + switch(key) { + case 27: + case 'q': + exit(0); + break; + + case ' ': + anim ^= 1; + glutIdleFunc(anim ? idle : 0); + glutPostRedisplay(); + + if(anim) { + anim_start = glutGet(GLUT_ELAPSED_TIME); + nframes = 0; + } else { + long tm = glutGet(GLUT_ELAPSED_TIME) - anim_start; + long fps = (nframes * 100000) / tm; + printf("framerate: %ld.%ld fps\n", fps / 100, fps % 100); + } + break; + + case '\n': + case '\r': + if(!(glutGetModifiers() & GLUT_ACTIVE_ALT)) { + break; + } + case 'f': + fullscr ^= 1; + if(fullscr) { + prev_xsz = glutGet(GLUT_WINDOW_WIDTH); + prev_ysz = glutGet(GLUT_WINDOW_HEIGHT); + glutFullScreen(); + } else { + glutReshapeWindow(prev_xsz, prev_ysz); + } + break; + } +} + +void skeypress(int key, int x, int y) +{ + switch(key) { + case GLUT_KEY_F1: + help ^= 1; + glutPostRedisplay(); + + default: + break; + } +} + +void mouse(int bn, int st, int x, int y) +{ + int bidx = bn - GLUT_LEFT_BUTTON; + bnstate[bidx] = st == GLUT_DOWN; + mouse_x = x; + mouse_y = y; +} + +void motion(int x, int y) +{ + int dx = x - mouse_x; + int dy = y - mouse_y; + mouse_x = x; + mouse_y = y; + + if(!(dx | dy)) return; + + if(bnstate[0]) { + cam_theta += dx * 0.5; + cam_phi += dy * 0.5; + if(cam_phi < -90) cam_phi = -90; + if(cam_phi > 90) cam_phi = 90; + glutPostRedisplay(); + } + if(bnstate[1]) { + float up[3], right[3]; + float theta = cam_theta * M_PI / 180.0f; + float phi = cam_phi * M_PI / 180.0f; + + up[0] = -sin(theta) * sin(phi); + up[1] = -cos(phi); + up[2] = cos(theta) * sin(phi); + right[0] = cos(theta); + right[1] = 0; + right[2] = sin(theta); + + cam_pan[0] += (right[0] * dx + up[0] * dy) * 0.01; + cam_pan[1] += up[1] * dy * 0.01; + cam_pan[2] += (right[2] * dx + up[2] * dy) * 0.01; + glutPostRedisplay(); + } + if(bnstate[2]) { + cam_dist += dy * 0.1; + if(cam_dist < 0) cam_dist = 0; + glutPostRedisplay(); + } +} diff --git a/progs/demos/CallbackMaker/CallbackMaker.c b/progs/demos/CallbackMaker/CallbackMaker.c new file mode 100644 index 0000000..f1fa0f3 --- /dev/null +++ b/progs/demos/CallbackMaker/CallbackMaker.c @@ -0,0 +1,740 @@ +/* CallbackMaker.c */ +/* + * Program to invoke all the callbacks that "freeglut" supports + */ + + +#include +#include +#include +#include +#include + +static int sequence_number = 0 ; + +#define CALLBACKMAKER_N_WINDOWS 4 +int windows[CALLBACKMAKER_N_WINDOWS] = {0}; + +/* define status vars showing whether given callback has been called for given window */ +#define CALLBACK_CALLED_VAR(name) int name##_called[CALLBACKMAKER_N_WINDOWS] = {0} +#define CALLBACK_0V(name) int name##_seq[CALLBACKMAKER_N_WINDOWS] = {-1}; CALLBACK_CALLED_VAR(name) +#define CALLBACK_1V(name,field) int name##_##field[CALLBACKMAKER_N_WINDOWS] = {-1}; CALLBACK_0V(name) +#define CALLBACK_2V(name,field1,field2) int name##_##field2[CALLBACKMAKER_N_WINDOWS] = {-1}; CALLBACK_1V(name,field1) +#define CALLBACK_3V(name,field1,field2,field3) int name##_##field3[CALLBACKMAKER_N_WINDOWS] = {-1}; CALLBACK_2V(name,field1,field2) +#define CALLBACK_4V(name,field1,field2,field3,field4) int name##_##field4[CALLBACKMAKER_N_WINDOWS] = {-1}; CALLBACK_3V(name,field1,field2,field3) +#define CALLBACK_5V(name,field1,field2,field3,field4,field5) int name##_##field5[CALLBACKMAKER_N_WINDOWS] = {-1}; CALLBACK_4V(name,field1,field2,field3,field4) +CALLBACK_2V(reshape,width,height); +CALLBACK_2V(position,top,left); +CALLBACK_1V(visibility,vis); +CALLBACK_1V(windowStatus,state); +CALLBACK_4V(key,key,x,y,mod); +CALLBACK_4V(keyup,key,x,y,mod); +CALLBACK_4V(special,key,x,y,mod); +CALLBACK_4V(specialup,key,x,y,mod); +CALLBACK_4V(joystick,a,b,c,d); +CALLBACK_5V(mouse,button,updown,x,y,mod); +CALLBACK_5V(mousewheel,number,direction,x,y,mod); +CALLBACK_3V(motion,x,y,mod); +CALLBACK_3V(passivemotion,x,y,mod); +CALLBACK_1V(entry,state); +CALLBACK_0V(close); +/* menudestroy is registered on each menu, not a window */ +int menudestroy_called = 0; +/* menustatus and menustate are global callbacks, set for all menus at the same time */ +int menustatus_called = 0; +int menustate_called = 0; + +#define STRING_LENGTH 10 + +static void +bitmapPrintf (const char *fmt, ...) +{ + static char buf[256]; + va_list args; + + va_start(args, fmt); +#if defined(WIN32) && !defined(__CYGWIN__) + (void) _vsnprintf (buf, sizeof(buf), fmt, args); +#else + (void) vsnprintf (buf, sizeof(buf), fmt, args); +#endif + va_end(args); + glutBitmapString ( GLUT_BITMAP_HELVETICA_12, (unsigned char*)buf ) ; +} + +static int +getWindowAndIdx(int *winIdx) +{ + int window = glutGetWindow(); + + if (winIdx) + (*winIdx) = window==windows[0] ? 0 : + window==windows[1] ? 1 : + window==windows[2] ? 2 : 3; + + return window; +} + +static void +Mod2Text(int mods, char *text) +{ + if (mods&GLUT_ACTIVE_CTRL) + strcat(text,"CTRL"); + if (mods&GLUT_ACTIVE_SHIFT) + { + if (text[0]) + strcat(text,"+SHIFT"); + else + strcat(text,"SHIFT"); + } + if (mods&GLUT_ACTIVE_ALT) + { + if (text[0]) + strcat(text,"+ALT"); + else + strcat(text,"ALT"); + } + + if (!text[0]) + strcat(text,"none"); +} + +static void +Display(void) +{ + int winIdx; + int window = getWindowAndIdx(&winIdx); + glClear ( GL_COLOR_BUFFER_BIT ); + + glDisable ( GL_DEPTH_TEST ); + glMatrixMode ( GL_PROJECTION ); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, glutGet ( GLUT_WINDOW_WIDTH ), + 0, glutGet ( GLUT_WINDOW_HEIGHT ), -1, 1 ); + glMatrixMode ( GL_MODELVIEW ); + glPushMatrix (); + glLoadIdentity (); + glColor3ub ( 0, 0, 0 ); + glRasterPos2i ( 10, glutGet ( GLUT_WINDOW_HEIGHT ) - 20 ); /* 10pt margin above 10pt letters */ + + if ( entry_called[winIdx] ) + { + bitmapPrintf ( "Entry %d: %d\n", entry_seq[winIdx], entry_state[winIdx] ); + } + + if ( visibility_called[winIdx] ) + { + bitmapPrintf ( "Visibility %d: %d\n", visibility_seq[winIdx], visibility_vis[winIdx] ); + } + + if ( windowStatus_called[winIdx] ) + { + bitmapPrintf ( "WindowStatus %d: %d\n", windowStatus_seq[winIdx], windowStatus_state[winIdx] ); + } + + if ( reshape_called[winIdx] ) + { + bitmapPrintf ( "Reshape %d: %d %d\n", reshape_seq[winIdx], reshape_width[winIdx], reshape_height[winIdx] ); + } + + if ( position_called[winIdx] ) + { + bitmapPrintf ( "Position %d: %d %d\n", position_seq[winIdx], position_left[winIdx], position_top[winIdx] ); + } + + if ( key_called[winIdx] ) + { + char mods[50] = {0}; + Mod2Text(key_mod[winIdx],mods); + bitmapPrintf ( "Key %d: %d(%c) %d %d (mod: %s)\n", key_seq[winIdx], key_key[winIdx], key_key[winIdx], key_x[winIdx], key_y[winIdx], mods ); + } + + if ( keyup_called[winIdx] ) + { + char mods[50] = {0}; + Mod2Text(keyup_mod[winIdx],mods); + bitmapPrintf ( "Key Up %d: %d(%c) %d %d (mod: %s)\n", keyup_seq[winIdx], keyup_key[winIdx], keyup_key[winIdx], keyup_x[winIdx], keyup_y[winIdx], mods ); + } + + if ( special_called[winIdx] ) + { + char mods[50] = {0}; + Mod2Text(special_mod[winIdx],mods); + bitmapPrintf ( "Special %d: %d(%c) %d %d (mod: %s)\n", special_seq[winIdx], special_key[winIdx], special_key[winIdx], special_x[winIdx], special_y[winIdx], mods ); + } + + if ( specialup_called[winIdx] ) + { + char mods[50] = {0}; + Mod2Text(specialup_mod[winIdx],mods); + bitmapPrintf ( "Special Up %d: %d(%c) %d %d (mod: %s)\n", specialup_seq[winIdx], specialup_key[winIdx], specialup_key[winIdx], specialup_x[winIdx], specialup_y[winIdx], mods ); + } + + if ( joystick_called[winIdx] ) + { + bitmapPrintf ( "Joystick %d: %d %d %d %d\n", joystick_seq[winIdx], joystick_a[winIdx], joystick_b[winIdx], joystick_c[winIdx], joystick_d[winIdx] ); + } + + if ( mouse_called[winIdx] ) + { + char mods[50] = {0}; + Mod2Text(mouse_mod[winIdx],mods); + bitmapPrintf ( "Mouse %d: %d %d %d %d (mod: %s)\n", mouse_seq[winIdx], mouse_button[winIdx], mouse_updown[winIdx], mouse_x[winIdx], mouse_y[winIdx], mods ); + } + + if ( mousewheel_called[winIdx] ) + { + char mods[50] = {0}; + Mod2Text(mousewheel_mod[winIdx],mods); + bitmapPrintf ( "Mouse Wheel %d: %d %d %d %d (mod: %s)\n", mousewheel_seq[winIdx], mousewheel_number[winIdx], mousewheel_direction[winIdx], mousewheel_x[winIdx], mousewheel_y[winIdx], mods ); + } + + if ( motion_called[winIdx] ) + { + char mods[50] = {0}; + Mod2Text(motion_mod[winIdx],mods); + bitmapPrintf ( "Motion %d: %d %d (mod: %s)\n", motion_seq[winIdx], motion_x[winIdx], motion_y[winIdx], mods ); + } + + if ( passivemotion_called[winIdx] ) + { + char mods[50] = {0}; + Mod2Text(passivemotion_mod[winIdx],mods); + bitmapPrintf ( "Passive Motion %d: %d %d (mod: %s)\n", passivemotion_seq[winIdx], passivemotion_x[winIdx], passivemotion_y[winIdx], mods ); + } + + glMatrixMode ( GL_PROJECTION ); + glPopMatrix (); + glMatrixMode ( GL_MODELVIEW ); + glPopMatrix (); + glEnable ( GL_DEPTH_TEST ); + + printf ( "%6d Window %d Display Callback\n", + ++sequence_number, window ) ; + glutSwapBuffers(); +} + +static void +Warning(const char *fmt, va_list ap) +{ + printf("%6d Warning callback:\n",++sequence_number); + + /* print warning message */ + vprintf(fmt, ap); +} + +static void +Error(const char *fmt, va_list ap) +{ + char dummy_string[STRING_LENGTH]; + printf("%6d Error callback:\n",++sequence_number); + + /* print warning message */ + vprintf(fmt, ap); + printf("\n"); + + /* terminate program, after pause for input so user can see */ + printf ( "Please enter something to exit: " ); + fgets ( dummy_string, STRING_LENGTH, stdin ); + + /* Call exit directly as freeglut is messed + * up internally when an error is called. + */ + exit(1); +} + +static void +Reshape(int width, int height) +{ + int winIdx; + int window = getWindowAndIdx(&winIdx); + printf ( "%6d Window %d Reshape Callback: %d %d\n", + ++sequence_number, window, width, height ) ; + reshape_called[winIdx] = 1 ; + reshape_width[winIdx] = width ; + reshape_height[winIdx] = height ; + reshape_seq[winIdx] = sequence_number ; + glViewport(0,0,width,height); + glutPostRedisplay () ; +} + +static void +Position(int left, int top) +{ + int winIdx; + int window = getWindowAndIdx(&winIdx); + printf ( "%6d Window %d Position Callback: %d %d\n", + ++sequence_number, window, left, top ) ; + position_called[winIdx] = 1 ; + position_left[winIdx] = left ; + position_top[winIdx] = top ; + position_seq[winIdx] = sequence_number ; + glutPostRedisplay () ; +} + +static void +Key(unsigned char key, int x, int y) +{ + int winIdx; + int window = getWindowAndIdx(&winIdx); + printf ( "%6d Window %d Keyboard Callback: %d %d %d\n", + ++sequence_number, window, key, x, y ) ; + key_called[winIdx] = 1 ; + key_key[winIdx] = key ; + key_x[winIdx] = x ; + key_y[winIdx] = y ; + key_seq[winIdx] = sequence_number ; + key_mod[winIdx] = glutGetModifiers() ; + glutPostRedisplay () ; +} + +static void +KeyUp(unsigned char key, int x, int y) +{ + int winIdx; + int window = getWindowAndIdx(&winIdx); + printf ( "%6d Window %d Key Release Callback: %d %d %d\n", + ++sequence_number, window, key, x, y ) ; + keyup_called[winIdx] = 1 ; + keyup_key[winIdx] = key ; + keyup_x[winIdx] = x ; + keyup_y[winIdx] = y ; + keyup_seq[winIdx] = sequence_number ; + keyup_mod[winIdx] = glutGetModifiers() ; + glutPostRedisplay () ; +} + +static void +Special(int key, int x, int y) +{ + int winIdx; + int window = getWindowAndIdx(&winIdx); + printf ( "%6d Window %d Special Key Callback: %d %d %d\n", + ++sequence_number, window, key, x, y ) ; + special_called[winIdx] = 1 ; + special_key[winIdx] = key ; + special_x[winIdx] = x ; + special_y[winIdx] = y ; + special_seq[winIdx] = sequence_number ; + special_mod[winIdx] = glutGetModifiers() ; + glutPostRedisplay () ; +} + +static void +SpecialUp(int key, int x, int y) +{ + int winIdx; + int window = getWindowAndIdx(&winIdx); + printf ( "%6d Window %d Special Key Release Callback: %d %d %d\n", + ++sequence_number, window, key, x, y ) ; + specialup_called[winIdx] = 1 ; + specialup_key[winIdx] = key ; + specialup_x[winIdx] = x ; + specialup_y[winIdx] = y ; + specialup_seq[winIdx] = sequence_number ; + specialup_mod[winIdx] = glutGetModifiers() ; + glutPostRedisplay () ; +} + +static void +Joystick( unsigned int a, int b, int c, int d) /* Need meaningful names */ +{ + int winIdx; + int window = getWindowAndIdx(&winIdx); + printf ( "%6d Window %d Joystick Callback: %d %d %d %d\n", + ++sequence_number, window, a, b, c, d ) ; + joystick_called[winIdx] = 1 ; + joystick_a[winIdx] = a ; + joystick_b[winIdx] = b ; + joystick_c[winIdx] = c ; + joystick_d[winIdx] = d ; + joystick_seq[winIdx] = sequence_number ; + glutPostRedisplay () ; +} + +static void +Mouse(int button, int updown, int x, int y) +{ + int winIdx; + int window = getWindowAndIdx(&winIdx); + printf ( "%6d Window %d Mouse Click Callback: %d %d %d %d\n", + ++sequence_number, window, button, updown, x, y ) ; + mouse_called[winIdx] = 1 ; + mouse_button[winIdx] = button ; + mouse_updown[winIdx] = updown ; + mouse_x[winIdx] = x ; + mouse_y[winIdx] = y ; + mouse_seq[winIdx] = sequence_number ; + mouse_mod[winIdx] = glutGetModifiers() ; + glutPostRedisplay () ; +} + +static void +MouseWheel(int wheel_number, int direction, int x, int y) +{ + int winIdx; + int window = getWindowAndIdx(&winIdx); + printf ( "%6d Window %d Mouse Wheel Callback: %d %d %d %d\n", + ++sequence_number, window, wheel_number, direction, x, y ) ; + mousewheel_called[winIdx] = 1 ; + mousewheel_number[winIdx] = wheel_number ; + mousewheel_direction[winIdx] = direction ; + mousewheel_x[winIdx] = x ; + mousewheel_y[winIdx] = y ; + mousewheel_seq[winIdx] = sequence_number ; + mousewheel_mod[winIdx] = glutGetModifiers() ; + glutPostRedisplay () ; +} + +static void +Motion(int x, int y) +{ + int winIdx; + int window = getWindowAndIdx(&winIdx); + printf ( "%6d Window %d Mouse Motion Callback: %d %d\n", + ++sequence_number, window, x, y ) ; + motion_called[winIdx] = 1 ; + motion_x[winIdx] = x ; + motion_y[winIdx] = y ; + motion_seq[winIdx] = sequence_number ; + motion_mod[winIdx] = glutGetModifiers() ; + glutPostRedisplay () ; +} + +static void +PassiveMotion(int x, int y) +{ + int winIdx; + int window = getWindowAndIdx(&winIdx); + printf ( "%6d Window %d Mouse Passive Motion Callback: %d %d\n", + ++sequence_number, window, x, y ) ; + passivemotion_called[winIdx] = 1 ; + passivemotion_x[winIdx] = x ; + passivemotion_y[winIdx] = y ; + passivemotion_seq[winIdx] = sequence_number ; + passivemotion_mod[winIdx] = glutGetModifiers() ; + glutPostRedisplay () ; +} + +static void +Entry(int state) +{ + int winIdx; + int window = getWindowAndIdx(&winIdx); + printf ( "%6d Window %d Entry Callback: %d\n", + ++sequence_number, window, state ) ; + entry_called[winIdx] = 1 ; + entry_seq[winIdx] = sequence_number; + entry_state[winIdx] = state; + glutPostRedisplay () ; +} + +static void +Close(void) +{ + int window = getWindowAndIdx(NULL); + printf ( "%6d Window %d Close Callback\n", + ++sequence_number, window ) ; +} + +static void +OverlayDisplay(void) +{ + int window = getWindowAndIdx(NULL); + printf ( "%6d Window %d OverlayDisplay Callback\n", + ++sequence_number, window ) ; + glutPostRedisplay () ; +} + +static void +Visibility(int vis) +{ + int winIdx; + int window = getWindowAndIdx(&winIdx); + printf ( "%6d Window %d Visibility Callback: %d\n", + ++sequence_number, window, vis ) ; + visibility_called[winIdx] = 1 ; + visibility_vis[winIdx] = vis ; + visibility_seq[winIdx] = sequence_number ; + glutPostRedisplay () ; +} + +static void +WindowStatus(int state) +{ + int winIdx; + int window = getWindowAndIdx(&winIdx); + printf ( "%6d Window %d WindowStatus Callback: %d\n", + ++sequence_number, window, state ) ; + windowStatus_called[winIdx] = 1 ; + windowStatus_state[winIdx] = state ; + windowStatus_seq[winIdx] = sequence_number ; + glutPostRedisplay () ; +} + +static void +SpaceMotion(int x, int y, int z) +{ + int window = getWindowAndIdx(NULL); + printf ( "%6d Window %d SpaceMotion Callback: %d %d %d\n", + ++sequence_number, window, x, y, z ) ; + glutPostRedisplay () ; +} + +static void +SpaceRotation(int x, int y, int z) +{ + int window = getWindowAndIdx(NULL); + printf ( "%6d Window %d SpaceRotation Callback: %d %d %d\n", + ++sequence_number, window, x, y, z ) ; + glutPostRedisplay () ; +} + +static void +SpaceButton(int button, int updown) +{ + int window = getWindowAndIdx(NULL); + printf ( "%6d Window %d SpaceButton Callback: %d %d\n", + ++sequence_number, window, button, updown ) ; + glutPostRedisplay () ; +} + +static void +Dials(int x, int y) +{ + int window = getWindowAndIdx(NULL); + printf ( "%6d Window %d Dials Callback: %d %d\n", + ++sequence_number, window, x, y ) ; + glutPostRedisplay () ; +} + +static void +ButtonBox(int button, int updown) +{ + int window = getWindowAndIdx(NULL); + printf ( "%6d Window %d ButtonBox Callback: %d %d\n", + ++sequence_number, window, button, updown ) ; + glutPostRedisplay () ; +} + +static void +TabletMotion(int x, int y) +{ + int window = getWindowAndIdx(NULL); + printf ( "%6d Window %d TabletMotion Callback: %d %d\n", + ++sequence_number, window, x, y ) ; + glutPostRedisplay () ; +} + +static void +TabletButton(int button, int updown, int x, int y) +{ + int window = getWindowAndIdx(NULL); + printf ( "%6d Window %d TabletButton Callback: %d %d %d %d\n", + ++sequence_number, window, button, updown, x, y ) ; + glutPostRedisplay () ; +} + +static void +MenuCallback ( int value ) +{ + int menu = glutGetMenu(); + int window = getWindowAndIdx(NULL); + printf( "%6d Menu %d MenuCallback for menu opened in Window %d - value is %d\n", + ++sequence_number, menu, window, value ); +} + +static void +MenuDestroy( void ) +{ + int menu = glutGetMenu(); + menudestroy_called = 1 ; + printf ( "%6d Menu %d MenuDestroy Callback\n", + ++sequence_number, menu ) ; +} + +static void +MenuStatus( int status, int x, int y ) +{ + /* Menu and window for which this event is triggered are current when the callback is called */ + int menu = glutGetMenu(); + int window = getWindowAndIdx(NULL); + menustatus_called = 1 ; + printf ( "%6d Menu %d MenuStatus Callback in Window %d: %d %d %d\n", + ++sequence_number, menu, window, status, x, y ) ; + glutPostRedisplay () ; +} + + +static void +MenuState( int status ) +{ + /* Menu and window for which this event is triggered are current when the callback is called */ + int menu = glutGetMenu(); + int window = getWindowAndIdx(NULL); + menustate_called = 1 ; + printf ( "%6d Menu %d MenuState Callback in Window %d: %d\n", + ++sequence_number, menu, window, status) ; + glutPostRedisplay () ; +} + +static void Idle ( void ) +{ + ++sequence_number ; +} + +static void SetWindowCallbacks( int first ) +{ + /* All these callbacks are set for only the current window */ + glutDisplayFunc( Display ); + glutReshapeFunc( Reshape ); + glutPositionFunc( Position ); + glutKeyboardFunc( Key ); + glutSpecialFunc( Special ); + glutKeyboardUpFunc( KeyUp ); + glutSpecialUpFunc( SpecialUp ); + if (first) + glutJoystickFunc( Joystick, 100 ); + glutMouseFunc ( Mouse ) ; + glutMouseWheelFunc ( MouseWheel ) ; + glutMotionFunc ( Motion ) ; + glutPassiveMotionFunc ( PassiveMotion ) ; + glutEntryFunc ( Entry ) ; + glutCloseFunc ( Close ) ; + glutOverlayDisplayFunc ( OverlayDisplay ) ; + glutSpaceballMotionFunc ( SpaceMotion ) ; + glutSpaceballRotateFunc ( SpaceRotation ) ; + glutSpaceballButtonFunc ( SpaceButton ) ; + glutButtonBoxFunc ( ButtonBox ) ; + glutDialsFunc ( Dials ) ; + glutTabletMotionFunc ( TabletMotion ) ; + glutTabletButtonFunc ( TabletButton ) ; + /* glutVisibilityFunc is deprecated in favor of glutWindowStatusFunc, which provides more detail. + * Setting one of these overwrites the other (see docs). + */ + glutVisibilityFunc ( Visibility ); /* This will thus never be called, as glutWindowStatusFunc is set afterwards */ + glutWindowStatusFunc ( WindowStatus ) ; +} + +int +main(int argc, char *argv[]) +{ + char dummy_string[STRING_LENGTH]; + + int subMenuA, subMenuB; + + glutInitWarningFunc(Warning); + glutInitErrorFunc(Error); + glutInitWindowSize(500, 250); + glutInitWindowPosition ( 140, 140 ); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE ); + glutInit(&argc, argv); + /* global setting: mainloop does not return when a window is closed, only returns when all windows are closed */ + glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,GLUT_ACTION_CONTINUE_EXECUTION); + /* global setting: repeated keys generating by keeping the key pressed down are passed on to the keyboard callback */ + /* There are two functions to control this behavior, glutSetKeyRepeat to set it globally, and glutIgnoreKeyRepeat to set it per window. + * These two interact however. If key repeat is globally switched off (glutSetKeyRepeat(GLUT_KEY_REPEAT_OFF)), it cannot be overridden + * (switched back on) for a specific window with glutIgnoreKeyRepeat. However, if key repeat is globally switched on + * (glutSetKeyRepeat(GLUT_KEY_REPEAT_ON)), it can be overridden (switched off) with glutIgnoreKeyRepeat on a per-window basis. That is + * what we demonstrate here. + */ + glutSetKeyRepeat(GLUT_KEY_REPEAT_ON); + + /* Set other global callback (global as in not associated with any specific menu or window) */ + glutIdleFunc ( Idle ); + glutMenuStatusFunc ( MenuStatus ); + glutMenuStateFunc ( MenuState ); /* Note that glutMenuStatusFunc is an enhanced version of the deprecated glutMenuStateFunc. */ + + + /* Open first window */ + windows[0] = glutCreateWindow( "Callback Demo" ); + printf ( "Creating window %d as 'Callback Demo'\n", windows[0] ) ; + + glClearColor(1.0, 1.0, 1.0, 1.0); + + /* callbacks, settings and menus for this window */ + SetWindowCallbacks( 1 ); + glutIgnoreKeyRepeat(GL_TRUE); + glutSetIconTitle("Icon Test - Callback Demo"); + + subMenuA = glutCreateMenu( MenuCallback ); + glutAddMenuEntry( "Sub menu A1 (01)", 11 ); + glutAddMenuEntry( "Sub menu A2 (02)", 12 ); + glutAddMenuEntry( "Sub menu A3 (03)", 13 ); + glutMenuDestroyFunc ( MenuDestroy ); /* callback specific to this menu */ + /* Change font for this menu */ + glutSetMenuFont(subMenuA, GLUT_BITMAP_HELVETICA_12); + + subMenuB = glutCreateMenu( MenuCallback ); + glutAddMenuEntry( "Sub menu B1 (04)", 14 ); + glutAddMenuEntry( "Sub menu B2 (05)", 15 ); + glutAddMenuEntry( "Sub menu B3 (06)", 16 ); + glutAddSubMenu( "Going to sub menu A", subMenuA ); + glutMenuDestroyFunc ( MenuDestroy ); /* callback specific to this menu */ + glutSetMenuFont(subMenuB, GLUT_BITMAP_9_BY_15); + + glutCreateMenu( MenuCallback ); + glutAddMenuEntry( "Entry one", 21 ); + glutAddMenuEntry( "Entry two", 22 ); + glutAddMenuEntry( "Entry three", 23 ); + glutAddMenuEntry( "Entry four", 24 ); + glutAddMenuEntry( "Entry five", 25 ); + glutAddSubMenu( "Enter sub menu A", subMenuA ); + glutAddSubMenu( "Enter sub menu B", subMenuB ); + glutMenuDestroyFunc ( MenuDestroy ); /* callback specific to this menu */ + + glutAttachMenu( GLUT_LEFT_BUTTON ); + + + /* Position second window right next to the first */ + glutInitWindowPosition ( 140+500+2*glutGet(GLUT_WINDOW_BORDER_WIDTH), 140 ); + glutInitWindowSize(600, 600); + windows[1] = glutCreateWindow( "Second Window" ); + printf ( "Creating window %d as 'Second Window'\n", windows[1] ) ; + + glClearColor(1.0, 1.0, 1.0, 1.0); + + /* callbacks, settings and menus for this window */ + SetWindowCallbacks( 0 ); + glutIgnoreKeyRepeat(GL_TRUE); + + glutSetMenu(subMenuB); + glutAttachMenu( GLUT_RIGHT_BUTTON ); + + + /* position a third window as a subwindow of the second */ + windows[2] = glutCreateSubWindow(windows[1],0,300,600,300); + printf ( "Creating window %d as subwindow to 'Second Window'\n", windows[2] ) ; + + glClearColor(0.7f, 0.7f, 0.7f, 1.0); + + /* callbacks, settings and menus for this window */ + SetWindowCallbacks( 0 ); + glutSetCursor(GLUT_CURSOR_CROSSHAIR); /* Cursors are per window */ + + glutSetMenu(subMenuA); + glutAttachMenu( GLUT_RIGHT_BUTTON ); + + + /* position a fourth window as a subsubwindow (grandchild) of the second */ + windows[3] = glutCreateSubWindow(windows[2],300,0,300,300); + printf ( "Creating window %d as subsubwindow to 'Second Window'\n", windows[3] ) ; + + glClearColor(0.4f, 0.4f, 0.4f, 1.0); + + /* callbacks and menus for this window */ + SetWindowCallbacks( 0 ); + glutSetCursor(GLUT_CURSOR_INHERIT); /* Inherit cursor look from parent (this is default on window creation) - comment the below to see in action */ + glutSetCursor(GLUT_CURSOR_CYCLE); + + + printf ( "Please enter something to continue: " ); + fgets ( dummy_string, STRING_LENGTH, stdin ); + + glutMainLoop(); + + printf ( "Back from the 'freeglut' main loop\n" ) ; + + return EXIT_SUCCESS; +} diff --git a/progs/demos/Fractals/fractals.c b/progs/demos/Fractals/fractals.c new file mode 100644 index 0000000..2c7fcce --- /dev/null +++ b/progs/demos/Fractals/fractals.c @@ -0,0 +1,342 @@ +/* fractals.c */ +/* + * Program to draw a fractal by Michael Barnsley's deterministic algorithm. + * Algorithm: + * (1) Define the affine transformations (of the form r(i+1) = A r(i) + b ) + * (2) Find the stationary point for each transformation + * (3) To draw: + * - If you are at the lowest level, draw lines connecting all the stationary points + * - If not, call the draw function recursively with each affine transformation applied + */ + +/* + * User Commands: + * +,- - increment/decrement number of levels + * PgUp, PgDn - increase/decrease scaling + * Arrow keys - translate viewing section + * r - reset view + * Escape - quit + */ + +#include +#include +#include +#include +#include +#define FGH_PI 3.14159265358979323846 + +typedef struct +{ + double a00, a01, a10, a11 ; /* Transformation matrix */ + double b0, b1 ; /* Constant vector added on */ + double statx, staty ; /* Coordinates of the stationary point */ +} +AffineTrans ; + +/* Number of levels to draw the fractal */ +static int num_levels = 4 ; + +/* The definition of the fractal */ +static int num_trans ; +static AffineTrans *affine ; + +/* Flag telling us to keep executing the main loop */ +static int continue_in_main_loop = 1; + +/* the window title */ +char window_title [ 80 ] ; + +/* The amount the view is translated and scaled */ +double xwin = 0.0, ywin = 0.0 ; +double scale_factor = 1.0 ; + +static void draw_level ( int num, double m00, double m01, double m10, double m11, double n0, double n1 ) +{ + /* Draw a fractal transformed by "M", "N" as passed in */ + int i ; + + if ( num == 0 ) + { + double x0 = m00 * affine[0].statx + m01 * affine[0].staty + n0 ; + double y0 = m10 * affine[0].statx + m11 * affine[0].staty + n1 ; + + for ( i = 1; i < num_trans; i++ ) + { + double x1 = m00 * affine[i].statx + m01 * affine[i].staty + n0 ; + double y1 = m10 * affine[i].statx + m11 * affine[i].staty + n1 ; + + glVertex2d ( x0, y0 ) ; + glVertex2d ( x1, y1 ) ; + + x0 = x1 ; + y0 = y1 ; + } + } + else + { + /* Map each affine transformation in the fractal through the one passed in and call "draw_level" */ + + for ( i = 0; i < num_trans; i++ ) + { + draw_level ( num-1, m00*affine[i].a00+m01*affine[i].a10, m00*affine[i].a01+m01*affine[i].a11, + m10*affine[i].a00+m11*affine[i].a10, m10*affine[i].a01+m11*affine[i].a11, + m00*affine[i].b0 +m01*affine[i].b1 + n0, m10*affine[i].b0 +m11*affine[i].b1 + n1 ) ; + } + } +} + +static void +Display(void) +{ + glClear( GL_COLOR_BUFFER_BIT ); + + /* the curve */ + glPushMatrix(); + glScalef(2.5, 2.5, 2.5); + + glColor4f(0.0, 0.0, 0.0, 1.0); + glBegin ( GL_LINES ) ; + draw_level ( num_levels, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 ); + glEnd () ; + + glPopMatrix(); + glutSwapBuffers(); +} + +static void +Reshape(int width, int height) +{ + float ar; + glViewport ( 0, 0, width, height ) ; + glMatrixMode ( GL_PROJECTION ) ; + glLoadIdentity(); + ar = (float) width / (float) height ; + if( ar > 1 ) + glFrustum ( -ar, ar, -1.0, 1.0, 2.0, 100.0 ) ; + else + glFrustum ( -1.0, 1.0, -1/ar, 1/ar, 2.0, 100.0 ); + glMatrixMode ( GL_MODELVIEW ) ; + glLoadIdentity () ; + xwin = -1.0 ; + ywin = 0.0 ; + glTranslated ( xwin, ywin, -5.0 ) ; +} + +static void +Key(unsigned char key, int x, int y) +{ + int need_redisplay = 1; + + switch (key) { + case 27: /* Escape key */ + continue_in_main_loop = 0 ; + break; + + case '+' : + ++num_levels ; + break ; + + case '-' : + if ( num_levels > 0 ) + --num_levels ; + break ; + + case 'r' : case 'R' : + glMatrixMode ( GL_MODELVIEW ) ; + glLoadIdentity(); + xwin = -1.0 ; + ywin = 0.0 ; + glTranslated ( xwin, ywin, -5.0 ) ; + break ; + + default: + need_redisplay = 0; + break; + } + if (need_redisplay) + glutPostRedisplay(); +} + +static void +Special(int key, int x, int y) +{ + int need_redisplay = 1; + + switch (key) { + case GLUT_KEY_UP : + glMatrixMode ( GL_MODELVIEW ) ; + ywin += 0.1 * scale_factor ; + glTranslated ( 0.0, 0.1 * scale_factor, 0.0 ) ; + break ; + + case GLUT_KEY_DOWN : + glMatrixMode ( GL_MODELVIEW ) ; + ywin -= 0.1 * scale_factor ; + glTranslated ( 0.0, -0.1 * scale_factor, 0.0 ) ; + break ; + + case GLUT_KEY_LEFT : + glMatrixMode ( GL_MODELVIEW ) ; + xwin -= 0.1 * scale_factor ; + glTranslated ( -0.1 * scale_factor, 0.0, 0.0 ) ; + break ; + + case GLUT_KEY_RIGHT : + glMatrixMode ( GL_MODELVIEW ) ; + xwin += 0.1 * scale_factor ; + glTranslated ( 0.1 * scale_factor, 0.0, 0.0 ) ; + break ; + + case GLUT_KEY_PAGE_UP : + glMatrixMode ( GL_MODELVIEW ) ; + glTranslated ( -xwin, -ywin, 0.0 ) ; + glScaled ( 1.25, 1.25, 1.25 ) ; + glTranslated ( xwin, ywin, 0.0 ) ; + scale_factor *= 0.8 ; + break ; + + case GLUT_KEY_PAGE_DOWN : + glMatrixMode ( GL_MODELVIEW ) ; + glTranslated ( -xwin, -ywin, 0.0 ) ; + glScaled ( 0.8, 0.8, 0.8 ) ; + glTranslated ( xwin, ywin, 0.0 ) ; + scale_factor *= 1.25 ; + break ; + + default: + need_redisplay = 0; + break; + } + if (need_redisplay) + glutPostRedisplay(); +} + + +static void +checkedFGets ( char *s, int size, FILE *stream ) +{ + if ( fgets ( s, size, stream ) == NULL ) { + fprintf ( stderr, "fgets failed\n"); + exit ( EXIT_FAILURE ); + } +} + + +void readConfigFile ( char *fnme ) +{ + FILE *fptr = fopen ( fnme, "rt" ) ; + int i ; + char inputline [ 256 ] ; + + if ( fptr ) + { + /* Read a header line */ + checkedFGets ( inputline, sizeof ( inputline ), fptr ) ; + + /* Read a comment line */ + checkedFGets ( inputline, sizeof ( inputline ), fptr ) ; + + /* Read the window title */ + checkedFGets ( inputline, sizeof ( inputline ), fptr ) ; + /* We assume here that this line will not exceed 79 characters plus a + newline (window_title is 80 characters long). That'll cause a buffer + overflow. For a simple program like this, though, we're letting it + slide! + */ + sscanf ( inputline, "%[a-zA-Z0-9!@#$%^&*()+=/\\_-\" ]", window_title ) ; + + /* Read a comment line */ + checkedFGets ( inputline, sizeof ( inputline ), fptr ) ; + + /* Read the number of affine transformations */ + checkedFGets ( inputline, sizeof ( inputline ), fptr ) ; + sscanf ( inputline, "%d", &num_trans ) ; + + affine = (AffineTrans *)malloc ( num_trans * sizeof(AffineTrans) ) ; + + /* Read a comment line */ + checkedFGets ( inputline, sizeof ( inputline ), fptr ) ; + + for ( i = 0; i < num_trans; i++ ) + { + /* Read an affine transformation definition */ + checkedFGets ( inputline, sizeof ( inputline ), fptr ) ; + sscanf ( inputline, "%lf %lf %lf %lf %lf %lf", &affine[i].a00, &affine[i].a01, + &affine[i].a10, &affine[i].a11, &affine[i].b0, &affine[i].b1 ) ; + } + } + else /* No data file, set a default */ + { + printf ( "ERROR opening file <%s>\n", fnme ) ; + strcpy ( window_title, "Koch Snowflake" ) ; + num_trans = 4 ; + affine = (AffineTrans *)malloc ( num_trans * sizeof(AffineTrans) ) ; + affine[0].a00 = 1/3. ; affine[0].a01 = 0.00 ; affine[0].a10 = 0.00 ; affine[0].a11 = 1/3. ; + affine[0].b0 = 0.0 ; affine[0].b1 = 0.0 ; + + affine[1].a00 = 1/6. ; affine[1].a01 = -1/3.*sin(FGH_PI/3.) ; affine[1].a10 = 1/3.*sin(FGH_PI/3.) ; affine[1].a11 = 1/6. ; + affine[1].b0 = 1/3. ; affine[1].b1 = 0.0 ; + + affine[2].a00 = 1/6. ; affine[2].a01 = -1/3.*sin(-FGH_PI/3.) ; affine[2].a10 = 1/3.*sin(-FGH_PI/3.) ; affine[2].a11 = 1/6. ; + affine[2].b0 = 0.5 ; affine[2].b1 = sqrt(3)/6. ; + + affine[3].a00 = 1/3. ; affine[3].a01 = 0.00 ; affine[3].a10 = 0.00 ; affine[3].a11 = 1/3. ; + affine[3].b0 = 2/3. ; affine[3].b1 = 0.0 ; + } + + for ( i = 0; i < num_trans; i++ ) + { + double m00, m01, m10, m11 ; /* Matrix "I" minus "A" */ + double determ ; /* Determinant of this matrix */ + + /* Calculate the stationary point */ + + m00 = 1.0 - affine[i].a00 ; + m01 = - affine[i].a01 ; + m10 = - affine[i].a10 ; + m11 = 1.0 - affine[i].a11 ; + + determ = m00 * m11 - m01 * m10 ; + + if ( fabs ( determ ) > 1.e-6 ) + { + affine[i].statx = ( m11 * affine[i].b0 - m01 * affine[i].b1 ) / determ ; + affine[i].staty = ( -m10 * affine[i].b0 + m00 * affine[i].b1 ) / determ ; + } + else + affine[i].statx = affine[i].staty = 0.0 ; + } +} + +int +main(int argc, char *argv[]) +{ + glutInitWindowSize(500, 250); + glutInitWindowPosition ( 140, 140 ); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE ); + glutInit(&argc, argv); + + if ( argc > 1 ) + readConfigFile ( argv[1] ) ; + else + readConfigFile ( "fractals.dat" ) ; + + glutCreateWindow( window_title ); + + glClearColor(1.0, 1.0, 1.0, 1.0); + + glutReshapeFunc(Reshape); + glutKeyboardFunc(Key); + glutSpecialFunc(Special); + glutDisplayFunc(Display); + +#ifdef WIN32 +#endif + + while ( continue_in_main_loop ) + glutMainLoopEvent(); + + printf ( "Back from the 'freeglut' main loop\n" ) ; + + return 0; /* ANSI C requires main to return int. */ +} diff --git a/progs/demos/Fractals/fractals.dat b/progs/demos/Fractals/fractals.dat new file mode 100644 index 0000000..6a32de6 --- /dev/null +++ b/progs/demos/Fractals/fractals.dat @@ -0,0 +1,10 @@ +Koch Snowflake Fractal +Title of window +"Koch Snowflake" +Number of transformations +4 + A00 A01 A10 A11 B0 B1 +0.33333 0.0 0.0 0.33333 0.0 0.0 +0.16667 -.28868 0.28868 0.16667 0.33333 0.0 +0.16667 0.28868 -.28868 0.16667 0.5 0.28868 +0.33333 0.0 0.0 0.33333 0.66667 0.0 diff --git a/progs/demos/Fractals_random/fractals.dat b/progs/demos/Fractals_random/fractals.dat new file mode 100644 index 0000000..6a32de6 --- /dev/null +++ b/progs/demos/Fractals_random/fractals.dat @@ -0,0 +1,10 @@ +Koch Snowflake Fractal +Title of window +"Koch Snowflake" +Number of transformations +4 + A00 A01 A10 A11 B0 B1 +0.33333 0.0 0.0 0.33333 0.0 0.0 +0.16667 -.28868 0.28868 0.16667 0.33333 0.0 +0.16667 0.28868 -.28868 0.16667 0.5 0.28868 +0.33333 0.0 0.0 0.33333 0.66667 0.0 diff --git a/progs/demos/Fractals_random/fractals_random.c b/progs/demos/Fractals_random/fractals_random.c new file mode 100644 index 0000000..aa10641 --- /dev/null +++ b/progs/demos/Fractals_random/fractals_random.c @@ -0,0 +1,393 @@ +/* fractals_random.c */ +/* This demo shows a single-buffering "freeglut" example. */ + +/* + * Program to draw a fractal by Michael Barnsley's stochastic algorithm. + * Algorithm: + * (1) Define the affine transformations (of the form r(i+1) = A r(i) + b ) + * (2) Find the stationary point for the first transformation + * (3) To draw: + * - Pick a random integer between 1 and the number of transformations (inclusive) + * - Send the current point through the transformation to create the new current point + * - Plot the new current point + */ + +/* + * User Commands: + * PgUp, PgDn - increase/decrease scaling + * Arrow keys - translate viewing section + * r - reset view + * Escape - quit + */ + +#include +#include +#include +#include +#include +#define FGH_PI 3.14159265358979323846 +#ifdef _MSC_VER +/* DUMP MEMORY LEAKS */ +#include +#endif + +typedef struct +{ + double a00, a01, a10, a11 ; /* Transformation matrix */ + double b0, b1 ; /* Constant vector added on */ + double statx, staty ; /* Coordinates of the stationary point */ +} +AffineTrans ; + +/* Number of levels to draw the fractal */ +static int num_levels = 0 ; + +/* The definition of the fractal */ +static int num_trans ; +static AffineTrans *affine ; + +/* the window title */ +char window_title [ 80 ] ; + +/* The amount the view is translated */ +double xwin = 0.0, ywin = 0.0 ; +double scale_factor = 1.0 ; + +/* The current point */ +double current_x = 0.0, current_y = 0.0 ; + +/* Signals when a glClear is needed */ +static GLboolean needClear = GL_TRUE; + +static void draw_level ( int num, double m00, double m01, double m10, double m11, double n0, double n1 ) +{ + /* Draw a fractal transformed by "M", "N" as passed in */ + int i ; + + for ( i = 0; i < 10; i++ ) + { + int random = ( rand( ) >> 10 ) % num_trans; + double new_x = affine[random].a00 * current_x + affine[random].a01 * current_y + affine[random].b0 ; + double new_y = affine[random].a10 * current_x + affine[random].a11 * current_y + affine[random].b1 ; + + glVertex2d ( new_x, new_y ) ; + current_x = new_x ; + current_y = new_y ; + } +} + +static void +Display(void) +{ + if (needClear) { + glClear(GL_COLOR_BUFFER_BIT); + needClear = GL_FALSE; + } + + /* the curve */ + glPushMatrix(); + glScaled(2.5, 2.5, 2.5); + + glColor4f(0.0, 0.0, 0.0, 1.0); + glBegin ( GL_POINTS ) ; + draw_level ( num_levels, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 ); + glEnd () ; + + glPopMatrix(); + + glFlush(); + glutPostRedisplay(); /* Needed so that this function will be called again */ +} + +static void +Reshape(int width, int height) +{ + float ar; + glViewport(0, 0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + ar = (float) width / (float) height; + if( ar > 1 ) + glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0); + else + glFrustum(-1.0, 1.0, -1/ar, 1/ar, 2.0, 100.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + xwin = -1.0 ; + ywin = 0.0 ; + glTranslated(xwin, ywin, -5.0); + needClear = GL_TRUE; +} + +static void +Key(unsigned char key, int x, int y) +{ + int changed_settings = 1; + + switch (key) { + case 27: /* Escape key */ + glutLeaveMainLoop (); + break; + + case 'r' : case 'R' : + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + xwin = -1.0 ; + ywin = 0.0 ; + glTranslated(xwin, ywin, -5.0); + break ; + + default: + changed_settings = 0; + break; + } + if (changed_settings) + needClear = GL_TRUE; + glutPostRedisplay(); +} + +static void +Special(int key, int x, int y) +{ + int changed_settings = 1; + + switch (key) { + case GLUT_KEY_UP : + glMatrixMode(GL_MODELVIEW); + ywin += 0.1 * scale_factor ; + glTranslated(0.0, 0.1 * scale_factor, 0.0); + break ; + + case GLUT_KEY_DOWN : + glMatrixMode(GL_MODELVIEW); + ywin -= 0.1 * scale_factor ; + glTranslated(0.0, -0.1 * scale_factor, 0.0); + break ; + + case GLUT_KEY_LEFT : + glMatrixMode(GL_MODELVIEW); + xwin -= 0.1 * scale_factor ; + glTranslated(-0.1 * scale_factor, 0.0, 0.0); + break ; + + case GLUT_KEY_RIGHT : + glMatrixMode(GL_MODELVIEW); + xwin += 0.1 * scale_factor ; + glTranslated(0.1 * scale_factor, 0.0, 0.0); + break ; + + case GLUT_KEY_PAGE_UP : + glMatrixMode(GL_MODELVIEW); + glTranslated ( -xwin, -ywin, 0.0 ) ; + glScaled(1.25, 1.25, 1.25); + glTranslated ( xwin, ywin, 0.0 ) ; + scale_factor *= 0.8 ; + break ; + + case GLUT_KEY_PAGE_DOWN : + glMatrixMode(GL_MODELVIEW); + glTranslated ( -xwin, -ywin, 0.0 ) ; + glScaled(0.8, 0.8, 0.8); + glTranslated ( xwin, ywin, 0.0 ) ; + scale_factor *= 1.25 ; + break ; + + default: + changed_settings = 0; + break; + } + if (changed_settings) + needClear = GL_TRUE; + + glutPostRedisplay(); +} + + +static int mouse_x = 0, mouse_y = 0 ; +static int button_down = GLUT_DOWN ; + +static void +Mouse ( int button, int updown, int x, int y ) +{ + button_down = updown ; + + if ( updown == GLUT_DOWN ) + { + mouse_x = x ; + mouse_y = y ; + } +} + +static void +MouseMotion ( int x, int y ) +{ + int window_width = glutGet ( GLUT_WINDOW_WIDTH ) ; + int window_height = glutGet ( GLUT_WINDOW_HEIGHT ) ; + int window_size = ( window_width < window_height ) ? window_width : window_height ; + + double delta_x = 5.0 * (double)(x - mouse_x) / (double)(window_size) ; + double delta_y = 5.0 * (double)(y - mouse_y) / (double)(window_size) ; + + xwin += delta_x * scale_factor ; + ywin -= delta_y * scale_factor ; + glMatrixMode ( GL_MODELVIEW ) ; + glTranslated ( delta_x * scale_factor, -delta_y * scale_factor, 0.0 ) ; + + needClear = GL_TRUE; + glutPostRedisplay(); + + mouse_x = x ; + mouse_y = y ; +} + +static void +MouseWheel ( int wheel_number, int direction, int x, int y ) +{ + double scale = ( direction > 0 ) ? 1.25 : 0.8 ; + + glMatrixMode ( GL_MODELVIEW ) ; + glTranslated ( -xwin, -ywin, 0.0 ) ; + glScaled ( scale, scale, scale ) ; + glTranslated ( xwin, ywin, 0.0 ) ; + scale_factor /= scale ; + + needClear = GL_TRUE; + glutPostRedisplay(); +} + + +static void +checkedFGets ( char *s, int size, FILE *stream ) +{ + if ( fgets ( s, size, stream ) == NULL ) { + fprintf ( stderr, "fgets failed\n"); + exit ( EXIT_FAILURE ); + } +} + + +void readConfigFile ( char *fnme ) +{ + FILE *fptr = fopen ( fnme, "rt" ) ; + int i ; + char inputline [ 256 ] ; + + if ( fptr ) + { + /* Read a header line */ + checkedFGets ( inputline, sizeof ( inputline ), fptr ) ; + + /* Read a comment line */ + checkedFGets ( inputline, sizeof ( inputline ), fptr ) ; + + /* Read the window title */ + checkedFGets ( inputline, sizeof ( inputline ), fptr ) ; + /* We assume here that this line will not exceed 79 characters plus a + newline (window_title is 80 characters long). That'll cause a buffer + overflow. For a simple program like this, though, we're letting it + slide! + */ + sscanf ( inputline, "%[a-zA-Z0-9!@#$%^&*()+=/\\_-\" ]", window_title ) ; + + /* Read a comment line */ + checkedFGets ( inputline, sizeof ( inputline ), fptr ) ; + + /* Read the number of affine transformations */ + checkedFGets ( inputline, sizeof ( inputline ), fptr ) ; + sscanf ( inputline, "%d", &num_trans ) ; + + affine = (AffineTrans *)malloc ( num_trans * sizeof(AffineTrans) ) ; + + /* Read a comment line */ + checkedFGets ( inputline, sizeof ( inputline ), fptr ) ; + + for ( i = 0; i < num_trans; i++ ) + { + /* Read an affine transformation definition */ + checkedFGets ( inputline, sizeof ( inputline ), fptr ) ; + sscanf ( inputline, "%lf %lf %lf %lf %lf %lf", &affine[i].a00, &affine[i].a01, + &affine[i].a10, &affine[i].a11, &affine[i].b0, &affine[i].b1 ) ; + } + } + else /* No data file, set a default */ + { + printf ( "ERROR opening file <%s>\n", fnme ) ; + strcpy ( window_title, "Koch Snowflake" ) ; + num_trans = 4 ; + affine = (AffineTrans *)malloc ( num_trans * sizeof(AffineTrans) ) ; + affine[0].a00 = 1/3. ; affine[0].a01 = 0.00 ; affine[0].a10 = 0.00 ; affine[0].a11 = 1/3. ; + affine[0].b0 = 0.0 ; affine[0].b1 = 0.0 ; + + affine[1].a00 = 1/6. ; affine[1].a01 = -1/3.*sin(FGH_PI/3.) ; affine[1].a10 = 1/3.*sin(FGH_PI/3.) ; affine[1].a11 = 1/6. ; + affine[1].b0 = 1/3. ; affine[1].b1 = 0.0 ; + + affine[2].a00 = 1/6. ; affine[2].a01 = -1/3.*sin(-FGH_PI/3.) ; affine[2].a10 = 1/3.*sin(-FGH_PI/3.) ; affine[2].a11 = 1/6. ; + affine[2].b0 = 0.5 ; affine[2].b1 = sqrt(3)/6. ; + + affine[3].a00 = 1/3. ; affine[3].a01 = 0.00 ; affine[3].a10 = 0.00 ; affine[3].a11 = 1/3. ; + affine[3].b0 = 2/3. ; affine[3].b1 = 0.0 ; + } + + for ( i = 0; i < num_trans; i++ ) + { + double m00, m01, m10, m11 ; /* Matrix "I" minus "A" */ + double determ ; /* Determinant of this matrix */ + + /* Calculate the stationary point */ + + m00 = 1.0 - affine[i].a00 ; + m01 = - affine[i].a01 ; + m10 = - affine[i].a10 ; + m11 = 1.0 - affine[i].a11 ; + + determ = m00 * m11 - m01 * m10 ; + + if ( fabs ( determ ) > 1.e-6 ) + { + affine[i].statx = ( m11 * affine[i].b0 - m01 * affine[i].b1 ) / determ ; + affine[i].staty = ( -m10 * affine[i].b0 + m00 * affine[i].b1 ) / determ ; + } + else + affine[i].statx = affine[i].staty = 0.0 ; + } +} + +int +main(int argc, char *argv[]) +{ + glutInitDisplayMode( GLUT_RGB | GLUT_SINGLE ); + + glutInitWindowSize(500, 250); + glutInitWindowPosition ( 140, 140 ) ; + glutInit(&argc, argv); + + if ( argc > 1 ) + readConfigFile ( argv[1] ) ; + else + readConfigFile ( "fractals.dat" ) ; + + glutCreateWindow( window_title ); + + glClearColor(1.0, 1.0, 1.0, 1.0); + + glutReshapeFunc(Reshape); + glutKeyboardFunc(Key); + glutSpecialFunc(Special); + glutDisplayFunc(Display); + glutMouseFunc(Mouse); + glutMotionFunc(MouseMotion); + glutMouseWheelFunc(MouseWheel); + + glutMainLoop(); + + printf ( "Back from the 'freeglut' main loop\n" ) ; + + free ( affine ) ; + +#ifdef _MSC_VER + /* DUMP MEMORY LEAK INFORMATION */ + _CrtDumpMemoryLeaks () ; +#endif + + return 0; /* ANSI C requires main to return int. */ +} diff --git a/progs/demos/Lorenz/lorenz.c b/progs/demos/Lorenz/lorenz.c new file mode 100644 index 0000000..a3a61db --- /dev/null +++ b/progs/demos/Lorenz/lorenz.c @@ -0,0 +1,378 @@ +/* + * Lorenz Strange Attractor + * + * Written by John F. Fay in honor of the "freeglut" 2.0.0 release in July 2003 + * + * What it does: + * This program starts with two particles right next to each other. The particles + * move through a three-dimensional phase space governed by the following equations: + * dx/dt = sigma * ( y - x ) + * dy/dt = r * x - y + x * z + * dz/dt = x * y + b * z + * These are the Lorenz equations and define the "Lorenz Attractor." Any two particles + * arbitrarily close together will move apart as time increases, but their tracks are + * confined within a region of the space. + * + * Commands: + * Arrow keys: Rotate the view + * PgUp, PgDn: Zoom in and out + * Mouse click: Center on the nearest point on a particle trajectory + * + * 'r'/'R': Reset the simulation + * 'm'/'M': Modify the Lorenz parameters (in the text window) + * 's'/'S': Stop (the advancement in time) + * 'g'/'G': Go + * : Single-step + * : Quit + */ + +/* Include Files */ +#include +#include +#include +#include +#include +#include +#ifdef _MSC_VER +/* DUMP MEMORY LEAKS */ +#include +#endif + + +/************************************** Defined Constants ***************************************/ +/* Number of points to draw in the curves */ +#define NUM_POINTS 512 + +/* Angle to rotate when the user presses an arrow key */ +#define ROTATION_ANGLE 5.0 + +/* Amount to scale bu when the user presses PgUp or PgDn */ +#define SCALE_FACTOR 0.8 + + +/*************************************** Global Variables ***************************************/ +/* Lorenz Attractor variables */ +double s0 = 10.0, r0 = 28.0, b0 = 8.0/3.0 ; /* Default Lorenz attactor parameters */ +double time_step = 0.03 ; /* Time step in the simulation */ +double sigma = 10.0, r = 28.0, b = 8.0/3.0 ; /* Lorenz attactor parameters */ +double red_position[NUM_POINTS][3] ; /* Path of the red point */ +double grn_position[NUM_POINTS][3] ; /* Path of the green point */ +int array_index ; /* Position in *_position arrays of most recent point */ +double distance = 0.0 ; /* Distance between the two points */ + +/* GLUT variables */ +double yaw = 0.0, pit = 0.0 ; /* Euler angles of the viewing rotation */ +double scale = 1.0 ; /* Scale factor */ +double xcen = 0.0, ycen = 0.0, zcen = 0.0 ; /* Coordinates of the point looked at */ + +int animate = 1 ; /* 0 - stop, 1 = go, 2 = single-step */ + + +/******************************************* Functions ******************************************/ + +/* The Lorenz Attractor */ +void calc_deriv ( double position[3], double deriv[3] ) +{ + /* Calculate the Lorenz attractor derivatives */ + deriv[0] = sigma * ( position[1] - position[0] ) ; + deriv[1] = ( r + position[2] ) * position[0] - position[1] ; + deriv[2] = -position[0] * position[1] - b * position[2] ; +} + +void advance_in_time ( double time_step, double position[3], double new_position[3] ) +{ + /* Move a point along the Lorenz attractor */ + double deriv0[3], deriv1[3], deriv2[3], deriv3[3] ; + int i ; + memcpy ( new_position, position, 3 * sizeof(double) ) ; /* Save the present values */ + + /* First pass in a Fourth-Order Runge-Kutta integration method */ + calc_deriv ( position, deriv0 ) ; + for ( i = 0; i < 3; i++ ) + new_position[i] = position[i] + 0.5 * time_step * deriv0[i] ; + + /* Second pass */ + calc_deriv ( new_position, deriv1 ) ; + for ( i = 0; i < 3; i++ ) + new_position[i] = position[i] + 0.5 * time_step * deriv1[i] ; + + /* Third pass */ + calc_deriv ( position, deriv2 ) ; + for ( i = 0; i < 3; i++ ) + new_position[i] = position[i] + time_step * deriv2[i] ; + + /* Second pass */ + calc_deriv ( new_position, deriv3 ) ; + for ( i = 0; i < 3; i++ ) + new_position[i] = position[i] + 0.1666666666666666667 * time_step * + ( deriv0[i] + 2.0 * ( deriv1[i] + deriv2[i] ) + deriv3[i] ) ; +} + +static void +checkedFGets ( char *s, int size, FILE *stream ) +{ + if ( fgets ( s, size, stream ) == NULL ) { + fprintf ( stderr, "fgets failed\n"); + exit ( EXIT_FAILURE ); + } +} + + +/* GLUT callbacks */ + +#define INPUT_LINE_LENGTH 80 + +void key_cb ( unsigned char key, int x, int y ) +{ + int i ; + char inputline [ INPUT_LINE_LENGTH ] ; + + switch ( key ) + { + case 'r' : case 'R' : /* Reset the simulation */ + /* Reset the Lorenz parameters */ + sigma = s0 ; + b = b0 ; + r = r0 ; + /* Set an initial position */ + red_position[0][0] = (double)rand() / (double)RAND_MAX ; + red_position[0][1] = (double)rand() / (double)RAND_MAX ; + red_position[0][2] = (double)rand() / (double)RAND_MAX ; + grn_position[0][0] = (double)rand() / (double)RAND_MAX ; + grn_position[0][1] = (double)rand() / (double)RAND_MAX ; + grn_position[0][2] = (double)rand() / (double)RAND_MAX ; + array_index = 0 ; + /* Initialize the arrays */ + for ( i = 1; i < NUM_POINTS; i++ ) + { + memcpy ( red_position[i], red_position[0], 3 * sizeof(double) ) ; + memcpy ( grn_position[i], grn_position[0], 3 * sizeof(double) ) ; + } + + break ; + + case 'm' : case 'M' : /* Modify the Lorenz parameters */ + printf ( "Please enter new value for (default %f, currently %f): ", s0, sigma ) ; + checkedFGets ( inputline, sizeof ( inputline ), stdin ) ; + sscanf ( inputline, "%lf", &sigma ) ; + + printf ( "Please enter new value for (default %f, currently %f): ", b0, b ) ; + checkedFGets ( inputline, sizeof ( inputline ), stdin ) ; + sscanf ( inputline, "%lf", &b ) ; + + printf ( "Please enter new value for (default %f, currently %f): ", r0, r ) ; + checkedFGets ( inputline, sizeof ( inputline ), stdin ) ; + sscanf ( inputline, "%lf", &r ) ; + + break ; + + case 's' : case 'S' : /* Stop the animation */ + animate = 0 ; + break ; + + case 'g' : case 'G' : /* Start the animation */ + animate = 1 ; + break ; + + case ' ' : /* Spacebar: Single step */ + animate = 2 ; + break ; + + case 27 : /* Escape key */ + glutLeaveMainLoop () ; + break ; + } +} + +void special_cb ( int key, int x, int y ) +{ + switch ( key ) + { + case GLUT_KEY_UP : /* Rotate up a little */ + glRotated ( ROTATION_ANGLE, 0.0, 1.0, 0.0 ) ; + break ; + + case GLUT_KEY_DOWN : /* Rotate down a little */ + glRotated ( -ROTATION_ANGLE, 0.0, 1.0, 0.0 ) ; + break ; + + case GLUT_KEY_LEFT : /* Rotate left a little */ + glRotated ( ROTATION_ANGLE, 0.0, 0.0, 1.0 ) ; + break ; + + case GLUT_KEY_RIGHT : /* Rotate right a little */ + glRotated ( -ROTATION_ANGLE, 0.0, 0.0, 1.0 ) ; + break ; + + case GLUT_KEY_PAGE_UP : /* Zoom in a little */ + glScaled ( 1.0 / SCALE_FACTOR, 1.0 / SCALE_FACTOR, 1.0 / SCALE_FACTOR ) ; + break ; + + case GLUT_KEY_PAGE_DOWN : /* Zoom out a little */ + glScaled ( SCALE_FACTOR, SCALE_FACTOR, SCALE_FACTOR ) ; + break ; + } + + glutPostRedisplay () ; +} + +void mouse_cb ( int button, int updown, int x, int y ) +{ + if ( updown == GLUT_DOWN ) + { + /*double dist = 1.0e20 ; A very large number */ + /* The idea here is that we go into "pick" mode and pick the nearest point + to the mouse click position. Unfortunately I don't have the time to implement + it at the moment. */ + } +} + +void draw_curve ( int index, double position [ NUM_POINTS ][3] ) +{ + int i = index ; + + glBegin ( GL_LINE_STRIP ) ; + do + { + i = ( i == NUM_POINTS-1 ) ? 0 : i + 1 ; + glVertex3dv ( position[i] ) ; + } + while ( i != index ) ; + + glEnd () ; +} + +void bitmapPrintf (const char *fmt, ...) +{ + static char buf[256]; + va_list args; + + va_start(args, fmt); +#if defined(WIN32) && !defined(__CYGWIN__) + (void) _vsnprintf (buf, sizeof(buf), fmt, args); +#else + (void) vsnprintf (buf, sizeof(buf), fmt, args); +#endif + va_end(args); + glutBitmapString ( GLUT_BITMAP_HELVETICA_12, (unsigned char*)buf ) ; +} + +void display_cb ( void ) +{ + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + + glColor3d ( 1.0, 1.0, 1.0 ) ; /* White */ + /* Draw some axes */ + glBegin ( GL_LINES ) ; + glVertex3d ( 0.0, 0.0, 0.0 ) ; + glVertex3d ( 2.0, 0.0, 0.0 ) ; + glVertex3d ( 0.0, 0.0, 0.0 ) ; + glVertex3d ( 0.0, 1.0, 0.0 ) ; + glVertex3d ( 0.0, 0.0, 0.0 ) ; + glVertex3d ( 0.0, 0.0, 1.0 ) ; + glEnd () ; + + glColor3d ( 1.0, 0.0, 0.0 ) ; /* Red */ + draw_curve ( array_index, red_position ) ; + + glColor3d ( 0.0, 1.0, 0.0 ) ; /* Green */ + draw_curve ( array_index, grn_position ) ; + + /* Print the distance between the two points */ + glColor3d ( 1.0, 1.0, 1.0 ) ; /* White */ + glRasterPos2i ( 1, 1 ) ; + bitmapPrintf ( "Distance: %10.6f", distance ) ; + + glutSwapBuffers(); +} + +void reshape_cb ( int width, int height ) +{ + float ar; + glViewport ( 0, 0, width, height ) ; + glMatrixMode ( GL_PROJECTION ) ; + glLoadIdentity () ; + ar = (float) width / (float) height ; + glFrustum ( -ar, ar, -1.0, 1.0, 10.0, 100.0 ) ; + glMatrixMode ( GL_MODELVIEW ) ; + glLoadIdentity () ; + xcen = 0.0 ; + ycen = 0.0 ; + zcen = 0.0 ; + glTranslated ( xcen, ycen, zcen - 50.0 ) ; +} + + +void timer_cb ( int value ) +{ + /* Function called at regular intervals to update the positions of the points */ + double deltax, deltay, deltaz ; + int new_index = array_index + 1 ; + + /* Set the next timed callback */ + glutTimerFunc ( 30, timer_cb, 0 ) ; + + if ( animate > 0 ) + { + if ( new_index == NUM_POINTS ) new_index = 0 ; + advance_in_time ( time_step, red_position[array_index], red_position[new_index] ) ; + advance_in_time ( time_step, grn_position[array_index], grn_position[new_index] ) ; + array_index = new_index ; + + deltax = red_position[array_index][0] - grn_position[array_index][0] ; + deltay = red_position[array_index][1] - grn_position[array_index][1] ; + deltaz = red_position[array_index][2] - grn_position[array_index][2] ; + distance = sqrt ( deltax * deltax + deltay * deltay + deltaz * deltaz ) ; + + if ( animate == 2 ) animate = 0 ; + } + + glutPostRedisplay () ; +} + + + +/* The Main Program */ + +int main ( int argc, char *argv[] ) +{ + int pargc = argc ; + + /* Initialize the random number generator */ + srand ( 1023 ) ; + + /* Set up the OpenGL parameters */ + glEnable ( GL_DEPTH_TEST ) ; + glClearColor ( 0.0, 0.0, 0.0, 0.0 ) ; + glClearDepth ( 1.0 ) ; + + /* Initialize GLUT */ + glutInitWindowSize ( 600, 600 ) ; + glutInit ( &pargc, argv ) ; + glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ; + + /* Create the window */ + glutCreateWindow ( "Lorenz Attractor" ) ; + glutKeyboardFunc ( key_cb ) ; + glutMouseFunc ( mouse_cb ) ; + glutSpecialFunc ( special_cb ) ; + glutDisplayFunc ( display_cb ) ; + glutReshapeFunc ( reshape_cb ) ; + glutTimerFunc ( 30, timer_cb, 0 ) ; + + /* Initialize the attractor: The easiest way is to call the keyboard callback with an + * argument of 'r' for Reset. + */ + key_cb ( 'r', 0, 0 ) ; + + /* Enter the GLUT main loop */ + glutMainLoop () ; + +#ifdef _MSC_VER + /* DUMP MEMORY LEAK INFORMATION */ + _CrtDumpMemoryLeaks () ; +#endif + + return 0 ; +} + diff --git a/progs/demos/One/objects.ico b/progs/demos/One/objects.ico new file mode 100644 index 0000000..c2b1575 Binary files /dev/null and b/progs/demos/One/objects.ico differ diff --git a/progs/demos/One/one.c b/progs/demos/One/one.c new file mode 100644 index 0000000..24ce7a7 --- /dev/null +++ b/progs/demos/One/one.c @@ -0,0 +1,405 @@ +/* + * one.c + * + * Hey! This was the original file where freeglut development started. Just + * note what I have written here at the time. And see the creation date :) + * + * : This is a wrapper. I still have to figure out + * : how to build shared libraries under *nix :) + * + * Copyright (c) 1999 by Pawel W. Olszta + * Written by Pawel W. Olszta, + * Creation date: czw gru 2 11:58:41 CET 1999 + */ + +#include +#include + +#include + +int g_LeaveGameMode = 0; +int g_InGameMode = 0; +int g_mainwin1, g_mainwin2, g_sw1, g_sw2, g_gamemodewin; + +/* + * Call this function to have some text drawn at given coordinates + */ +void PrintText( int nX, int nY, char* pszText ) +{ + int lines; + char *p; + + /* + * Prepare the OpenGL state + */ + glDisable( GL_LIGHTING ); + glDisable( GL_DEPTH_TEST ); + glMatrixMode( GL_PROJECTION ); + glPushMatrix(); + glLoadIdentity(); + + /* + * Have an orthogonal projection matrix set + */ + glOrtho( 0, glutGet( GLUT_WINDOW_WIDTH ), + 0, glutGet( GLUT_WINDOW_HEIGHT ), + -1, +1 + ); + + /* + * Now the matrix mode + */ + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + glLoadIdentity(); + + /* + * Now the main text + */ + glColor3ub( 0, 0, 0 ); + glRasterPos2i( nX, nY ); + + for( p=pszText, lines=0; *p; p++ ) + { + if( *p == '\n' ) + { + lines++; + glRasterPos2i( nX, nY-(lines*18) ); + } + + glutBitmapCharacter( GLUT_BITMAP_HELVETICA_18, *p ); + } + + /* + * Revert to the old matrix modes + */ + glMatrixMode( GL_PROJECTION ); + glPopMatrix(); + + glMatrixMode( GL_MODELVIEW ); + glPopMatrix(); + + /* + * Restore the old OpenGL states + */ + glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); + glEnable( GL_DEPTH_TEST ); + glEnable( GL_LIGHTING ); +} + +/* + * This is the display routine for our sample FreeGLUT windows + */ +void SampleDisplay( void ) +{ + int win = glutGetWindow(); + + if (g_InGameMode && win!=g_gamemodewin) + /* Don't draw other windows when in gamemode, those aren't visible + * anyway. Drawing them continuously nonetheless can cause flicker trouble + * on my machine. This only seems to occur only when there are child windows + * among the non-visible windows + */ + return; + + if (win==g_sw1) + { + /* + * Clear the screen + */ + glClearColor(0.7f,0.7f,0.7f,1); + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + glutPostWindowRedisplay(g_mainwin2); + } + else if (win==g_sw2) + { + /* + * Clear the screen + */ + glClearColor(0.3f,0.3f,0.3f,1); + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + glutPostWindowRedisplay(g_mainwin2); + } + else + { + const GLfloat time = glutGet(GLUT_ELAPSED_TIME) / 1000.f * 40; + + /* + * Clear the screen + */ + glClearColor( 0, 0.5, 1, 1 ); + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + + /* + * Have the cube rotated + */ + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + + glRotatef( time, 0, 0, 1 ); + glRotatef( time, 0, 1, 0 ); + glRotatef( time, 1, 0, 0 ); + + /* + * And then drawn... + */ + glColor3f( 1, 1, 0 ); + /* glutWireCube( 20.0 ); */ + glutWireTeapot( 20.0 ); + /* glutWireSphere( 15.0, 15, 15 ); */ + /* glColor3f( 0, 1, 0 ); */ + /* glutWireCube( 30.0 ); */ + /* glutSolidCone( 10, 20, 10, 2 ); */ + + /* + * Don't forget about the model-view matrix + */ + glPopMatrix( ); + + /* + * Draw a silly text + */ + if( g_InGameMode == 0 ) + PrintText( 20, 20, "Hello there cruel world!" ); + else + PrintText( 20, 20, "Press ESC to leave the game mode!" ); + } + + /* + * And swap this context's buffers + */ + glutSwapBuffers( ); + glutPostWindowRedisplay(win); +} + +/* + * This is a sample idle function + */ +void SampleIdle( void ) +{ + if( g_LeaveGameMode == 1 ) + { + /* One could do all this just as well in SampleGameModeKeyboard... */ + printf("leaving gamemode...\n"); + glutLeaveGameMode( ); + g_LeaveGameMode = 0; + g_InGameMode = 0; + glutPostWindowRedisplay(g_mainwin1); + glutPostWindowRedisplay(g_mainwin2); + glutPostWindowRedisplay(g_sw1); + glutPostWindowRedisplay(g_sw2); + } +} + +void SampleEntry(int state) +{ + int window = glutGetWindow () ; + printf ( "Window %d Entry Callback: %d\n", window, state ) ; +} + +/* + * The reshape function + */ +void SampleReshape( int nWidth, int nHeight ) +{ + GLfloat fAspect = (GLfloat) nHeight / (GLfloat) nWidth; + GLfloat fPos[ 4 ] = { 0.0f, 0.0f, 10.0f, 0.0f }; + GLfloat fCol[ 4 ] = { 0.5f, 1.0f, 0.0f, 1.0f }; + + /* + * Update the viewport first + */ + glViewport( 0, 0, nWidth, nHeight ); + + /* + * Then the projection matrix + */ + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + glFrustum( -1.0, 1.0, -fAspect, fAspect, 1.0, 80.0 ); + + /* + * Move back the camera a bit + */ + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity( ); + glTranslatef( 0.0, 0.0, -40.0f ); + + /* + * Enable some features... + */ + glEnable( GL_CULL_FACE ); + glEnable( GL_DEPTH_TEST ); + glEnable( GL_NORMALIZE ); + + /* + * Set up some lighting + */ + glLightfv( GL_LIGHT0, GL_POSITION, fPos ); + glEnable( GL_LIGHTING ); + glEnable( GL_LIGHT0 ); + + /* + * Set up a sample material + */ + glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, fCol ); +} + +/* + * A sample keyboard callback + */ +void SampleKeyboard( unsigned char cChar, int nMouseX, int nMouseY ) +{ + printf( "SampleKeyboard(): keypress '%c' at (%i,%i)\n", + cChar, nMouseX, nMouseY ); +} + +/* + * A sample keyboard callback (for game mode window) + */ +void SampleGameModeKeyboard( unsigned char cChar, int nMouseX, int nMouseY ) +{ + if( cChar == 27 ) + g_LeaveGameMode = 1; +} + + +/* + * A sample special callback + */ +void SampleSpecial( int nSpecial, int nMouseX, int nMouseY ) +{ + printf( "SampleSpecial(): special keypress %i at (%i,%i)\n", + nSpecial, nMouseX, nMouseY ); +} + +/* + * A sample menu callback + */ +void SampleMenu( int menuID ) +{ + printf( "SampleMenu() callback executed, menuID is %i\n", menuID ); +} + +/* + * A sample menu status callback + */ +void SampleMenuStatus( int status, int x, int y ) +{ + printf ( "SampleMenu() callback executed, MenuStatus is %i at (%i,%i)\n", status, x, y ); +} + +/* + * The sample's entry point + */ +int main( int argc, char** argv ) +{ + int menuID, subMenuA, subMenuB; + + glutInitDisplayString( "stencil~2 rgb double depth>=16 samples" ); + glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ); + glutInitWindowPosition( 100, 100 ); + + glutInit( &argc, argv ); + + glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,GLUT_ACTION_GLUTMAINLOOP_RETURNS); + glutMenuStatusFunc( SampleMenuStatus ); + glutIdleFunc( SampleIdle ); + + subMenuA = glutCreateMenu( SampleMenu ); + glutAddMenuEntry( "Sub menu A1 (01)", 1 ); + glutAddMenuEntry( "Sub menu A2 (02)", 2 ); + glutAddMenuEntry( "Sub menu A3 (03)", 3 ); + + subMenuB = glutCreateMenu( SampleMenu ); + glutAddMenuEntry( "Sub menu B1 (04)", 4 ); + glutAddMenuEntry( "Sub menu B2 (05)", 5 ); + glutAddMenuEntry( "Sub menu B3 (06)", 6 ); + glutAddSubMenu( "Going to sub menu A", subMenuA ); + + menuID = glutCreateMenu( SampleMenu ); + glutAddMenuEntry( "Entry one", 1 ); + glutAddMenuEntry( "Entry two", 2 ); + glutAddMenuEntry( "Entry three", 3 ); + glutAddMenuEntry( "Entry four", 4 ); + glutAddMenuEntry( "Entry five", 5 ); + glutAddSubMenu( "Enter sub menu A", subMenuA ); + glutAddSubMenu( "Enter sub menu B", subMenuB ); + + g_mainwin1 = glutCreateWindow( "Hello world!" ); + glutDisplayFunc( SampleDisplay ); + glutReshapeFunc( SampleReshape ); + glutKeyboardFunc( SampleKeyboard ); + glutSpecialFunc( SampleSpecial ); + glutEntryFunc( SampleEntry ); + glutAttachMenu( GLUT_LEFT_BUTTON ); + + glutInitWindowPosition( 200, 200 ); + g_mainwin2 = glutCreateWindow( "I am not Jan B." ); + glutDisplayFunc( SampleDisplay ); + glutReshapeFunc( SampleReshape ); + glutKeyboardFunc( SampleKeyboard ); + glutSpecialFunc( SampleSpecial ); + glutEntryFunc( SampleEntry ); + glutAttachMenu( GLUT_LEFT_BUTTON ); + glutSetMenu(subMenuA); + glutAttachMenu( GLUT_RIGHT_BUTTON ); + + g_sw1=glutCreateSubWindow(g_mainwin2,200,0,100,100); + glutDisplayFunc( SampleDisplay ); + glutSetMenu(subMenuB); + glutAttachMenu( GLUT_LEFT_BUTTON ); + + g_sw2=glutCreateSubWindow(g_sw1,50,0,50,50); + glutDisplayFunc( SampleDisplay ); + glutSetMenu(menuID); + glutAttachMenu( GLUT_RIGHT_BUTTON ); + + printf( "Testing game mode string parsing, don't panic!\n" ); + glutGameModeString( "320x240:32@100" ); + glutGameModeString( "640x480:16@72" ); + glutGameModeString( "1024x768" ); + glutGameModeString( ":32@120" ); + glutGameModeString( "Toudi glupcze, Danwin bedzie moj!" ); + + glutGameModeString( "640x480:37@300" ); /* this one should fail */ + glutEnterGameMode(); + + glutGameModeString( "800x600" ); /* this one is likely to succeed */ + g_gamemodewin = glutEnterGameMode(); + + if (glutGameModeGet(GLUT_GAME_MODE_ACTIVE)) + g_InGameMode = 1; + glutDisplayFunc( SampleDisplay ); + glutReshapeFunc( SampleReshape ); + glutKeyboardFunc( SampleGameModeKeyboard ); + glutEntryFunc( SampleEntry ); + glutSetMenu(menuID); + glutAttachMenu( GLUT_LEFT_BUTTON ); + + printf( "current window is %ix%i at (%i,%i)\n", + glutGet( GLUT_WINDOW_WIDTH ), glutGet( GLUT_WINDOW_HEIGHT ), + glutGet( GLUT_WINDOW_X ), glutGet( GLUT_WINDOW_Y ) + ); + + /* + * Describe pixel format + */ + printf("The current window has %i red bits, %i green bits, %i blue bits and %i alpha bits for a total buffer size of %i bits\n",glutGet(GLUT_WINDOW_RED_SIZE),glutGet(GLUT_WINDOW_GREEN_SIZE),glutGet(GLUT_WINDOW_BLUE_SIZE),glutGet(GLUT_WINDOW_ALPHA_SIZE),glutGet(GLUT_WINDOW_BUFFER_SIZE)); + printf("It furthermore has %i depth bits and %i stencil bits\n",glutGet(GLUT_WINDOW_DEPTH_SIZE),glutGet(GLUT_WINDOW_STENCIL_SIZE)); + + /* + * Enter the main FreeGLUT processing loop + */ + glutMainLoop(); + + /* + * returned from mainloop after window closed + * see glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,GLUT_ACTION_GLUTMAINLOOP_RETURNS); above + */ + printf( "glutMainLoop() termination works fine!\n" ); + + return EXIT_SUCCESS; +} + +/*** END OF FILE ***/ diff --git a/progs/demos/One/one.rc b/progs/demos/One/one.rc new file mode 100644 index 0000000..eaa74b3 --- /dev/null +++ b/progs/demos/One/one.rc @@ -0,0 +1 @@ +GLUT_ICON ICON DISCARDABLE "objects.ico" diff --git a/progs/demos/indexed_color/idxcol.c b/progs/demos/indexed_color/idxcol.c new file mode 100644 index 0000000..668d9b8 --- /dev/null +++ b/progs/demos/indexed_color/idxcol.c @@ -0,0 +1,175 @@ +/* Indexed color mode demo + * Written by John Tsiombikas + * + * Demonstrates how to create an indexed color OpenGL context, manipulate the + * colormap, and do lighting in indexed color mode. + * + * Obviously none of this will work if your OpenGL implementation and/or + * window system does not support indexed color. + */ +#include +#include +#include + +void display(void); +void reshape(int x, int y); +void keyb(unsigned char key, int x, int y); +void mouse(int bn, int st, int x, int y); +void motion(int x, int y); + +float cam_theta, cam_phi, cam_dist = 6; + +int prev_x, prev_y; +int bnstate[8]; + +int sphere, torus; +int redramp[3], blueramp[3]; + + +int main(int argc, char **argv) +{ + int i, ncolors, rampsz, maxdif; + float x; + + glutInit(&argc, argv); + /* request an indexed color visual, this will fail on most modern systems */ + glutInitDisplayMode(GLUT_INDEX | GLUT_DEPTH | GLUT_DOUBLE); + glutInitWindowSize(640, 480); + glutCreateWindow("FreeGLUT indexed color demo"); + + glutDisplayFunc(display); + glutReshapeFunc(reshape); + glutKeyboardFunc(keyb); + glutMouseFunc(mouse); + glutMotionFunc(motion); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + + ncolors = glutGet(GLUT_WINDOW_COLORMAP_SIZE); + printf("Colormap size: %d\n", ncolors); + + rampsz = ncolors / 2; + maxdif = (int)(rampsz * 0.75f); + + /* prepare a palette with two color ramps for a red and a blue object */ + for(i=0; i 90) cam_phi = 90; + glutPostRedisplay(); + } + if(bnstate[2]) { + cam_dist += dy * 0.1f; + if(cam_dist < 0) cam_dist = 0; + glutPostRedisplay(); + } +} diff --git a/progs/demos/init_error_func/init_error_func.c b/progs/demos/init_error_func/init_error_func.c new file mode 100644 index 0000000..de5cf28 --- /dev/null +++ b/progs/demos/init_error_func/init_error_func.c @@ -0,0 +1,58 @@ +/* + * ------------------------------------------ + * user_error_handler.c + * + * This is a sample program showing a basic + * user defined error handlers with FreeGLUT + * ------------------------------------------ + */ + +#include + +/* + * ------------------------------------------ + * Declare our own Error handler for FreeGLUT + * ------------------------------------------ + */ + +/* This declares the vprintf() routine */ +#include + +/* This declares the va_list type */ +#include + +/* The new handler looks like a vprintf prototype */ +void myError (const char *fmt, va_list ap) +{ + fprintf(stderr, "myError: Entering user defined error handler\n"); + + /* print warning message */ + fprintf(stderr, "myError:"); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + + /* deInitialize the freeglut state */ + fprintf(stderr, "myError: Calling glutExit()\n"); + glutExit(); + + /* terminate error handler appropriately */ + fprintf(stderr, "myError: Exit-ing handler routine\n"); + + exit(1); +} + +/* + * ------------------------------------------ + * Just enough code to create the error to + * demonstrate the user defined handler + * ------------------------------------------ + */ +int main(int argc, char** argv) +{ + glutInitErrorFunc(&myError); + glutCreateWindow ("error test"); /* This is an error! */ + glutInit(&argc, argv); /* Should be called + after glutInit() */ + glutMainLoop(); + return 0; +} diff --git a/progs/demos/joystick/joystick.c b/progs/demos/joystick/joystick.c new file mode 100644 index 0000000..0406bb8 --- /dev/null +++ b/progs/demos/joystick/joystick.c @@ -0,0 +1,221 @@ +/* Joystick demo + * Written by John Tsiombikas + * Press escape or q to exit. + */ +#include +#include +#include +#include +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#ifdef _MSC_VER +#pragma warning (disable: 4305 4244) +#endif + +void display(void); +void rect(float x0, float y0, float x1, float y1); +void text(float x, float y, const char *fmt, ...); +void widget(float xsz, float ysz, float xpos, float ypos); +void button(float sz, float state); +void reshape(int x, int y); +void keyboard(unsigned char key, int x, int y); +void joystick(unsigned int bmask, int x, int y, int z); + +int win_width, win_height; +int joy[3]; +unsigned int joy_bmask; +int num_buttons, bhist; + +int main(int argc, char **argv) +{ + glutInit(&argc, argv); + glutInitWindowSize(800, 600); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); + glutCreateWindow("Joystick demo"); + + glutDisplayFunc(display); + glutReshapeFunc(reshape); + glutKeyboardFunc(keyboard); + glutJoystickFunc(joystick, 25); + + if(!glutGet(GLUT_HAS_JOYSTICK)) { + fprintf(stderr, "no joystick detected\n"); + return 1; + } + printf("Joystick axes: %d\n", glutGet(GLUT_JOYSTICK_AXES)); + num_buttons = glutGet(GLUT_JOYSTICK_BUTTONS); + printf("Joystick buttons: %d\n", num_buttons); + + glutMainLoop(); +} + +#define WSZ 0.8 +#define RAD (WSZ / 8) +#define FRM 0.0075 +#define MAX_BSZ (WSZ / 9) + +void display(void) +{ + float dmax = WSZ * 0.5f - RAD; + float jx, jy, jz, cury, bsz; + int i, num; + + jx = joy[0] / 1000.0f; + jy = joy[1] / 1000.0f; + jz = joy[2] / 1000.0f; + + glClear(GL_COLOR_BUFFER_BIT); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glPushMatrix(); + glTranslatef(-WSZ / 2, 0, 0); + widget(WSZ, WSZ, jx * dmax, -jy * dmax); + glPopMatrix(); + + glPushMatrix(); + glTranslatef(WSZ / 2, 0, 0); + widget(RAD * 2, WSZ, 0, -jz * dmax); + glPopMatrix(); + + if(num_buttons > 0) { + num = num_buttons; + } else { + bhist |= joy_bmask; + num = 0; + while(num < 32 && bhist >> num) { + num++; + } + } + + if(num) { + if(num > 32) num = 32; + bsz = 2.0 / (num * 1.4); + + if(bsz > MAX_BSZ) bsz = MAX_BSZ; + + glPushMatrix(); + glTranslatef(-bsz * 1.4 * (num - 1) / 2, 0.7, 0); + for(i=0; i +#include +#include +#include +#include + +void display(void); +void draw_text(int x, int y, const char *str); +const char *skeyname(int skey); +void reshape(int x, int y); +void keypress(unsigned char key, int x, int y); +void keyrelease(unsigned char key, int x, int y); +void skeypress(int key, int x, int y); +void skeyrelease(int key, int x, int y); + +unsigned int modstate; +int cur_key = -1; +int cur_skey = -1; +int win_width, win_height; + +int main(int argc, char **argv) +{ + glutInit(&argc, argv); + glutInitWindowSize(400, 200); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); + glutCreateWindow("Keyboard demo"); + + glutDisplayFunc(display); + glutReshapeFunc(reshape); + glutKeyboardFunc(keypress); + glutKeyboardUpFunc(keyrelease); + glutSpecialFunc(skeypress); + glutSpecialUpFunc(skeyrelease); + + glutMainLoop(); + return 0; +} + +void display(void) +{ + char str[256]; + + glClear(GL_COLOR_BUFFER_BIT); + + strcpy(str, "Key:"); + if(cur_key > 0) { + if(isprint(cur_key)) { + sprintf(str + 4, " '%c'", cur_key); + } else { + sprintf(str + 4, " 0x%02x", cur_key); + } + + + if(modstate & GLUT_ACTIVE_SHIFT) { + strcat(str, " shift"); + } + if(modstate & GLUT_ACTIVE_CTRL) { + strcat(str, " ctrl"); + } + if(modstate & GLUT_ACTIVE_ALT) { + strcat(str, " alt"); + } + if(modstate & GLUT_ACTIVE_SUPER) { + strcat(str, " super"); + } + } + draw_text(win_width / 3, 2 * win_height / 3, str); + + strcpy(str, "Special key: "); + if(cur_skey > 0) { + strcat(str, skeyname(cur_skey)); + } + draw_text(win_width / 3, win_height / 3, str); + + glutSwapBuffers(); +} + +void draw_text(int x, int y, const char *str) +{ + glRasterPos2i(x, y); + while(*str) { + glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *str++); + } +} + +const char *skeyname(int skey) +{ + static const char *fkeys[] = {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12"}; + + switch(skey) { + case GLUT_KEY_LEFT: return "left"; + case GLUT_KEY_UP: return "up"; + case GLUT_KEY_RIGHT: return "right"; + case GLUT_KEY_DOWN: return "down"; + case GLUT_KEY_PAGE_UP: return "page up"; + case GLUT_KEY_PAGE_DOWN: return "page down"; + case GLUT_KEY_HOME: return "home"; + case GLUT_KEY_END: return "end"; + case GLUT_KEY_INSERT: return "insert"; + case GLUT_KEY_NUM_LOCK: return "num lock"; + case GLUT_KEY_BEGIN: return "begin"; + case GLUT_KEY_DELETE: return "delete"; + case GLUT_KEY_SHIFT_L: return "L Shift"; + case GLUT_KEY_SHIFT_R: return "R Shift"; + case GLUT_KEY_CTRL_L: return "L Ctrl"; + case GLUT_KEY_CTRL_R: return "R Ctrl"; + case GLUT_KEY_ALT_L: return "L Alt"; + case GLUT_KEY_ALT_R: return "R Alt"; + case GLUT_KEY_SUPER_L: return "L Super"; + case GLUT_KEY_SUPER_R: return "R Super"; + default: + if(skey >= GLUT_KEY_F1 && skey <= GLUT_KEY_F12) { + return fkeys[skey - GLUT_KEY_F1]; + } + + break; + } + return ""; +} + +void reshape(int x, int y) +{ + win_width = x; + win_height = y; + glViewport(0, 0, x, y); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, x, 0, y, -1, 1); +} + +void keypress(unsigned char key, int x, int y) +{ + if(key == 27) exit(0); + + modstate = glutGetModifiers(); + cur_key = key; + glutPostRedisplay(); +} + +void keyrelease(unsigned char key, int x, int y) +{ + cur_key = -1; + glutPostRedisplay(); +} + +void skeypress(int key, int x, int y) +{ + cur_skey = key; + glutPostRedisplay(); +} + +void skeyrelease(int key, int x, int y) +{ + cur_skey = -1; + glutPostRedisplay(); +} diff --git a/progs/demos/multi-touch/multi-touch.c b/progs/demos/multi-touch/multi-touch.c new file mode 100644 index 0000000..37f5d79 --- /dev/null +++ b/progs/demos/multi-touch/multi-touch.c @@ -0,0 +1,163 @@ +/** + * Sample multi-touch program that displays a square where a cursor + * clicks, with a different color for each cursor. + * + * Copyright (C) 2012 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include + +#include +#include + +#define NUM_DEVICES 16 +#define NUM_CURSORS 64 +typedef struct cursor { + char on; + float x; + float y; +} *Cursor; +struct cursor cursors[NUM_DEVICES][NUM_CURSORS]; + + +static float square[] = { + -.5, -.5, + .5, -.5, + -.5, .5, + .5, .5, + }; + +void onDisplay(void) { + int d; + glClearColor(0,0,0,1); + glClear(GL_COLOR_BUFFER_BIT); + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, square); + for (d = 0; d < NUM_DEVICES; d++) { + int c; + for (c = 0; c < NUM_CURSORS; c++) { + Cursor C = &cursors[d][c]; + if (C->on) { + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(C->x, C->y, 0); + glScalef(30, 30, 1); + + switch(c) { + case 0: + glColor4f(0,0,1,1); + break; + case 1: + glColor4f(0,1,0,1); + break; + case 2: + glColor4f(1,0,0,1); + break; + case 3: + glColor4f(1,1,1,1); + break; + default: + glColor4d(.5,.5,.5,1); + break; + } + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } + } + } + glDisableClientState(GL_VERTEX_ARRAY); + + glutSwapBuffers(); +} + +void onMouse(int button, int state, int x, int y) { + if (button == 0) { + cursors[0][0].on = (state == GLUT_DOWN); + cursors[0][0].x = (float)x; + cursors[0][0].y = (float)y; + printf("normal click\n"); + } +} + +void onMotion(int x, int y) { + cursors[0][0].x = (float)x; + cursors[0][0].y = (float)y; +} + +/* Using FG2.8 (reversed) prototype for now */ +/* void onMultiButton(int cursor_id, int button, int state, int x, int y) { */ +void onMultiButton(int cursor_id, int x, int y, int button, int state) { + if (cursor_id >= NUM_CURSORS) { + fprintf(stderr, "cursor_id (%d) >= NUM_CURSORS (%d), out of slots\n", cursor_id, NUM_CURSORS); + return; + } + if (button == 0) { + cursors[0][cursor_id].on = (state == GLUT_DOWN); + cursors[0][cursor_id].x = (float)x; + cursors[0][cursor_id].y = (float)y; + printf("multi-touch %d click\n", cursor_id); + } +} + +void onMultiMotion(int cursor_id, int x, int y) { + if (cursor_id >= NUM_CURSORS) { + fprintf(stderr, "cursor_id (%d) >= NUM_CURSORS (%d), out of slots\n", cursor_id, NUM_CURSORS); + return; + } + cursors[0][cursor_id].x = (float)x; + cursors[0][cursor_id].y = (float)y; +} + +void onReshape(int width, int height) { + glViewport(0, 0, width, height); + + glMatrixMode(GL_PROJECTION); + glOrtho(0, width, height, 0, -1, 1); +} + +void onIdle(void) { + glutPostRedisplay(); +} + +int main(int argc, char* argv[]) { + memset(cursors, 0, sizeof(cursors)); + + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE); + glutInitWindowSize(640, 480); + glutCreateWindow("Multi-touch test"); + + glutDisplayFunc(onDisplay); + glutReshapeFunc(onReshape); + glutIdleFunc(onIdle); + glutMouseFunc(onMouse); + glutMotionFunc(onMotion); + glutMultiButtonFunc(onMultiButton); + glutMultiMotionFunc(onMultiMotion); + + glutMainLoop(); + + return EXIT_SUCCESS; +} diff --git a/progs/demos/resizer/resizer.c b/progs/demos/resizer/resizer.c new file mode 100644 index 0000000..97a3109 --- /dev/null +++ b/progs/demos/resizer/resizer.c @@ -0,0 +1,395 @@ +#include + +#include + +int nWindow, nChildWindow = -1; +int nLoopMain = 0; +GLboolean bChildPosDone = GL_FALSE, bChildSizeDone = GL_FALSE; + +void SampleKeyboard( unsigned char cChar, int nMouseX, int nMouseY ); +void Redisplay(); +void Reshape(int width, int height); +void Position(int x, int y); +void WindowStatus(int state); + + + + +void DrawQuad() +{ + int width = glutGet(GLUT_WINDOW_WIDTH); + int height = glutGet(GLUT_WINDOW_HEIGHT); + + glBegin(GL_QUADS); + glVertex2d(width*.25, height*.75); + glVertex2d(width*.75, height*.75); + glVertex2d(width*.75, height*.25); + glVertex2d(width*.25, height*.25); + glEnd(); +} + +void UnhideTimer(int window) +{ + glutSetWindow(window); + glutShowWindow(); +} + +void ChangeTitleTimer(int unused) +{ + glutSetIconTitle("new icon title"); + glutSetWindowTitle("new test title"); +} + +void SampleKeyboard( unsigned char cChar, int nMouseX, int nMouseY ) +{ + switch (cChar) + { + case 27: + glutLeaveMainLoop(); + + break; + + + case 'f': + case 'F': + printf("main window toggle fullscreen\n"); + glutFullScreenToggle(); + + break; + + + case 'r': + case 'R': + if (nChildWindow!=-1 && cChar=='r') /* Capital R always resizes the main window*/ + { + glutSetWindow(nChildWindow); + printf("child window resize\n"); + if (!bChildSizeDone) + glutReshapeWindow(glutGet(GLUT_WINDOW_WIDTH)+50,glutGet(GLUT_WINDOW_HEIGHT)+50); + else + glutReshapeWindow(glutGet(GLUT_WINDOW_WIDTH)-50,glutGet(GLUT_WINDOW_HEIGHT)-50); + bChildSizeDone = !bChildSizeDone; + } + else + { + glutSetWindow(nWindow); + printf("main window resize\n"); + if (glutGet(GLUT_WINDOW_WIDTH)<400) + glutReshapeWindow(600,300); + else + glutReshapeWindow(300,300); + } + + break; + + + case 'm': + case 'M': + if (nChildWindow!=-1 && cChar=='m') /* Capital M always moves the main window*/ + { + glutSetWindow(nChildWindow); + /* The window position you request is relative to the top-left + * corner of the client area of the parent window. + */ + if (!bChildPosDone) + glutPositionWindow(glutGet(GLUT_WINDOW_X)+50,glutGet(GLUT_WINDOW_Y)+50); + else + glutPositionWindow(glutGet(GLUT_WINDOW_X)-50,glutGet(GLUT_WINDOW_Y)-50); + bChildPosDone = !bChildPosDone; + } + else + { + glutSetWindow(nWindow); + printf("main window position\n"); + /* The window position you request is the outer top-left of the window, + * the client area is at a different position if the window has borders + * and/or a title bar. + */ + if (glutGet(GLUT_WINDOW_X)<400) + glutPositionWindow(600,300); + else + glutPositionWindow(300,300); + } + + break; + + + case 'd': + case 'D': + if (nChildWindow!=-1 && cChar=='d') /* Capital D always moves+resizes the main window*/ + { + glutSetWindow(nChildWindow); + if (!bChildPosDone) + glutPositionWindow(glutGet(GLUT_WINDOW_X)+50,glutGet(GLUT_WINDOW_Y)+50); + else + glutPositionWindow(glutGet(GLUT_WINDOW_X)-50,glutGet(GLUT_WINDOW_Y)-50); + bChildPosDone = !bChildPosDone; + if (!bChildSizeDone) + glutReshapeWindow(glutGet(GLUT_WINDOW_WIDTH)+50,glutGet(GLUT_WINDOW_HEIGHT)+50); + else + glutReshapeWindow(glutGet(GLUT_WINDOW_WIDTH)-50,glutGet(GLUT_WINDOW_HEIGHT)-50); + bChildSizeDone = !bChildSizeDone; + } + else + { + if (glutGet(GLUT_WINDOW_X)<400) + glutPositionWindow(600,300); + else + glutPositionWindow(300,300); + if (glutGet(GLUT_WINDOW_WIDTH)<400) + glutReshapeWindow(600,300); + else + glutReshapeWindow(300,300); + } + break; + + + case 'c': + case 'C': + if (nChildWindow==-1) + { + int width = glutGet(GLUT_WINDOW_WIDTH); + int height = glutGet(GLUT_WINDOW_HEIGHT); + + /* open child window */ + printf("open child window\n"); + + nChildWindow = glutCreateSubWindow(nWindow,(int)(width*.35),(int)(height*.35),(int)(width*.3),(int)(height*.3)); + glutKeyboardFunc( SampleKeyboard ); + glutDisplayFunc( Redisplay ); + glutReshapeFunc( Reshape ); + glutPositionFunc( Position ); + glutWindowStatusFunc( WindowStatus ); + } + else + { + /* close child window */ + printf("close child window\n"); + glutSetWindow(nWindow); + glutDestroyWindow(nChildWindow); + nChildWindow = -1; + bChildSizeDone = GL_FALSE; + bChildPosDone = GL_FALSE; + } + break; + + + case 'i': + case 'I': + glutIconifyWindow(); + glutTimerFunc(1500, ChangeTitleTimer, 0); + break; + + + case 'h': + case 'H': + if (nChildWindow!=-1 && cChar=='h') /* Capital H always hides the main window*/ + { + glutSetWindow(nChildWindow); + glutTimerFunc(2000, UnhideTimer, nChildWindow); + } + else + { + glutSetWindow(nWindow); + glutTimerFunc(2000, UnhideTimer, nWindow); + } + glutHideWindow(); + break; + + case 'p': + case 'P': + if (nChildWindow!=-1 && cChar=='p') /* Capital P always changes pointer for the main window*/ + { + glutSetWindow(nChildWindow); + if (glutGet(GLUT_WINDOW_CURSOR)==GLUT_CURSOR_TOP_SIDE) + { + glutSetCursor(GLUT_CURSOR_RIGHT_ARROW); + printf("reverting child window cursor\n"); + } + else + { + glutSetCursor(GLUT_CURSOR_TOP_SIDE); + printf("changing child window cursor\n"); + } + } + else + { + glutSetWindow(nWindow); + if (glutGet(GLUT_WINDOW_CURSOR)==GLUT_CURSOR_CYCLE) + { + glutSetCursor(GLUT_CURSOR_RIGHT_ARROW); + printf("reverting main window cursor\n"); + } + else + { + glutSetCursor(GLUT_CURSOR_CYCLE); + printf("changing main window cursor\n"); + } + } + break; + + default: + break; + } +} + +void Idle(void) +{ + glutPostRedisplay(); +} + +void Reshape(int width, int height) +{ + int win = glutGetWindow(); + + printf("reshape %s, client area: %dx%d\n",win==nWindow?"main":"child", + width, height); + + glViewport(0,0,width,height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluOrtho2D(0,width,0,height); + + if (win==nWindow && nChildWindow!=-1) + { + /* Put child window in right place */ + int x = (int)(width*.35), y=(int)(height*.35), w=(int)(width*.3), h = (int)(height*.3); + if (bChildPosDone) + { + x += 50; + y += 50; + } + if (bChildSizeDone) + { + w += 50; + h += 50; + } + glutSetWindow(nChildWindow); + glutPositionWindow(x,y); + glutReshapeWindow(w,h); + glutSetWindow(nWindow); + } +} + +void Position(int x, int y) +{ + int win = glutGetWindow(); + + printf("position, %s: (%d,%d)\n",win==nWindow?"top-left (non-client) of main":"top-left of child relative to parent", + x, y); +} + +void WindowStatus(int state) +{ + int win = glutGetWindow(); + printf("windowstatus (win %i): %i\n",win,state); +} + +void Redisplay(void) +{ + int win = glutGetWindow(); + int viewport[4]; + + if (win==nWindow) + { + glClearColor(.2f,0.f,0.f,0.f); + glColor3f(1,1,1); + } + else + { + /* child window */ + glClearColor(.0f,.2f,0.f,0.f); + glColor3f(.5,.5,.5); + glutPostWindowRedisplay(nWindow); + } + glClear(GL_COLOR_BUFFER_BIT); + DrawQuad(); + + if (win==nWindow) + { + glColor3f(1, 1, 0); + glGetIntegerv(GL_VIEWPORT, viewport); + glRasterPos2i(2, -glutBitmapHeight(GLUT_BITMAP_9_BY_15)+3+viewport[3]); + glutBitmapString(GLUT_BITMAP_9_BY_15, (unsigned char*)"press f/r/m/d/c/i/h/p"); + } + + glutSwapBuffers(); + glutPostWindowRedisplay(win); +} + +void Timer(int unused) +{ + int win = glutGetWindow(); + int x, y; + int width, height; + int border, caption; + + x = glutGet(GLUT_WINDOW_X); + y = glutGet(GLUT_WINDOW_Y); + width = glutGet(GLUT_WINDOW_WIDTH); + height = glutGet(GLUT_WINDOW_HEIGHT); + border = glutGet(GLUT_WINDOW_BORDER_WIDTH); + caption = glutGet(GLUT_WINDOW_HEADER_HEIGHT); + /* returned position is top-left of client area, to get top-left of + * of window you'll need to add the size of the border and caption + * of the current window (can be 0). + * Note that the window position is not necessarily positive (e.g. + * when the window is on a monitor to the left of the primary monitor + * or simply when maximized--try pressing the maximize button). + * the returned size is the size of the client area + * Note that the top-left of a child window is relative to the + * top-left of the client area of the parent. + */ + /* printf("window border: %dpx, caption: %dpx\n",border,caption); */ + if (win==nWindow) + printf("main window %dx%d, top-left of client at: (%d,%d), of window at: (%d,%d)\n", + width, height, + x ,y, + x-border, + y-caption); + else + printf("child window %dx%d, top-left of client at: (%d,%d), relative to parent\n", + width, height, + x ,y); + + /* (re)set the timer callback and ask glut to call it in 500 ms */ + glutTimerFunc(500, Timer, 0); +} + + +int main(int argc, char* argv[]) +{ + int border, caption; + glutInit( &argc, argv ); + glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE /*| GLUT_BORDERLESS*/); /* do try as well with GLUT_BORDERLESS and GLUT_CAPTIONLESS */ + glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,GLUT_ACTION_GLUTMAINLOOP_RETURNS); + + /* Get border and caption size of default window style */ + border = glutGet(GLUT_WINDOW_BORDER_WIDTH); + caption = glutGet(GLUT_WINDOW_HEADER_HEIGHT); + printf("default window style border: %dpx, caption: %dpx\n",border,caption); + + /* NB: The window position you request is the outer top-left of the + * window, the client area is at a different position if the window has + * borders and/or a title bar. + */ + glutInitWindowPosition(150,250); + glutInitWindowSize(200,200); + + nWindow = glutCreateWindow("test"); + glutSetIconTitle("test icon title"); + printf("main window id: %d\n", nWindow); + + glutKeyboardFunc( SampleKeyboard ); + glutDisplayFunc( Redisplay ); + glutReshapeFunc( Reshape ); + glutPositionFunc( Position ); + glutWindowStatusFunc( WindowStatus ); + + glutTimerFunc(300, Timer, 0); + + glutMainLoop(); + printf("glutMainLoop returned\n"); + + return EXIT_SUCCESS; +} diff --git a/progs/demos/shapes/glmatrix.c b/progs/demos/shapes/glmatrix.c new file mode 100644 index 0000000..485e324 --- /dev/null +++ b/progs/demos/shapes/glmatrix.c @@ -0,0 +1,219 @@ +#include +#define _USE_MATH_DEFINES +#include +#include "glmatrix.h" + +#ifndef M_PI +#define M_PI 3.141592653589793 +#endif + +#define MMODE_IDX(x) ((x) - GL_MODELVIEW) +#define MAT_STACK_SIZE 32 +#define MAT_IDENT {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1} + +static int mm_idx = 0; +static float mat_stack[3][MAT_STACK_SIZE][16] = {{MAT_IDENT}, {MAT_IDENT}, {MAT_IDENT}}; +static int stack_top[3]; + +void gl_matrix_mode(int mm) +{ + mm_idx = MMODE_IDX(mm); +} + +void gl_push_matrix(void) +{ + int top = stack_top[mm_idx]; + + memcpy(mat_stack[mm_idx][top + 1], mat_stack[mm_idx][top], 16 * sizeof(float)); + stack_top[mm_idx]++; +} + +void gl_pop_matrix(void) +{ + stack_top[mm_idx]--; +} + +void gl_load_identity(void) +{ + static const float idmat[] = MAT_IDENT; + int top = stack_top[mm_idx]; + float *mat = mat_stack[mm_idx][top]; + + memcpy(mat, idmat, sizeof idmat); +} + +void gl_load_matrixf(const float *m) +{ + int top = stack_top[mm_idx]; + float *mat = mat_stack[mm_idx][top]; + + memcpy(mat, m, 16 * sizeof *mat); +} + +#define M4(i, j) ((i << 2) + j) + +void gl_mult_matrixf(const float *m2) +{ + int i, j; + int top = stack_top[mm_idx]; + float *m1 = mat_stack[mm_idx][top]; + float res[16]; + + for(i=0; i<4; i++) { + for(j=0; j<4; j++) { + res[M4(i,j)] = m1[M4(i,0)] * m2[M4(0,j)] + + m1[M4(i,1)] * m2[M4(1,j)] + + m1[M4(i,2)] * m2[M4(2,j)] + + m1[M4(i,3)] * m2[M4(3,j)]; + } + } + + memcpy(m1, res, sizeof res); +} + +void gl_translatef(float x, float y, float z) +{ + float mat[] = MAT_IDENT; + + mat[12] = x; + mat[13] = y; + mat[14] = z; + + gl_mult_matrixf(mat); +} + +void gl_rotatef(float angle, float x, float y, float z) +{ + float mat[] = MAT_IDENT; + + float angle_rad = (float)M_PI * angle / 180.f; + float sina = (float)sin(angle_rad); + float cosa = (float)cos(angle_rad); + float one_minus_cosa = 1.f - cosa; + float nxsq = x * x; + float nysq = y * y; + float nzsq = z * z; + + mat[0] = nxsq + (1.f - nxsq) * cosa; + mat[4] = x * y * one_minus_cosa - z * sina; + mat[8] = x * z * one_minus_cosa + y * sina; + mat[1] = x * y * one_minus_cosa + z * sina; + mat[5] = nysq + (1.f - nysq) * cosa; + mat[9] = y * z * one_minus_cosa - x * sina; + mat[2] = x * z * one_minus_cosa - y * sina; + mat[6] = y * z * one_minus_cosa + x * sina; + mat[10] = nzsq + (1.f - nzsq) * cosa; + + gl_mult_matrixf(mat); +} + +void gl_scalef(float x, float y, float z) +{ + float mat[] = MAT_IDENT; + + mat[0] = x; + mat[5] = y; + mat[10] = z; + + gl_mult_matrixf(mat); +} + +void gl_ortho(float left, float right, float bottom, float top, float znear, float zfar) +{ + float mat[] = MAT_IDENT; + + float dx = right - left; + float dy = top - bottom; + float dz = zfar - znear; + + float tx = -(right + left) / dx; + float ty = -(top + bottom) / dy; + float tz = -(zfar + znear) / dz; + + float sx = 2.f / dx; + float sy = 2.f / dy; + float sz = -2.f / dz; + + mat[0] = sx; + mat[5] = sy; + mat[10] = sz; + mat[12] = tx; + mat[13] = ty; + mat[14] = tz; + + gl_mult_matrixf(mat); +} + +void gl_frustum(float left, float right, float bottom, float top, float znear, float zfar) +{ + float mat[] = MAT_IDENT; + + float dx = right - left; + float dy = top - bottom; + float dz = zfar - znear; + + float a = (right + left) / dx; + float b = (top + bottom) / dy; + float c = -(zfar + znear) / dz; + float d = -2.f * zfar * znear / dz; + + mat[0] = 2.f * znear / dx; + mat[5] = 2.f * znear / dy; + mat[8] = a; + mat[9] = b; + mat[10] = c; + mat[11] = -1.f; + mat[14] = d; + mat[15] = 0; + + gl_mult_matrixf(mat); +} + +void glu_perspective(float vfov, float aspect, float znear, float zfar) +{ + float vfov_rad = (float)M_PI * vfov / 180.f; + float x = znear * (float)tan(vfov_rad / 2.f); + gl_frustum(-aspect * x, aspect * x, -x, x, znear, zfar); +} + +/* return the matrix (16 elements, 4x4 matrix, row-major order */ +float* get_matrix(int mm) +{ + int idx = MMODE_IDX(mm); + int top = stack_top[idx]; + return mat_stack[idx][top]; +} + + +#define M3(i, j) ((i * 3) + j) +static float inv_transpose_result[9]; + +/* return the inverse transpose of the left-upper 3x3 of a matrix + The returned pointer is only valid until the next time this function is + called, so make a deep copy when you want to keep it around. + */ +float* get_inv_transpose_3x3(int mm) +{ + int idx = MMODE_IDX(mm); + int top = stack_top[idx]; + float *m1 = mat_stack[idx][top]; + + + float determinant = +m1[M4(0,0)]*(m1[M4(1,1)]*m1[M4(2,2)]-m1[M4(2,1)]*m1[M4(1,2)]) + -m1[M4(0,1)]*(m1[M4(1,0)]*m1[M4(2,2)]-m1[M4(1,2)]*m1[M4(2,0)]) + +m1[M4(0,2)]*(m1[M4(1,0)]*m1[M4(2,1)]-m1[M4(1,1)]*m1[M4(2,0)]); + + float invdet = 1/determinant; + + inv_transpose_result[M3(0,0)] = (m1[M4(1,1)]*m1[M4(2,2)]-m1[M4(2,1)]*m1[M4(1,2)])*invdet; + inv_transpose_result[M3(1,0)] = -(m1[M4(0,1)]*m1[M4(2,2)]-m1[M4(0,2)]*m1[M4(2,1)])*invdet; + inv_transpose_result[M3(2,0)] = (m1[M4(0,1)]*m1[M4(1,2)]-m1[M4(0,2)]*m1[M4(1,1)])*invdet; + inv_transpose_result[M3(0,1)] = -(m1[M4(1,0)]*m1[M4(2,2)]-m1[M4(1,2)]*m1[M4(2,0)])*invdet; + inv_transpose_result[M3(1,1)] = (m1[M4(0,0)]*m1[M4(2,2)]-m1[M4(0,2)]*m1[M4(2,0)])*invdet; + inv_transpose_result[M3(2,1)] = -(m1[M4(0,0)]*m1[M4(1,2)]-m1[M4(1,0)]*m1[M4(0,2)])*invdet; + inv_transpose_result[M3(0,2)] = (m1[M4(1,0)]*m1[M4(2,1)]-m1[M4(2,0)]*m1[M4(1,1)])*invdet; + inv_transpose_result[M3(1,2)] = -(m1[M4(0,0)]*m1[M4(2,1)]-m1[M4(2,0)]*m1[M4(0,1)])*invdet; + inv_transpose_result[M3(2,2)] = (m1[M4(0,0)]*m1[M4(1,1)]-m1[M4(1,0)]*m1[M4(0,1)])*invdet; + + return inv_transpose_result; +} diff --git a/progs/demos/shapes/glmatrix.h b/progs/demos/shapes/glmatrix.h new file mode 100644 index 0000000..997a70d --- /dev/null +++ b/progs/demos/shapes/glmatrix.h @@ -0,0 +1,31 @@ +#ifndef GLMATRIX_H_ +#define GLMATRIX_H_ + +#ifndef GL_MODELVIEW +#define GL_MODELVIEW 0x1700 +#endif +#ifndef GL_PROJECTION +#define GL_PROJECTION 0x1701 +#endif +#ifndef GL_TEXTURE +#define GL_TEXTURE 0x1702 +#endif + +void gl_matrix_mode(int mmode); +void gl_push_matrix(void); +void gl_pop_matrix(void); +void gl_load_identity(void); +void gl_load_matrixf(const float *mat); +void gl_mult_matrixf(const float *mat); +void gl_translatef(float x, float y, float z); +void gl_rotatef(float angle, float x, float y, float z); +void gl_scalef(float x, float y, float z); +void gl_ortho(float left, float right, float bottom, float top, float znear, float zfar); +void gl_frustum(float left, float right, float bottom, float top, float znear, float zfar); +void glu_perspective(float vfov, float aspect, float znear, float zfar); + +/* getters */ +float* get_matrix(int mm); +float* get_inv_transpose_3x3(int mm); + +#endif /* GLMATRIX_H_ */ diff --git a/progs/demos/shapes/shapes.c b/progs/demos/shapes/shapes.c new file mode 100644 index 0000000..09fb5ef --- /dev/null +++ b/progs/demos/shapes/shapes.c @@ -0,0 +1,946 @@ +/*! \file shapes.c + \ingroup demos + + This program is a test harness for the various shapes + in OpenGLUT. It may also be useful to see which + parameters control what behavior in the OpenGLUT + objects. + + Spinning wireframe and solid-shaded shapes are + displayed. Some parameters can be adjusted. + + Keys: + - Esc   Quit + - q Q   Quit + - i I   Show info + - p P   Toggle perspective or orthographic projection + - r R   Toggle fixed or animated rotation around model X-axis + - s S   Toggle toggle fixed function or shader render path + - n N   Toggle visualization of object's normal vectors + - = +   Increase \a slices + - - _   Decreate \a slices + - , <   Decreate \a stacks + - . >   Increase \a stacks + - 9 (   Decreate \a depth (Sierpinski Sponge) + - 0 )   Increase \a depth (Sierpinski Sponge) + - up    Increase "outer radius" + - down  Decrease "outer radius" + - left  Decrease "inner radius" + - right Increase "inner radius" + - PgUp  Next shape-drawing function + - PgDn  Prev shape-drawing function + + \author Written by Nigel Stewart November 2003 + + \author Portions Copyright (C) 2004, the OpenGLUT project contributors.
+ OpenGLUT branched from freeglut in February, 2004. + + \image html openglut_shapes.png OpenGLUT Geometric Shapes Demonstration + \include demos/shapes/shapes.c +*/ + +#include + +#include +#include +#include +#include + +#include "glmatrix.h" + +#ifdef _MSC_VER +/* DUMP MEMORY LEAKS */ +#include +#endif + +/* report GL errors, if any, to stderr */ +void checkError(const char *functionName) +{ + GLenum error; + while (( error = glGetError() ) != GL_NO_ERROR) { + fprintf (stderr, "GL error 0x%X detected in %s\n", error, functionName); + } +} + +/* + * OpenGL 2+ shader mode needs some function and macro definitions, + * avoiding a dependency on additional libraries like GLEW or the + * GL/glext.h header + */ +#ifndef GL_FRAGMENT_SHADER +#define GL_FRAGMENT_SHADER 0x8B30 +#endif + +#ifndef GL_VERTEX_SHADER +#define GL_VERTEX_SHADER 0x8B31 +#endif + +#ifndef GL_COMPILE_STATUS +#define GL_COMPILE_STATUS 0x8B81 +#endif + +#ifndef GL_LINK_STATUS +#define GL_LINK_STATUS 0x8B82 +#endif + +#ifndef GL_INFO_LOG_LENGTH +#define GL_INFO_LOG_LENGTH 0x8B84 +#endif + +typedef ptrdiff_t ourGLsizeiptr; +typedef char ourGLchar; + +#ifndef APIENTRY +#define APIENTRY +#endif + +#ifndef GL_VERSION_2_0 +typedef GLuint (APIENTRY *PFNGLCREATESHADERPROC) (GLenum type); +typedef void (APIENTRY *PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const ourGLchar **string, const GLint *length); +typedef void (APIENTRY *PFNGLCOMPILESHADERPROC) (GLuint shader); +typedef GLuint (APIENTRY *PFNGLCREATEPROGRAMPROC) (void); +typedef void (APIENTRY *PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (APIENTRY *PFNGLLINKPROGRAMPROC) (GLuint program); +typedef void (APIENTRY *PFNGLUSEPROGRAMPROC) (GLuint program); +typedef void (APIENTRY *PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params); +typedef void (APIENTRY *PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, ourGLchar *infoLog); +typedef void (APIENTRY *PFNGLGETPROGRAMIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY *PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, ourGLchar *infoLog); +typedef GLint (APIENTRY *PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const ourGLchar *name); +typedef GLint (APIENTRY *PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const ourGLchar *name); +typedef void (APIENTRY *PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRY *PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +#endif + +PFNGLCREATESHADERPROC gl_CreateShader; +PFNGLSHADERSOURCEPROC gl_ShaderSource; +PFNGLCOMPILESHADERPROC gl_CompileShader; +PFNGLCREATEPROGRAMPROC gl_CreateProgram; +PFNGLATTACHSHADERPROC gl_AttachShader; +PFNGLLINKPROGRAMPROC gl_LinkProgram; +PFNGLUSEPROGRAMPROC gl_UseProgram; +PFNGLGETSHADERIVPROC gl_GetShaderiv; +PFNGLGETSHADERINFOLOGPROC gl_GetShaderInfoLog; +PFNGLGETPROGRAMIVPROC gl_GetProgramiv; +PFNGLGETPROGRAMINFOLOGPROC gl_GetProgramInfoLog; +PFNGLGETATTRIBLOCATIONPROC gl_GetAttribLocation; +PFNGLGETUNIFORMLOCATIONPROC gl_GetUniformLocation; +PFNGLUNIFORMMATRIX4FVPROC gl_UniformMatrix4fv; +PFNGLUNIFORMMATRIX3FVPROC gl_UniformMatrix3fv; + +void initExtensionEntries(void) +{ + gl_CreateShader = (PFNGLCREATESHADERPROC) glutGetProcAddress ("glCreateShader"); + gl_ShaderSource = (PFNGLSHADERSOURCEPROC) glutGetProcAddress ("glShaderSource"); + gl_CompileShader = (PFNGLCOMPILESHADERPROC) glutGetProcAddress ("glCompileShader"); + gl_CreateProgram = (PFNGLCREATEPROGRAMPROC) glutGetProcAddress ("glCreateProgram"); + gl_AttachShader = (PFNGLATTACHSHADERPROC) glutGetProcAddress ("glAttachShader"); + gl_LinkProgram = (PFNGLLINKPROGRAMPROC) glutGetProcAddress ("glLinkProgram"); + gl_UseProgram = (PFNGLUSEPROGRAMPROC) glutGetProcAddress ("glUseProgram"); + gl_GetShaderiv = (PFNGLGETSHADERIVPROC) glutGetProcAddress ("glGetShaderiv"); + gl_GetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) glutGetProcAddress ("glGetShaderInfoLog"); + gl_GetProgramiv = (PFNGLGETPROGRAMIVPROC) glutGetProcAddress ("glGetProgramiv"); + gl_GetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) glutGetProcAddress ("glGetProgramInfoLog"); + gl_GetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) glutGetProcAddress ("glGetAttribLocation"); + gl_GetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) glutGetProcAddress ("glGetUniformLocation"); + gl_UniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) glutGetProcAddress ("glUniformMatrix4fv"); + gl_UniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC) glutGetProcAddress ("glUniformMatrix3fv"); + if (!gl_CreateShader || !gl_ShaderSource || !gl_CompileShader || !gl_CreateProgram || !gl_AttachShader || !gl_LinkProgram || !gl_UseProgram || !gl_GetShaderiv || !gl_GetShaderInfoLog || !gl_GetProgramiv || !gl_GetProgramInfoLog || !gl_GetAttribLocation || !gl_GetUniformLocation || !gl_UniformMatrix4fv || !gl_UniformMatrix3fv) + { + fprintf (stderr, "glCreateShader, glShaderSource, glCompileShader, glCreateProgram, glAttachShader, glLinkProgram, glUseProgram, glGetShaderiv, glGetShaderInfoLog, glGetProgramiv, glGetProgramInfoLog, glGetAttribLocation, glGetUniformLocation, glUniformMatrix4fv or gl_UniformMatrix3fv not found"); + exit(1); + } +} + +const ourGLchar *vertexShaderSource[] = { + "/**", + " * From the OpenGL Programming wikibook: http://en.wikibooks.org/wiki/GLSL_Programming/GLUT/Smooth_Specular_Highlights", + " * This file is in the public domain.", + " * Contributors: Sylvain Beucler", + " */", + "attribute vec3 fg_coord;", + "attribute vec3 fg_normal;", + "varying vec4 position; /* position of the vertex (and fragment) in world space */", + "varying vec3 varyingNormalDirection; /* surface normal vector in world space */", + "uniform mat4 m, p; /* don't need v, as always identity in our demo */", + "uniform mat3 m_3x3_inv_transp;", + " ", + "void main()", + "{", + " vec4 fg_coord4 = vec4(fg_coord, 1.0);", + " position = m * fg_coord4;", + " varyingNormalDirection = normalize(m_3x3_inv_transp * fg_normal);", + " ", + " mat4 mvp = p*m; /* normally p*v*m */", + " gl_Position = mvp * fg_coord4;", + "}" +}; + +const ourGLchar *fragmentShaderSource[] = { + "/**", + " * From the OpenGL Programming wikibook: http://en.wikibooks.org/wiki/GLSL_Programming/GLUT/Smooth_Specular_Highlights", + " * This file is in the public domain.", + " * Contributors: Martin Kraus, Sylvain Beucler", + " */", + "varying vec4 position; /* position of the vertex (and fragment) in world space */", + "varying vec3 varyingNormalDirection; /* surface normal vector in world space */", + "/* uniform mat4 v_inv; // in this demo, the view matrix is always an identity matrix */", + " ", + "struct lightSource", + "{", + " vec4 position;", + " vec4 diffuse;", + " vec4 specular;", + " float constantAttenuation, linearAttenuation, quadraticAttenuation;", + " float spotCutoff, spotExponent;", + " vec3 spotDirection;", + "};", + "lightSource light0 = lightSource(", + " vec4(2.0, 5.0, 5.0, 0.0),", + " vec4(1.0, 1.0, 1.0, 1.0),", + " vec4(1.0, 1.0, 1.0, 1.0),", + " 0.0, 1.0, 0.0,", + " 180.0, 0.0,", + " vec3(0.0, 0.0, 0.0)", + ");", + "vec4 scene_ambient = vec4(0.2, 0.2, 0.2, 1.0);", + " ", + "struct material", + "{", + " vec4 ambient;", + " vec4 diffuse;", + " vec4 specular;", + " float shininess;", + "};", + "material frontMaterial = material(", + " vec4(1.0, 0.0, 0.0, 1.0),", + " vec4(1.0, 0.0, 0.0, 1.0),", + " vec4(1.0, 1.0, 1.0, 1.0),", + " 100.0", + ");", + " ", + "void main()", + "{", + " vec3 normalDirection = normalize(varyingNormalDirection);", + " /* vec3 viewDirection = normalize(vec3(v_inv * vec4(0.0, 0.0, 0.0, 1.0) - position)); */", + " vec3 viewDirection = normalize(vec3(vec4(0.0, 0.0, 0.0, 1.0) - position)); /* in this demo, the view matrix is always an identity matrix */", + " vec3 lightDirection;", + " float attenuation;", + " ", + " if (0.0 == light0.position.w) /* directional light? */", + " {", + " attenuation = 1.0; /* no attenuation */", + " lightDirection = normalize(vec3(light0.position));", + " } ", + " else /* point light or spotlight (or other kind of light) */", + " {", + " vec3 positionToLightSource = vec3(light0.position - position);", + " float distance = length(positionToLightSource);", + " lightDirection = normalize(positionToLightSource);", + " attenuation = 1.0 / (light0.constantAttenuation", + " + light0.linearAttenuation * distance", + " + light0.quadraticAttenuation * distance * distance);", + " ", + " if (light0.spotCutoff <= 90.0) /* spotlight? */", + " {", + " float clampedCosine = max(0.0, dot(-lightDirection, light0.spotDirection));", + " if (clampedCosine < cos(radians(light0.spotCutoff))) /* outside of spotlight cone? */", + " {", + " attenuation = 0.0;", + " }", + " else", + " {", + " attenuation = attenuation * pow(clampedCosine, light0.spotExponent); ", + " }", + " }", + " }", + " ", + " vec3 ambientLighting = vec3(scene_ambient) * vec3(frontMaterial.ambient);", + " ", + " vec3 diffuseReflection = attenuation ", + " * vec3(light0.diffuse) * vec3(frontMaterial.diffuse)", + " * max(0.0, dot(normalDirection, lightDirection));", + " ", + " vec3 specularReflection;", + " if (dot(normalDirection, lightDirection) < 0.0) /* light source on the wrong side? */", + " {", + " specularReflection = vec3(0.0, 0.0, 0.0); /* no specular reflection */", + " }", + " else /* light source on the right side */", + " {", + " specularReflection = attenuation * vec3(light0.specular) * vec3(frontMaterial.specular) ", + " * pow(max(0.0, dot(reflect(-lightDirection, normalDirection), viewDirection)), frontMaterial.shininess);", + " }", + " ", + " gl_FragColor = vec4(ambientLighting + diffuseReflection + specularReflection, 1.0);", + "}" +}; + +GLint getAttribOrUniformLocation(const char* name, GLuint program, GLboolean isAttrib) +{ + if (isAttrib) + { + GLint attrib = gl_GetAttribLocation(program, name); + if (attrib == -1) + { + fprintf(stderr, "Warning: Could not bind attrib %s\n", name); + } + + checkError ("getAttribOrUniformLocation"); + return attrib; + } + else + { + GLint uniform = gl_GetUniformLocation(program, name); + if (uniform == -1) + { + fprintf(stderr, "Warning: Could not bind uniform %s\n", name); + } + + checkError ("getAttribOrUniformLocation"); + return uniform; + } +} + +GLuint program; +GLint attribute_fg_coord = -1, attribute_fg_normal = -1; +GLint uniform_m = -1, uniform_p = -1, uniform_m_3x3_inv_transp = -1; +GLint shaderReady = 0; /* Set to 1 when all initialization went well, to -1 when shader somehow unusable. */ + + + +void compileAndCheck(GLuint shader) +{ + GLint status; + gl_CompileShader (shader); + gl_GetShaderiv (shader, GL_COMPILE_STATUS, &status); + if (status == GL_FALSE) { + GLint infoLogLength; + ourGLchar *infoLog; + gl_GetShaderiv (shader, GL_INFO_LOG_LENGTH, &infoLogLength); + infoLog = (ourGLchar*) malloc (infoLogLength); + gl_GetShaderInfoLog (shader, infoLogLength, NULL, infoLog); + fprintf (stderr, "compile log: %s\n", infoLog); + free (infoLog); + } + checkError ("compileAndCheck"); +} + +GLuint compileShaderSource(GLenum type, GLsizei count, const ourGLchar **string) +{ + GLuint shader = gl_CreateShader (type); + gl_ShaderSource (shader, count, string, NULL); + + checkError ("compileShaderSource"); + + compileAndCheck (shader); + return shader; +} + +void linkAndCheck(GLuint program) +{ + GLint status; + gl_LinkProgram (program); + gl_GetProgramiv (program, GL_LINK_STATUS, &status); + if (status == GL_FALSE) { + GLint infoLogLength; + ourGLchar *infoLog; + gl_GetProgramiv (program, GL_INFO_LOG_LENGTH, &infoLogLength); + infoLog = (ourGLchar*) malloc (infoLogLength); + gl_GetProgramInfoLog (program, infoLogLength, NULL, infoLog); + fprintf (stderr, "link log: %s\n", infoLog); + free (infoLog); + } + checkError ("linkAndCheck"); +} + +void createProgram(GLuint vertexShader, GLuint fragmentShader) +{ + program = gl_CreateProgram (); + if (vertexShader != 0) { + gl_AttachShader (program, vertexShader); + } + if (fragmentShader != 0) { + gl_AttachShader (program, fragmentShader); + } + + checkError ("createProgram"); + + linkAndCheck (program); +} + +void initShader(void) +{ + const GLsizei vertexShaderLines = sizeof(vertexShaderSource) / sizeof(ourGLchar*); + GLuint vertexShader = + compileShaderSource (GL_VERTEX_SHADER, vertexShaderLines, vertexShaderSource); + + const GLsizei fragmentShaderLines = sizeof(fragmentShaderSource) / sizeof(ourGLchar*); + GLuint fragmentShader = + compileShaderSource (GL_FRAGMENT_SHADER, fragmentShaderLines, fragmentShaderSource); + + checkError ("initShader - 1"); + + createProgram (vertexShader, fragmentShader); + + gl_UseProgram (program); + + attribute_fg_coord = getAttribOrUniformLocation("fg_coord" , program, GL_TRUE); + attribute_fg_normal = getAttribOrUniformLocation("fg_normal" , program, GL_TRUE); + uniform_m = getAttribOrUniformLocation("m" , program, GL_FALSE); + uniform_p = getAttribOrUniformLocation("p" , program, GL_FALSE); + uniform_m_3x3_inv_transp= getAttribOrUniformLocation("m_3x3_inv_transp" , program, GL_FALSE); + + gl_UseProgram (0); + + if (attribute_fg_coord==-1 || attribute_fg_normal==-1 || + uniform_m==-1 || uniform_p==-1 || uniform_m_3x3_inv_transp==-1) + shaderReady = -1; + else + shaderReady = 1; + + checkError ("initShader - 2"); +} + +/* + * This macro is only intended to be used on arrays, of course. + */ +#define NUMBEROF(x) ((sizeof(x))/(sizeof(x[0]))) + +/* + * These global variables control which object is drawn, + * and how it is drawn. No object uses all of these + * variables. + */ +static int function_index; +static int slices = 16; +static int stacks = 16; +static double irad = .25; +static double orad = 1.0; /* doubles as size for objects other than Torus */ +static int depth = 4; +static double offset[ 3 ] = { 0, 0, 0 }; +static GLboolean show_info = GL_TRUE; +static float ar; +static GLboolean persProject = GL_TRUE; +static GLboolean animateXRot = GL_FALSE; +static GLboolean useShader = GL_FALSE; +static GLboolean visNormals = GL_FALSE; +static GLboolean flat; + +/* + * Enum to tell drawSizeInfo what to draw for each object + */ +#define GEO_NO_SIZE 0 +#define GEO_SIZE 1 +#define GEO_SCALE 2 +#define GEO_INNER_OUTER_RAD 4 +#define GEO_RAD 8 +#define GEO_BASE_HEIGHT 16 +#define GEO_RAD_HEIGHT 32 + +/* + * These one-liners draw particular objects, fetching appropriate + * information from the above globals. They are just thin wrappers + * for the FreeGLUT objects. + */ +static void drawSolidTetrahedron(void) { glutSolidTetrahedron (); } +static void drawWireTetrahedron(void) { glutWireTetrahedron (); } +static void drawSolidCube(void) { glutSolidCube(orad); } /* orad doubles as size input */ +static void drawWireCube(void) { glutWireCube(orad); } /* orad doubles as size input */ +static void drawSolidOctahedron(void) { glutSolidOctahedron (); } +static void drawWireOctahedron(void) { glutWireOctahedron (); } +static void drawSolidDodecahedron(void) { glutSolidDodecahedron (); } +static void drawWireDodecahedron(void) { glutWireDodecahedron (); } +static void drawSolidRhombicDodecahedron(void) { glutSolidRhombicDodecahedron (); } +static void drawWireRhombicDodecahedron(void) { glutWireRhombicDodecahedron (); } +static void drawSolidIcosahedron(void) { glutSolidIcosahedron (); } +static void drawWireIcosahedron(void) { glutWireIcosahedron (); } +static void drawSolidSierpinskiSponge(void) { glutSolidSierpinskiSponge (depth, offset, orad);} /* orad doubles as size input */ +static void drawWireSierpinskiSponge(void) { glutWireSierpinskiSponge (depth, offset, orad); } /* orad doubles as size input */ +static void drawSolidTorus(void) { glutSolidTorus(irad,orad,slices,stacks); } +static void drawWireTorus(void) { glutWireTorus (irad,orad,slices,stacks); } +static void drawSolidSphere(void) { glutSolidSphere(orad,slices,stacks); } /* orad doubles as size input */ +static void drawWireSphere(void) { glutWireSphere(orad,slices,stacks); } /* orad doubles as size input */ +static void drawSolidCone(void) { glutSolidCone(irad,orad,slices,stacks); } /* irad doubles as base input, and orad as height input */ +static void drawWireCone(void) { glutWireCone(irad,orad,slices,stacks); } /* irad doubles as base input, and orad as height input */ +static void drawSolidCylinder(void) { glutSolidCylinder(irad,orad,slices,stacks); } /* irad doubles as radius input, and orad as height input */ +static void drawWireCylinder(void) { glutWireCylinder(irad,orad,slices,stacks); } /* irad doubles as radius input, and orad as height input */ +/* per Glut manpage, it should be noted that the teapot is rendered + * with clockwise winding for front facing polygons... + * Same for the teacup and teaspoon + */ +static void drawSolidTeapot(void) +{ glFrontFace(GL_CW); glutSolidTeapot(orad); glFrontFace(GL_CCW); /* orad doubles as size input */} +static void drawWireTeapot(void) +{ glFrontFace(GL_CW); glutWireTeapot(orad); glFrontFace(GL_CCW); /* orad doubles as size input */} +static void drawSolidTeacup(void) +{ glFrontFace(GL_CW); glutSolidTeacup(orad); glFrontFace(GL_CCW); /* orad doubles as size input */} +static void drawWireTeacup(void) +{ glFrontFace(GL_CW); glutWireTeacup(orad); glFrontFace(GL_CCW); /* orad doubles as size input */} +static void drawSolidTeaspoon(void) +{ glFrontFace(GL_CW); glutSolidTeaspoon(orad); glFrontFace(GL_CCW); /* orad doubles as size input */} +static void drawWireTeaspoon(void) +{ glFrontFace(GL_CW); glutWireTeaspoon(orad); glFrontFace(GL_CCW); /* orad doubles as size input */} + +#define RADIUSFAC 0.70710678118654752440084436210485f + +static void drawSolidCuboctahedron(void) +{ + GLfloat radius = RADIUSFAC*(GLfloat)orad; /* orad doubles as size */ + glBegin( GL_TRIANGLES ); + glNormal3d( 0.577350269189, 0.577350269189, 0.577350269189); glVertex3d( radius, radius, 0.0 ); glVertex3d( 0.0, radius, radius ); glVertex3d( radius, 0.0, radius ); + glNormal3d( 0.577350269189, 0.577350269189,-0.577350269189); glVertex3d( radius, radius, 0.0 ); glVertex3d( radius, 0.0,-radius ); glVertex3d( 0.0, radius,-radius ); + glNormal3d( 0.577350269189,-0.577350269189, 0.577350269189); glVertex3d( radius,-radius, 0.0 ); glVertex3d( radius, 0.0, radius ); glVertex3d( 0.0,-radius, radius ); + glNormal3d( 0.577350269189,-0.577350269189,-0.577350269189); glVertex3d( radius,-radius, 0.0 ); glVertex3d( 0.0,-radius,-radius ); glVertex3d( radius, 0.0,-radius ); + glNormal3d(-0.577350269189, 0.577350269189, 0.577350269189); glVertex3d(-radius, radius, 0.0 ); glVertex3d(-radius, 0.0, radius ); glVertex3d( 0.0, radius, radius ); + glNormal3d(-0.577350269189, 0.577350269189,-0.577350269189); glVertex3d(-radius, radius, 0.0 ); glVertex3d( 0.0, radius,-radius ); glVertex3d(-radius, 0.0,-radius ); + glNormal3d(-0.577350269189,-0.577350269189, 0.577350269189); glVertex3d(-radius,-radius, 0.0 ); glVertex3d( 0.0,-radius, radius ); glVertex3d(-radius, 0.0, radius ); + glNormal3d(-0.577350269189,-0.577350269189,-0.577350269189); glVertex3d(-radius,-radius, 0.0 ); glVertex3d(-radius, 0.0,-radius ); glVertex3d( 0.0,-radius,-radius ); + glEnd(); + + glBegin( GL_QUADS ); + glNormal3d( 1.0, 0.0, 0.0 ); glVertex3d( radius, radius, 0.0 ); glVertex3d( radius, 0.0, radius ); glVertex3d( radius,-radius, 0.0 ); glVertex3d( radius, 0.0,-radius ); + glNormal3d(-1.0, 0.0, 0.0 ); glVertex3d(-radius, radius, 0.0 ); glVertex3d(-radius, 0.0,-radius ); glVertex3d(-radius,-radius, 0.0 ); glVertex3d(-radius, 0.0, radius ); + glNormal3d( 0.0, 1.0, 0.0 ); glVertex3d( radius, radius, 0.0 ); glVertex3d( 0.0, radius,-radius ); glVertex3d(-radius, radius, 0.0 ); glVertex3d( 0.0, radius, radius ); + glNormal3d( 0.0,-1.0, 0.0 ); glVertex3d( radius,-radius, 0.0 ); glVertex3d( 0.0,-radius, radius ); glVertex3d(-radius,-radius, 0.0 ); glVertex3d( 0.0,-radius,-radius ); + glNormal3d( 0.0, 0.0, 1.0 ); glVertex3d( radius, 0.0, radius ); glVertex3d( 0.0, radius, radius ); glVertex3d(-radius, 0.0, radius ); glVertex3d( 0.0,-radius, radius ); + glNormal3d( 0.0, 0.0,-1.0 ); glVertex3d( radius, 0.0,-radius ); glVertex3d( 0.0,-radius,-radius ); glVertex3d(-radius, 0.0,-radius ); glVertex3d( 0.0, radius,-radius ); + glEnd(); +} + +static void drawWireCuboctahedron(void) +{ + GLfloat radius = RADIUSFAC*(GLfloat)orad; /* orad doubles as size */ + glBegin( GL_LINE_LOOP ); + glNormal3d( 1.0, 0.0, 0.0 ); glVertex3d( radius, radius, 0.0 ); glVertex3d( radius, 0.0, radius ); glVertex3d( radius,-radius, 0.0 ); glVertex3d( radius, 0.0,-radius ); + glEnd(); + glBegin( GL_LINE_LOOP ); + glNormal3d(-1.0, 0.0, 0.0 ); glVertex3d(-radius, radius, 0.0 ); glVertex3d(-radius, 0.0,-radius ); glVertex3d(-radius,-radius, 0.0 ); glVertex3d(-radius, 0.0, radius ); + glEnd(); + glBegin( GL_LINE_LOOP ); + glNormal3d( 0.0, 1.0, 0.0 ); glVertex3d( radius, radius, 0.0 ); glVertex3d( 0.0, radius,-radius ); glVertex3d(-radius, radius, 0.0 ); glVertex3d( 0.0, radius, radius ); + glEnd(); + glBegin( GL_LINE_LOOP ); + glNormal3d( 0.0,-1.0, 0.0 ); glVertex3d( radius,-radius, 0.0 ); glVertex3d( 0.0,-radius, radius ); glVertex3d(-radius,-radius, 0.0 ); glVertex3d( 0.0,-radius,-radius ); + glEnd(); + glBegin( GL_LINE_LOOP ); + glNormal3d( 0.0, 0.0, 1.0 ); glVertex3d( radius, 0.0, radius ); glVertex3d( 0.0, radius, radius ); glVertex3d(-radius, 0.0, radius ); glVertex3d( 0.0,-radius, radius ); + glEnd(); + glBegin( GL_LINE_LOOP ); + glNormal3d( 0.0, 0.0,-1.0 ); glVertex3d( radius, 0.0,-radius ); glVertex3d( 0.0,-radius,-radius ); glVertex3d(-radius, 0.0,-radius ); glVertex3d( 0.0, radius,-radius ); + glEnd(); +} + +#undef RADIUSFAC + +/* + * This structure defines an entry in our function-table. + */ +typedef struct +{ + const char * const name; + void (*solid) (void); + void (*wire) (void); + int drawSizeInfoFlag; +} entry; + +#define ENTRY(e,f) {#e, drawSolid##e, drawWire##e,f} +static const entry table [] = +{ + ENTRY (Tetrahedron,GEO_NO_SIZE), + ENTRY (Cube,GEO_SIZE), + ENTRY (Octahedron,GEO_NO_SIZE), + ENTRY (Dodecahedron,GEO_NO_SIZE), + ENTRY (RhombicDodecahedron,GEO_NO_SIZE), + ENTRY (Icosahedron,GEO_NO_SIZE), + ENTRY (SierpinskiSponge,GEO_SCALE), + ENTRY (Teapot,GEO_SIZE), + ENTRY (Teacup,GEO_SIZE), + ENTRY (Teaspoon,GEO_SIZE), + ENTRY (Torus,GEO_INNER_OUTER_RAD), + ENTRY (Sphere,GEO_RAD), + ENTRY (Cone,GEO_BASE_HEIGHT), + ENTRY (Cylinder,GEO_RAD_HEIGHT), + ENTRY (Cuboctahedron,GEO_SIZE) /* This one doesn't work when in shader mode and is then skipped */ +}; +#undef ENTRY + +/*! + Does printf()-like work using freeglut + glutBitmapString(). Uses a fixed font. Prints + at the indicated row/column position. + + Limitation: Cannot address pixels. + Limitation: Renders in screen coords, not model coords. +*/ +static void shapesPrintf (int row, int col, const char *fmt, ...) +{ + static char buf[256]; + int viewport[4]; + void *font = GLUT_BITMAP_9_BY_15; + va_list args; + + va_start(args, fmt); +#if defined(WIN32) && !defined(__CYGWIN__) + (void) _vsnprintf (buf, sizeof(buf), fmt, args); +#else + (void) vsnprintf (buf, sizeof(buf), fmt, args); +#endif + va_end(args); + + glGetIntegerv(GL_VIEWPORT,viewport); + + glPushMatrix(); + glLoadIdentity(); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glOrtho(0,viewport[2],0,viewport[3],-1,1); + + glRasterPos2i + ( + glutBitmapWidth(font, ' ') * col, + - glutBitmapHeight(font) * row + viewport[3] + ); + glutBitmapString (font, (unsigned char*)buf); + + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +} + +/* Print info about the about the current shape and render state on the screen */ +static void DrawSizeInfo(int *row) +{ + switch (table [function_index].drawSizeInfoFlag) + { + case GEO_NO_SIZE: + break; + case GEO_SIZE: + shapesPrintf ((*row)++, 1, "Size Up Down : %f", orad); + break; + case GEO_SCALE: + shapesPrintf ((*row)++, 1, "Scale Up Down : %f", orad); + break; + case GEO_INNER_OUTER_RAD: + shapesPrintf ((*row)++, 1, "Inner radius Left Right: %f", irad); + shapesPrintf ((*row)++, 1, "Outer radius Up Down : %f", orad); + break; + case GEO_RAD: + shapesPrintf ((*row)++, 1, "Radius Up Down : %f", orad); + break; + case GEO_BASE_HEIGHT: + shapesPrintf ((*row)++, 1, "Base Left Right: %f", irad); + shapesPrintf ((*row)++, 1, "Height Up Down : %f", orad); + break; + case GEO_RAD_HEIGHT: + shapesPrintf ((*row)++, 1, "Radius Left Right: %f", irad); + shapesPrintf ((*row)++, 1, "Height Up Down : %f", orad); + break; + } +} + +static void drawInfo() +{ + int row = 1; + shapesPrintf (row++, 1, "Shape PgUp PgDn: %s", table [function_index].name); + shapesPrintf (row++, 1, "Slices +-: %d Stacks <>: %d", slices, stacks); + shapesPrintf (row++, 1, "nSides +-: %d nRings <>: %d", slices, stacks); + shapesPrintf (row++, 1, "Depth (): %d", depth); + DrawSizeInfo(&row); + if (persProject) + shapesPrintf (row++, 1, "Perspective projection (p)"); + else + shapesPrintf (row++, 1, "Orthographic projection (p)"); + if (useShader) { + shapesPrintf (row++, 1, "Using shader (s)"); + } else { + shapesPrintf (row++, 1, "Using fixed function pipeline (s)"); + if (flat) + shapesPrintf (row++, 1, "Flat shading (f)"); + else + shapesPrintf (row++, 1, "Smooth shading (f)"); + } + if (animateXRot) + shapesPrintf (row++, 1, "2D rotation (r)"); + else + shapesPrintf (row++, 1, "1D rotation (r)"); + shapesPrintf (row++, 1, "visualizing normals: %i (n)",visNormals); +} + +/* GLUT callback Handlers */ +static void +resize(int width, int height) +{ + ar = (float) width / (float) height; + + glViewport(0, 0, width, height); +} + +static void display(void) +{ + const double t = glutGet(GLUT_ELAPSED_TIME) / 1000.0; + const double a = t*89.0; + const double b = (animateXRot?t:1)*67.0; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glutSetOption(GLUT_GEOMETRY_VISUALIZE_NORMALS,visNormals); /* Normals visualized or not? */ + + glShadeModel(flat ? GL_FLAT : GL_SMOOTH); /* flat or gouraud shading */ + + if (useShader && !shaderReady) + initShader(); + + if (useShader && shaderReady) + { + /* setup use of shader (and vertex buffer by FreeGLUT) */ + gl_UseProgram (program); + glutSetVertexAttribCoord3(attribute_fg_coord); + glutSetVertexAttribNormal(attribute_fg_normal); + /* There is also a glutSetVertexAttribTexCoord2, which is used only when drawing the teapot, teacup or teaspoon */ + + gl_matrix_mode(GL_PROJECTION); + gl_load_identity(); + if (persProject) + gl_frustum(-ar, ar, -1.f, 1.f, 2.f, 100.f); + else + gl_ortho(-ar*3, ar*3, -3.f, 3.f, 2.f, 100.f); + gl_UniformMatrix4fv (uniform_p, 1, GL_FALSE, get_matrix(GL_PROJECTION)); + + + gl_matrix_mode(GL_MODELVIEW); + gl_load_identity(); + + gl_push_matrix(); + /* Not in reverse order like normal OpenGL, our util library multiplies the matrices in the order they are specified in */ + gl_rotatef((float)a,0,0,1); + gl_rotatef((float)b,1,0,0); + gl_translatef(0,1.2f,-6); + gl_UniformMatrix4fv (uniform_m , 1, GL_FALSE, get_matrix(GL_MODELVIEW)); + gl_UniformMatrix3fv (uniform_m_3x3_inv_transp, 1, GL_FALSE, get_inv_transpose_3x3(GL_MODELVIEW)); + table [function_index].solid (); + gl_pop_matrix(); + + gl_push_matrix(); + gl_rotatef((float)a,0,0,1); + gl_rotatef((float)b,1,0,0); + gl_translatef(0,-1.2f,-6); + gl_UniformMatrix4fv (uniform_m , 1, GL_FALSE, get_matrix(GL_MODELVIEW)); + gl_UniformMatrix3fv (uniform_m_3x3_inv_transp, 1, GL_FALSE, get_inv_transpose_3x3(GL_MODELVIEW)); + table [function_index].wire (); + gl_pop_matrix(); + + gl_UseProgram (0); + glutSetVertexAttribCoord3(-1); + glutSetVertexAttribNormal(-1); + + checkError ("display"); + } + else + { + /* fixed function pipeline */ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + if (persProject) + glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0); + else + glOrtho(-ar*3, ar*3, -3.0, 3.0, 2.0, 100.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glEnable(GL_LIGHTING); + + glColor3d(1,0,0); + + glPushMatrix(); + glTranslated(0,1.2,-6); + glRotated(b,1,0,0); + glRotated(a,0,0,1); + table [function_index].solid (); + glPopMatrix(); + + glPushMatrix(); + glTranslated(0,-1.2,-6); + glRotated(b,1,0,0); + glRotated(a,0,0,1); + table [function_index].wire (); + glPopMatrix(); + + glDisable(GL_LIGHTING); + glColor3d(0.1,0.1,0.4); + } + + if( show_info ) + /* print info to screen */ + drawInfo(); + else + /* print to command line instead */ + printf ( "Shape %d slides %d stacks %d\n", function_index, slices, stacks ) ; + + glutSwapBuffers(); +} + + +static void +key(unsigned char key, int x, int y) +{ + switch (key) + { + case 27 : + case 'Q': + case 'q': glutLeaveMainLoop () ; break; + + case 'I': + case 'i': show_info=!show_info; break; + + case '=': + case '+': slices++; break; + + case '-': + case '_': if( slices > -1 ) slices--; break; + + case ',': + case '<': if( stacks > -1 ) stacks--; break; + + case '.': + case '>': stacks++; break; + + case '9': + case '(': if( depth > -1 ) depth--; break; + + case '0': + case ')': ++depth; break; + + case 'P': + case 'p': persProject=!persProject; break; + + case 'R': + case 'r': animateXRot=!animateXRot; break; + + case 'S': + case 's': + useShader=!useShader; + /* Cuboctahedron can't be shown when in shader mode, move to next */ + if (useShader && NUMBEROF (table)-1 == ( unsigned )function_index) + function_index = 0; + break; + + case 'F': + case 'f': + flat ^= 1; + break; + + case 'N': + case 'n': visNormals=!visNormals; break; + + default: + break; + } + + glutPostRedisplay(); +} + +static void special (int key, int x, int y) +{ + switch (key) + { + case GLUT_KEY_PAGE_UP: ++function_index; break; + case GLUT_KEY_PAGE_DOWN: --function_index; break; + case GLUT_KEY_UP: orad *= 2; break; + case GLUT_KEY_DOWN: orad /= 2; break; + + case GLUT_KEY_RIGHT: irad *= 2; break; + case GLUT_KEY_LEFT: irad /= 2; break; + + default: + break; + } + + if (0 > function_index) + function_index = NUMBEROF (table) - 1; + + if (NUMBEROF (table) <= ( unsigned )function_index) + function_index = 0; + + /* Cuboctahedron can't be shown when in shader mode, skip it */ + if (useShader && NUMBEROF (table)-1 == ( unsigned )function_index) + { + if (key==GLUT_KEY_PAGE_UP) + function_index = 0; + else + function_index -= 1; + } +} + + +static void +idle(void) +{ + glutPostRedisplay(); +} + +const GLfloat light_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f }; +const GLfloat light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f }; +const GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; +const GLfloat light_position[] = { 2.0f, 5.0f, 5.0f, 0.0f }; + +const GLfloat mat_ambient[] = { 0.7f, 0.7f, 0.7f, 1.0f }; +const GLfloat mat_diffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f }; +const GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; +const GLfloat high_shininess[] = { 100.0f }; + +/* Program entry point */ + +int +main(int argc, char *argv[]) +{ + glutInitWindowSize(800,600); + glutInitWindowPosition(40,40); + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE); + + glutCreateWindow("FreeGLUT Shapes"); + + glutReshapeFunc(resize); + glutDisplayFunc(display); + glutKeyboardFunc(key); + glutSpecialFunc(special); + glutIdleFunc(idle); + + glutSetOption ( GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION ) ; + + glClearColor(1,1,1,1); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + + glEnable(GL_LIGHT0); + glEnable(GL_NORMALIZE); + glEnable(GL_COLOR_MATERIAL); + + glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); + glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); + glLightfv(GL_LIGHT0, GL_POSITION, light_position); + + glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient); + glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); + glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); + glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess); + + initExtensionEntries(); + + glutMainLoop(); + +#ifdef _MSC_VER + /* DUMP MEMORY LEAK INFORMATION */ + _CrtDumpMemoryLeaks () ; +#endif + + return EXIT_SUCCESS; +} diff --git a/progs/demos/smooth_opengl3/smooth_opengl3.c b/progs/demos/smooth_opengl3/smooth_opengl3.c new file mode 100755 index 0000000..93e708d --- /dev/null +++ b/progs/demos/smooth_opengl3/smooth_opengl3.c @@ -0,0 +1,469 @@ +/* + * smooth_opengl3.c, based on smooth.c, which is (c) by SGI, see below. + * This program demonstrates smooth shading in a way which is fully + * OpenGL-3.1-compliant. + * A smooth shaded polygon is drawn in a 2-D projection. + */ + +/* + * Original copyright notice from smooth.c: + * + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 1.1 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + * + */ + +#include +#include +#include +#include +#include + +/* report GL errors, if any, to stderr */ +void checkError(const char *functionName) +{ + GLenum error; + while (( error = glGetError() ) != GL_NO_ERROR) { + fprintf (stderr, "GL error 0x%X detected in %s\n", error, functionName); + } +} + +/* extension #defines, types and entries, avoiding a dependency on additional + libraries like GLEW or the GL/glext.h header */ +#ifndef GL_ARRAY_BUFFER +#define GL_ARRAY_BUFFER 0x8892 +#endif + +#ifndef GL_STATIC_DRAW +#define GL_STATIC_DRAW 0x88E4 +#endif + +#ifndef GL_FRAGMENT_SHADER +#define GL_FRAGMENT_SHADER 0x8B30 +#endif + +#ifndef GL_VERTEX_SHADER +#define GL_VERTEX_SHADER 0x8B31 +#endif + +#ifndef GL_SHADING_LANGUAGE_VERSION +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#endif + +#ifndef GL_COMPILE_STATUS +#define GL_COMPILE_STATUS 0x8B81 +#endif + +#ifndef GL_LINK_STATUS +#define GL_LINK_STATUS 0x8B82 +#endif + +#ifndef GL_INFO_LOG_LENGTH +#define GL_INFO_LOG_LENGTH 0x8B84 +#endif + +typedef ptrdiff_t ourGLsizeiptr; +typedef char ourGLchar; + +#ifndef APIENTRY +#define APIENTRY +#endif + + +#ifndef GL_ARB_vertex_array_object +typedef void (APIENTRY *PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays); +typedef void (APIENTRY *PFNGLBINDVERTEXARRAYPROC) (GLuint array); +#endif +#ifndef GL_VERSION_1_5 +typedef void (APIENTRY *PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers); +typedef void (APIENTRY *PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); +typedef void (APIENTRY *PFNGLBUFFERDATAPROC) (GLenum target, ourGLsizeiptr size, const GLvoid *data, GLenum usage); +#endif +#ifndef GL_VERSION_2_0 +typedef GLuint (APIENTRY *PFNGLCREATESHADERPROC) (GLenum type); +typedef void (APIENTRY *PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const ourGLchar **string, const GLint *length); +typedef void (APIENTRY *PFNGLCOMPILESHADERPROC) (GLuint shader); +typedef GLuint (APIENTRY *PFNGLCREATEPROGRAMPROC) (void); +typedef void (APIENTRY *PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (APIENTRY *PFNGLLINKPROGRAMPROC) (GLuint program); +typedef void (APIENTRY *PFNGLUSEPROGRAMPROC) (GLuint program); +typedef void (APIENTRY *PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params); +typedef void (APIENTRY *PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, ourGLchar *infoLog); +typedef void (APIENTRY *PFNGLGETPROGRAMIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY *PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, ourGLchar *infoLog); +typedef GLint (APIENTRY *PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const ourGLchar *name); +typedef void (APIENTRY *PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); +typedef void (APIENTRY *PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index); +typedef GLint (APIENTRY *PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const ourGLchar *name); +typedef void (APIENTRY *PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +#endif + +PFNGLGENVERTEXARRAYSPROC gl_GenVertexArrays; +PFNGLBINDVERTEXARRAYPROC gl_BindVertexArray; +PFNGLGENBUFFERSPROC gl_GenBuffers; +PFNGLBINDBUFFERPROC gl_BindBuffer; +PFNGLBUFFERDATAPROC gl_BufferData; +PFNGLCREATESHADERPROC gl_CreateShader; +PFNGLSHADERSOURCEPROC gl_ShaderSource; +PFNGLCOMPILESHADERPROC gl_CompileShader; +PFNGLCREATEPROGRAMPROC gl_CreateProgram; +PFNGLATTACHSHADERPROC gl_AttachShader; +PFNGLLINKPROGRAMPROC gl_LinkProgram; +PFNGLUSEPROGRAMPROC gl_UseProgram; +PFNGLGETSHADERIVPROC gl_GetShaderiv; +PFNGLGETSHADERINFOLOGPROC gl_GetShaderInfoLog; +PFNGLGETPROGRAMIVPROC gl_GetProgramiv; +PFNGLGETPROGRAMINFOLOGPROC gl_GetProgramInfoLog; +PFNGLGETATTRIBLOCATIONPROC gl_GetAttribLocation; +PFNGLVERTEXATTRIBPOINTERPROC gl_VertexAttribPointer; +PFNGLENABLEVERTEXATTRIBARRAYPROC gl_EnableVertexAttribArray; +PFNGLGETUNIFORMLOCATIONPROC gl_GetUniformLocation; +PFNGLUNIFORMMATRIX4FVPROC gl_UniformMatrix4fv; + +void initExtensionEntries(void) +{ + gl_GenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) glutGetProcAddress ("glGenVertexArrays"); + gl_BindVertexArray = (PFNGLBINDVERTEXARRAYPROC) glutGetProcAddress ("glBindVertexArray"); + if (!gl_GenVertexArrays || !gl_BindVertexArray) + { + fprintf (stderr, "glGenVertexArrays or glBindVertexArray not found"); + exit(1); + } + gl_GenBuffers = (PFNGLGENBUFFERSPROC) glutGetProcAddress ("glGenBuffers"); + gl_BindBuffer = (PFNGLBINDBUFFERPROC) glutGetProcAddress ("glBindBuffer"); + gl_BufferData = (PFNGLBUFFERDATAPROC) glutGetProcAddress ("glBufferData"); + if (!gl_GenBuffers || !gl_BindBuffer || !gl_BufferData) + { + fprintf (stderr, "glGenBuffers, glBindBuffer or glBufferData not found"); + exit(1); + } + gl_CreateShader = (PFNGLCREATESHADERPROC) glutGetProcAddress ("glCreateShader"); + gl_ShaderSource = (PFNGLSHADERSOURCEPROC) glutGetProcAddress ("glShaderSource"); + gl_CompileShader = (PFNGLCOMPILESHADERPROC) glutGetProcAddress ("glCompileShader"); + gl_CreateProgram = (PFNGLCREATEPROGRAMPROC) glutGetProcAddress ("glCreateProgram"); + gl_AttachShader = (PFNGLATTACHSHADERPROC) glutGetProcAddress ("glAttachShader"); + gl_LinkProgram = (PFNGLLINKPROGRAMPROC) glutGetProcAddress ("glLinkProgram"); + gl_UseProgram = (PFNGLUSEPROGRAMPROC) glutGetProcAddress ("glUseProgram"); + gl_GetShaderiv = (PFNGLGETSHADERIVPROC) glutGetProcAddress ("glGetShaderiv"); + gl_GetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) glutGetProcAddress ("glGetShaderInfoLog"); + gl_GetProgramiv = (PFNGLGETPROGRAMIVPROC) glutGetProcAddress ("glGetProgramiv"); + gl_GetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) glutGetProcAddress ("glGetProgramInfoLog"); + gl_GetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) glutGetProcAddress ("glGetAttribLocation"); + gl_VertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC) glutGetProcAddress ("glVertexAttribPointer"); + gl_EnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC) glutGetProcAddress ("glEnableVertexAttribArray"); + gl_GetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) glutGetProcAddress ("glGetUniformLocation"); + gl_UniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) glutGetProcAddress ("glUniformMatrix4fv"); + if (!gl_CreateShader || !gl_ShaderSource || !gl_CompileShader || !gl_CreateProgram || !gl_AttachShader || !gl_LinkProgram || !gl_UseProgram || !gl_GetShaderiv || !gl_GetShaderInfoLog || !gl_GetProgramiv || !gl_GetProgramInfoLog || !gl_GetAttribLocation || !gl_VertexAttribPointer || !gl_EnableVertexAttribArray || !gl_GetUniformLocation || !gl_UniformMatrix4fv) + { + fprintf (stderr, "glCreateShader, glShaderSource, glCompileShader, glCreateProgram, glAttachShader, glLinkProgram, glUseProgram, glGetShaderiv, glGetShaderInfoLog, glGetProgramiv, glGetProgramInfoLog, glGetAttribLocation, glVertexAttribPointer, glEnableVertexAttribArray, glGetUniformLocation or glUniformMatrix4fv not found"); + exit(1); + } +} + +/* vertex array data for a colored 2D triangle, consisting of RGB color values + and XY coordinates */ +const GLfloat varray[] = { + 1.0f, 0.0f, 0.0f, /* red */ + 5.0f, 5.0f, /* lower left */ + + 0.0f, 1.0f, 0.0f, /* green */ + 25.0f, 5.0f, /* lower right */ + + 0.0f, 0.0f, 1.0f, /* blue */ + 5.0f, 25.0f /* upper left */ +}; + +/* ISO C somehow enforces this silly use of 'enum' for compile-time constants */ +enum { + numColorComponents = 3, + numVertexComponents = 2, + stride = sizeof(GLfloat) * (numColorComponents + numVertexComponents), + numElements = sizeof(varray) / stride +}; + +/* the name of the vertex buffer object */ +GLuint vertexBufferName; +GLuint vertexArrayName; + +void initBuffer(void) +{ + /* Need to setup a vertex array as otherwise invalid operation errors can + * occur when accessing vertex buffer (OpenGL 3.3 has no default zero named + * vertex array) + */ + gl_GenVertexArrays(1, &vertexArrayName); + gl_BindVertexArray(vertexArrayName); + + gl_GenBuffers (1, &vertexBufferName); + gl_BindBuffer (GL_ARRAY_BUFFER, vertexBufferName); + gl_BufferData (GL_ARRAY_BUFFER, sizeof(varray), varray, GL_STATIC_DRAW); + checkError ("initBuffer"); +} + +const ourGLchar *vertexShaderSource[] = { + "#version 140\n", + "uniform mat4 fg_ProjectionMatrix;\n", + "in vec4 fg_Color;\n", + "in vec4 fg_Vertex;\n", + "smooth out vec4 fg_SmoothColor;\n", + "void main()\n", + "{\n", + " fg_SmoothColor = fg_Color;\n", + " gl_Position = fg_ProjectionMatrix * fg_Vertex;\n", + "}\n" +}; + +const ourGLchar *fragmentShaderSource[] = { + "#version 140\n", + "smooth in vec4 fg_SmoothColor;\n", + "out vec4 fg_FragColor;\n", + "void main(void)\n", + "{\n", + " fg_FragColor = fg_SmoothColor;\n", + "}\n" +}; + +void compileAndCheck(GLuint shader) +{ + GLint status; + gl_CompileShader (shader); + gl_GetShaderiv (shader, GL_COMPILE_STATUS, &status); + if (status == GL_FALSE) { + GLint infoLogLength; + ourGLchar *infoLog; + gl_GetShaderiv (shader, GL_INFO_LOG_LENGTH, &infoLogLength); + infoLog = (ourGLchar*) malloc (infoLogLength); + gl_GetShaderInfoLog (shader, infoLogLength, NULL, infoLog); + fprintf (stderr, "compile log: %s\n", infoLog); + free (infoLog); + } +} + +GLuint compileShaderSource(GLenum type, GLsizei count, const ourGLchar **string) +{ + GLuint shader = gl_CreateShader (type); + gl_ShaderSource (shader, count, string, NULL); + compileAndCheck (shader); + return shader; +} + +void linkAndCheck(GLuint program) +{ + GLint status; + gl_LinkProgram (program); + gl_GetProgramiv (program, GL_LINK_STATUS, &status); + if (status == GL_FALSE) { + GLint infoLogLength; + ourGLchar *infoLog; + gl_GetProgramiv (program, GL_INFO_LOG_LENGTH, &infoLogLength); + infoLog = (ourGLchar*) malloc (infoLogLength); + gl_GetProgramInfoLog (program, infoLogLength, NULL, infoLog); + fprintf (stderr, "link log: %s\n", infoLog); + free (infoLog); + } +} + +GLuint createProgram(GLuint vertexShader, GLuint fragmentShader) +{ + GLuint program = gl_CreateProgram (); + if (vertexShader != 0) { + gl_AttachShader (program, vertexShader); + } + if (fragmentShader != 0) { + gl_AttachShader (program, fragmentShader); + } + linkAndCheck (program); + return program; +} + +GLuint fgProjectionMatrixIndex; +GLuint fgColorIndex; +GLuint fgVertexIndex; + +void initShader(void) +{ + const GLsizei vertexShaderLines = sizeof(vertexShaderSource) / sizeof(ourGLchar*); + GLuint vertexShader = + compileShaderSource (GL_VERTEX_SHADER, vertexShaderLines, vertexShaderSource); + + const GLsizei fragmentShaderLines = sizeof(fragmentShaderSource) / sizeof(ourGLchar*); + GLuint fragmentShader = + compileShaderSource (GL_FRAGMENT_SHADER, fragmentShaderLines, fragmentShaderSource); + + GLuint program = createProgram (vertexShader, fragmentShader); + + gl_UseProgram (program); + + fgProjectionMatrixIndex = gl_GetUniformLocation(program, "fg_ProjectionMatrix"); + + fgColorIndex = gl_GetAttribLocation(program, "fg_Color"); + gl_EnableVertexAttribArray (fgColorIndex); + + fgVertexIndex = gl_GetAttribLocation(program, "fg_Vertex"); + gl_EnableVertexAttribArray (fgVertexIndex); + + checkError ("initShader"); +} + +void initRendering(void) +{ + glClearColor (0.0, 0.0, 0.0, 0.0); + checkError ("initRendering"); +} + +void init(void) +{ + initExtensionEntries (); + initBuffer (); + initShader (); + initRendering (); +} + +void dumpInfo(void) +{ + printf ("Vendor: %s\n", glGetString (GL_VENDOR)); + printf ("Renderer: %s\n", glGetString (GL_RENDERER)); + printf ("Version: %s\n", glGetString (GL_VERSION)); + printf ("GLSL: %s\n", glGetString (GL_SHADING_LANGUAGE_VERSION)); + checkError ("dumpInfo"); +} + +const GLvoid *bufferObjectPtr (GLsizei index) +{ + return (const GLvoid *) (((char *) NULL) + index); +} + +GLfloat projectionMatrix[16]; + +void triangle(void) +{ + gl_UniformMatrix4fv (fgProjectionMatrixIndex, 1, GL_FALSE, projectionMatrix); + + gl_BindBuffer (GL_ARRAY_BUFFER, vertexBufferName); + gl_VertexAttribPointer (fgColorIndex, numColorComponents, GL_FLOAT, GL_FALSE, + stride, bufferObjectPtr (0)); + gl_VertexAttribPointer (fgVertexIndex, numVertexComponents, GL_FLOAT, GL_FALSE, + stride, bufferObjectPtr (sizeof(GLfloat) * numColorComponents)); + glDrawArrays(GL_TRIANGLES, 0, numElements); + checkError ("triangle"); +} + +void display(void) +{ + glClear (GL_COLOR_BUFFER_BIT); + triangle (); + glFlush (); + checkError ("display"); +} + +void loadOrthof(GLfloat *m, GLfloat l, GLfloat r, GLfloat b, GLfloat t, + GLfloat n, GLfloat f) +{ + m[ 0] = 2.0f / (r - l); + m[ 1] = 0.0f; + m[ 2] = 0.0f; + m[ 3] = 0.0f; + + m[ 4] = 0.0f; + m[ 5] = 2.0f / (t - b); + m[ 6] = 0.0f; + m[ 7] = 0.0f; + + m[ 8] = 0.0f; + m[ 9] = 0.0f; + m[10] = -2.0f / (f - n); + m[11] = 0.0f; + + m[12] = -(r + l) / (r - l); + m[13] = -(t + b) / (t - b); + m[14] = -(f + n) / (f - n); + m[15] = 1.0f; +} + +void loadOrtho2Df(GLfloat *m, GLfloat l, GLfloat r, GLfloat b, GLfloat t) +{ + loadOrthof (m, l, r, b, t, -1.0f, 1.0f); +} + +void reshape (int w, int h) +{ + glViewport (0, 0, (GLsizei) w, (GLsizei) h); + if (w <= h) { + loadOrtho2Df (projectionMatrix, 0.0f, 30.0f, 0.0f, 30.0f * (GLfloat) h/(GLfloat) w); + } else { + loadOrtho2Df (projectionMatrix, 0.0f, 30.0f * (GLfloat) w/(GLfloat) h, 0.0f, 30.0f); + } + checkError ("reshape"); +} + +void keyboard(unsigned char key, int x, int y) +{ + switch (key) { + case 27: + exit(0); + break; + } +} + +void samplemenu(int menuID) +{} + +int main(int argc, char** argv) +{ + int menuA; + glutInit(&argc, argv); + glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); + /* add command line argument "classic" for a pre-3.x context */ + if ((argc != 2) || (strcmp (argv[1], "classic") != 0)) { + glutInitContextVersion (3, 1); + glutInitContextFlags (GLUT_FORWARD_COMPATIBLE | GLUT_DEBUG); + } + glutInitWindowSize (500, 500); + glutInitWindowPosition (100, 100); + glutCreateWindow (argv[0]); + dumpInfo (); + init (); + glutDisplayFunc(display); + glutReshapeFunc(reshape); + glutKeyboardFunc (keyboard); + + /* Add a menu. They have their own context and should thus work with forward compatible main windows too. */ + menuA = glutCreateMenu(samplemenu); + glutAddMenuEntry("Sub menu A1 (01)",1); + glutAddMenuEntry("Sub menu A2 (02)",2); + glutAddMenuEntry("Sub menu A3 (03)",3); + glutSetMenu(menuA); + glutAttachMenu(GLUT_RIGHT_BUTTON); + + glutMainLoop(); + return 0; +} diff --git a/progs/demos/spaceball/spaceball.c b/progs/demos/spaceball/spaceball.c new file mode 100644 index 0000000..52da93a --- /dev/null +++ b/progs/demos/spaceball/spaceball.c @@ -0,0 +1,177 @@ +/* Spaceball demo + * + * Written by John Tsiombikas + * (converted from the libspnav cube example) + * + * Use the spaceball to move and rotate the colored cube. + * Pressing any button will reset the cube at its original location. + * + * Press escape or q to exit. + */ + +#include +#include +#include +#include +#include "vmath.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846264338327950 +#endif + +void draw_cube(void); + +/* callbacks */ +void disp(void); +void reshape(int x, int y); +void keyb(unsigned char key, int x, int y); +void sbmot(int x, int y, int z); /* spaceball translation */ +void sbrot(int x, int y, int z); /* spaceball rotation */ +void sbbut(int bn, int state); /* spaceball button */ + +vec3_t pos = {0, 0, -6}; +quat_t rot = {0, 0, 0, 1}; + +int main(int argc, char **argv) +{ + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); + glutCreateWindow("spaceball demo"); + + glutDisplayFunc(disp); + glutReshapeFunc(reshape); + glutKeyboardFunc(keyb); + glutSpaceballMotionFunc(sbmot); + glutSpaceballRotateFunc(sbrot); + glutSpaceballButtonFunc(sbbut); + + glEnable(GL_CULL_FACE); + + glutMainLoop(); + return 0; +} + +void disp(void) +{ + mat4_t xform; + + quat_to_mat(xform, rot); + + glClear(GL_COLOR_BUFFER_BIT); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(pos.x, pos.y, pos.z); + glMultMatrixf((float*)xform); + + draw_cube(); + + glutSwapBuffers(); +} + +void draw_cube(void) +{ + glBegin(GL_QUADS); + /* face +Z */ + glNormal3f(0, 0, 1); + glColor3f(1, 0, 0); + glVertex3f(-1, -1, 1); + glVertex3f(1, -1, 1); + glVertex3f(1, 1, 1); + glVertex3f(-1, 1, 1); + /* face +X */ + glNormal3f(1, 0, 0); + glColor3f(0, 1, 0); + glVertex3f(1, -1, 1); + glVertex3f(1, -1, -1); + glVertex3f(1, 1, -1); + glVertex3f(1, 1, 1); + /* face -Z */ + glNormal3f(0, 0, -1); + glColor3f(0, 0, 1); + glVertex3f(1, -1, -1); + glVertex3f(-1, -1, -1); + glVertex3f(-1, 1, -1); + glVertex3f(1, 1, -1); + /* face -X */ + glNormal3f(-1, 0, 0); + glColor3f(1, 1, 0); + glVertex3f(-1, -1, -1); + glVertex3f(-1, -1, 1); + glVertex3f(-1, 1, 1); + glVertex3f(-1, 1, -1); + /* face +Y */ + glNormal3f(0, 1, 0); + glColor3f(0, 1, 1); + glVertex3f(-1, 1, 1); + glVertex3f(1, 1, 1); + glVertex3f(1, 1, -1); + glVertex3f(-1, 1, -1); + /* face -Y */ + glNormal3f(0, -1, 0); + glColor3f(1, 0, 1); + glVertex3f(-1, -1, -1); + glVertex3f(1, -1, -1); + glVertex3f(1, -1, 1); + glVertex3f(-1, -1, 1); + glEnd(); +} + +/* 45deg fov */ +#define FOV (M_PI / 4.0) + +void reshape(int x, int y) +{ + float aspect = (float)x / (float)y; + float halfy = (float)tan(FOV / 2.0); + float halfx = halfy * aspect; + + glViewport(0, 0, x, y); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-halfx, halfx, -halfy, halfy, 1.0, 1000.0); +} + +void keyb(unsigned char key, int x, int y) +{ + switch(key) { + case 'q': + case 'Q': + case 27: + exit(0); + + case ' ': + /* reset initial view */ + pos = v3_cons(0, 0, -6); + rot = quat_cons(1, 0, 0, 0); + glutPostRedisplay(); + + default: + break; + } +} + +void sbmot(int x, int y, int z) +{ + pos.x += x * 0.001f; + pos.y += y * 0.001f; + pos.z -= z * 0.001f; + glutPostRedisplay(); +} + +void sbrot(int x, int y, int z) +{ + float axis_len = (float)sqrt(x * x + y * y + z * z); + rot = quat_rotate(rot, axis_len * 0.001f, -x / axis_len, -y / axis_len, z / axis_len); + glutPostRedisplay(); +} + +void sbbut(int bn, int state) +{ + if(state == GLUT_DOWN) { + pos = v3_cons(0, 0, -6); + rot = quat_cons(1, 0, 0, 0); + glutPostRedisplay(); + } +} diff --git a/progs/demos/spaceball/vmath.c b/progs/demos/spaceball/vmath.c new file mode 100644 index 0000000..7ef3c25 --- /dev/null +++ b/progs/demos/spaceball/vmath.c @@ -0,0 +1,16 @@ +#include +#include "vmath.h" + +quat_t quat_rotate(quat_t q, float angle, float x, float y, float z) +{ + quat_t rq; + float half_angle = angle * 0.5f; + float sin_half = (float)sin(half_angle); + + rq.w = (float)cos(half_angle); + rq.x = x * sin_half; + rq.y = y * sin_half; + rq.z = z * sin_half; + + return quat_mul(q, rq); +} diff --git a/progs/demos/spaceball/vmath.h b/progs/demos/spaceball/vmath.h new file mode 100644 index 0000000..249a504 --- /dev/null +++ b/progs/demos/spaceball/vmath.h @@ -0,0 +1,38 @@ +#ifndef VMATH_H_ +#define VMATH_H_ + +#if defined(WIN32) +#define INLINE +#else +#define INLINE inline +#endif + + +typedef struct { float x, y, z; } vec3_t; +typedef struct { float x, y, z, w; } vec4_t; + +typedef vec4_t quat_t; + +typedef float mat4_t[4][4]; + +/* vector functions */ +static INLINE vec3_t v3_cons(float x, float y, float z); +static INLINE float v3_dot(vec3_t v1, vec3_t v2); + +/* quaternion functions */ +static INLINE quat_t quat_cons(float s, float x, float y, float z); +static INLINE vec3_t quat_vec(quat_t q); +static INLINE quat_t quat_mul(quat_t q1, quat_t q2); +static INLINE void quat_to_mat(mat4_t res, quat_t q); +quat_t quat_rotate(quat_t q, float angle, float x, float y, float z); + +/* matrix functions */ +static INLINE void m4_cons(mat4_t m, + float m11, float m12, float m13, float m14, + float m21, float m22, float m23, float m24, + float m31, float m32, float m33, float m34, + float m41, float m42, float m43, float m44); + +#include "vmath.inl" + +#endif /* VMATH_H_ */ diff --git a/progs/demos/spaceball/vmath.inl b/progs/demos/spaceball/vmath.inl new file mode 100644 index 0000000..e3ad6b8 --- /dev/null +++ b/progs/demos/spaceball/vmath.inl @@ -0,0 +1,68 @@ +/* vector functions */ +static INLINE vec3_t v3_cons(float x, float y, float z) +{ + vec3_t res; + res.x = x; + res.y = y; + res.z = z; + return res; +} + +static INLINE vec3_t quat_vec(quat_t q) +{ + vec3_t v; + v.x = q.x; + v.y = q.y; + v.z = q.z; + return v; +} + +static INLINE float v3_dot(vec3_t v1, vec3_t v2) +{ + return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; +} + +/* quaternion functions */ +static INLINE quat_t quat_cons(float s, float x, float y, float z) +{ + quat_t q; + q.x = x; + q.y = y; + q.z = z; + q.w = s; + return q; +} + +static INLINE quat_t quat_mul(quat_t q1, quat_t q2) +{ + quat_t res; + vec3_t v1 = quat_vec(q1); + vec3_t v2 = quat_vec(q2); + + res.w = q1.w * q2.w - v3_dot(v1, v2); + res.x = v2.x * q1.w + v1.x * q2.w + (v1.y * v2.z - v1.z * v2.y); + res.y = v2.y * q1.w + v1.y * q2.w + (v1.z * v2.x - v1.x * v2.z); + res.z = v2.z * q1.w + v1.z * q2.w + (v1.x * v2.y - v1.y * v2.x); + return res; +} + +static INLINE void quat_to_mat(mat4_t res, quat_t q) +{ + m4_cons(res, 1.0f - 2.0f * q.y*q.y - 2.0f * q.z*q.z, 2.0f * q.x * q.y + 2.0f * q.w * q.z, 2.0f * q.z * q.x - 2.0f * q.w * q.y, 0, + 2.0f * q.x * q.y - 2.0f * q.w * q.z, 1.0f - 2.0f * q.x*q.x - 2.0f * q.z*q.z, 2.0f * q.y * q.z + 2.0f * q.w * q.x, 0, + 2.0f * q.z * q.x + 2.0f * q.w * q.y, 2.0f * q.y * q.z - 2.0f * q.w * q.x, 1.0f - 2.0f * q.x*q.x - 2.0f * q.y*q.y, 0, + 0, 0, 0, 1); +} + +/* matrix functions */ +static INLINE void m4_cons(mat4_t m, + float m11, float m12, float m13, float m14, + float m21, float m22, float m23, float m24, + float m31, float m32, float m33, float m34, + float m41, float m42, float m43, float m44) +{ + m[0][0] = m11; m[1][0] = m12; m[2][0] = m13; m[3][0] = m14; + m[0][1] = m21; m[1][1] = m22; m[2][1] = m23; m[3][1] = m24; + m[0][2] = m31; m[1][2] = m32; m[2][2] = m33; m[3][2] = m34; + m[0][3] = m41; m[1][3] = m42; m[2][3] = m43; m[3][3] = m44; +} diff --git a/progs/demos/subwin/subwin.c b/progs/demos/subwin/subwin.c new file mode 100644 index 0000000..0572873 --- /dev/null +++ b/progs/demos/subwin/subwin.c @@ -0,0 +1,235 @@ +/*! \file subwin.c + \ingroup demos + + This program is a test harness for the subwindows + in OpenGLUT. Based Originally on shape.c demo. + + \author Written by Evan Felix February 2011 + + \author Portions Copyright (C) 2004, the OpenGLUT project contributors.
+ OpenGLUT branched from freeglut in February, 2004. + + \image html openglut_subwin.png OpenGLUT Sub Window Demonstration + \include demos/subwin/subwin.c +*/ + +#include + +#include +#include +#include +#include +#ifdef _MSC_VER +/* DUMP MEMORY LEAKS */ +#include +#endif + +#define MAXSTR 16 +char **strings; +int mainwin; + + +/*! + Does printf()-like work using freeglut/OpenGLUT + glutBitmapString(). Uses a fixed font. Prints + at the indicated row/column position. + + Limitation: Cannot address pixels. + Limitation: Renders in screen coords, not model coords. +*/ +static void shapesPrintf (int row, int col, const char *fmt, ...) +{ + static char buf[256]; + int viewport[4]; + void *font = GLUT_BITMAP_9_BY_15; + va_list args; + + va_start(args, fmt); +#if defined(WIN32) && !defined(__CYGWIN__) + (void) _vsnprintf (buf, sizeof(buf), fmt, args); +#else + (void) vsnprintf (buf, sizeof(buf), fmt, args); +#endif + va_end(args); + + glGetIntegerv(GL_VIEWPORT,viewport); + + glPushMatrix(); + glLoadIdentity(); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glOrtho(0,viewport[2],0,viewport[3],-1,1); + + glRasterPos2i + ( + glutBitmapWidth(font, ' ') * col, + - glutBitmapHeight(font) * (row+2) + viewport[3] + ); + glutBitmapString (font, (unsigned char*)buf); + + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +} + +/* GLUT callback Handlers */ + +static void +resize(int width, int height) +{ + + glViewport(0, 0, width, height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + /*gluOrtho2D(0, width, 0, height);*/ + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity() ; +} + +static void display(void) +{ + + int win = glutGetWindow(); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glColor3d(1,0,0); + + glDisable(GL_LIGHTING); + glColor3d(0.1,0.1,0.4); + + if (win == mainwin) + { + shapesPrintf (2, 3, "Move The mouse into different windows"); + shapesPrintf (3, 3, "pressing keys will add to the string"); + shapesPrintf (5, 3, "Window: %d", win); + shapesPrintf (6, 3, "String: %s", strings[win]); + } + else + { + shapesPrintf (1, 3, "Window: %d", win); + shapesPrintf (2, 3, "String: %s", strings[win]); + } + + glutSwapBuffers(); +} + + +static void +key(unsigned char key, int x, int y) +{ + char *s,str[2]; + int win = glutGetWindow(); + + switch (key) + { + case 27 : + case 'Q': + case 'q': glutLeaveMainLoop () ; break; + + default: + s=strings[win]; + if (strlen(s)+1>MAXSTR) { + s[0]=0; + } + str[0]=key; + str[1]=0; + strcat(s,str); + break; + } + + glutPostRedisplay(); +} + +static void special (int key, int x, int y) +{ + switch (key) + { + default: + break; + } + glutPostRedisplay(); +} + + +static void +entry(int state) +{ + int win = glutGetWindow(); + printf("Win: %d, state: %d\n",win,state); +} + +/* Program entry point */ + +int +main(int argc, char *argv[]) +{ + int winmax,sw1,sw2,sw2sw,i; + + glutInitWindowSize(640,480); + glutInitWindowPosition(40,40); + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE); + + glutCreateWindow("FreeGLUT Sub Windows"); + + glutReshapeFunc(resize); + glutDisplayFunc(display); + glutKeyboardFunc(key); + glutSpecialFunc(special); + glutEntryFunc(entry); + + glutSetOption ( GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION ) ; + + glClearColor(1,1,1,1); + + mainwin = glutGetWindow(); + winmax=mainwin; + + sw1=glutCreateSubWindow(mainwin,4,240,314,236); + glutReshapeFunc(resize); + glutDisplayFunc(display); + glutKeyboardFunc(key); + glutSpecialFunc(special); + glutEntryFunc(entry); + glClearColor(0.7f,0.7f,0.7f,1); + winmax = sw1 > winmax ? sw1 : winmax; + + sw2=glutCreateSubWindow(mainwin,322,240,314,236); + glutReshapeFunc(resize); + glutDisplayFunc(display); + glutKeyboardFunc(key); + glutSpecialFunc(special); + glutEntryFunc(entry); + glClearColor(0.7f,0.7f,0.7f,1); + winmax = sw2 > winmax ? sw2 : winmax; + + sw2sw=glutCreateSubWindow(sw2,10,128,294,98); + glutReshapeFunc(resize); + glutDisplayFunc(display); + glutKeyboardFunc(key); + glutSpecialFunc(special); + glutEntryFunc(entry); + glClearColor(0.4f,0.4f,0.4f,1); + winmax = sw2sw > winmax ? sw2sw : winmax; + + strings = malloc(sizeof(char *)*(winmax+1)); + for (i=0;i + * + * Demonstrate the use of glutTimerFunc, by changing the color of the + * framebuffer every (approximately) 1 sec. + */ +#include +#include + +void disp(void); +void timer_func(int unused); + +/* color index will be advanced every time the timer expires */ +int cidx = 0; +int pcidx = 2; +float color[][3] = { + {1, 0, 0}, + {0, 1, 0}, + {0, 0, 1}, + {1, 1, 0}, + {0, 1, 1}, + {1, 0, 1} +}; +int timerInts[] = { + 250, + 500, + 1000 +}; +int timerSurroundInt = 1000, timerCenterInt = 1000; + +/* menu IDs, creation/update funcs and callback */ +int menuID, subMenuSurround, subMenuCenter; + +void createMenuEntries(int which) +{ + int i; + for (i = 0; i < sizeof(timerInts) / sizeof(*timerInts); i++) + { + char temp[10] = {'\0'}; + /* flag current value */ + if ((which == 1 ? timerSurroundInt : timerCenterInt) == timerInts[i]) + temp[0] = '+'; + else + temp[0] = '-'; + + sprintf(temp + 1, " %4d ms", timerInts[i]); + + glutAddMenuEntry(temp, timerInts[i]); + } +} + +void updateMenuEntries(int which) +{ + int i; + for (i = 0; i < sizeof(timerInts) / sizeof(*timerInts); i++) + { + char temp[10] = { '\0' }; + /* flag current value */ + if ((which == 1 ? timerSurroundInt : timerCenterInt) == timerInts[i]) + temp[0] = '+'; + else + temp[0] = '-'; + + sprintf(temp + 1, " %4d ms", timerInts[i]); + + glutChangeToMenuEntry(i+1, temp, timerInts[i]); + } +} + +void MenuSurround(int timerInt) +{ + timerSurroundInt = timerInt; + glutSetMenu(subMenuSurround); + updateMenuEntries(1); +} +void MenuCenter(int timerInt) +{ + timerCenterInt = timerInt; + glutSetMenu(subMenuCenter); + updateMenuEntries(2); +} + +int main(int argc, char **argv) +{ + glutInit(&argc, argv); + glutInitWindowSize(128, 128); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); + glutCreateWindow("timer test"); + + glutDisplayFunc(disp); + + /* get timer started, its reset in the timer function itself */ + glutTimerFunc(1000, timer_func, 1); + glutTimerFunc(500, timer_func, 2); + + /* menus for setting timing */ + subMenuSurround = glutCreateMenu(MenuSurround); + createMenuEntries(1); + + subMenuCenter = glutCreateMenu(MenuCenter); + createMenuEntries(2); + + menuID = glutCreateMenu(MenuSurround); /* doesn't matter, no clickable entries in this menu */ + glutAddSubMenu("Center", subMenuCenter); + glutAddSubMenu("Surround", subMenuSurround); + glutAttachMenu(GLUT_RIGHT_BUTTON); + + glutMainLoop(); + return 0; +} + +void disp(void) +{ + glClearColor(color[cidx][0], color[cidx][1], color[cidx][2], 1); + glClear(GL_COLOR_BUFFER_BIT); + + glPointSize(10.f); + glColor3f(color[pcidx][0], color[pcidx][1], color[pcidx][2]); + glBegin(GL_POINTS); + glVertex2i(0,0); + glEnd(); + + glutSwapBuffers(); +} + +void timer_func(int which) +{ + /* advance the color index and trigger a redisplay */ + switch (which) + { + case 1: + cidx = (cidx + 1) % (sizeof color / sizeof *color); + break; + case 2: + pcidx = (pcidx + 1) % (sizeof color / sizeof *color); + break; + } + + glutPostRedisplay(); + + /* (re)set the timer callback and ask glut to call it in x ms */ + glutTimerFunc(which == 1 ? timerSurroundInt:timerCenterInt, timer_func, which); +} diff --git a/progs/demos/timer_callback/timer.c b/progs/demos/timer_callback/timer.c new file mode 100644 index 0000000..03acd40 --- /dev/null +++ b/progs/demos/timer_callback/timer.c @@ -0,0 +1,174 @@ +/* Timer (callback) demo + * + * Written by John Tsiombikas + * Modified by Vincent Simonetti + * + * A modification of the timer sample, but with this + * offering a use of the user-data callback. + */ +#include +#include + +struct display_index_s +{ + /* color index will be advanced every time the timer expires */ + int surround_color_index; + int center_color_index; +}; +typedef struct display_index_s display_index_t; + +struct timer_state_s +{ + int* color_index_ptr; + int* timer_time_ptr; +}; +typedef struct timer_state_s timer_state_t; + +struct menu_state_s +{ + int* timer_time_ptr; + int menu_id; +}; +typedef struct menu_state_s menu_state_t; + +void disp(void* uptr); +void timer_func(int which, void* uptr); + +const float color[][3] = { + {1, 0, 0}, + {0, 1, 0}, + {0, 0, 1}, + {1, 1, 0}, + {0, 1, 1}, + {1, 0, 1} +}; +const int timerInts[] = { + 250, + 500, + 1000 +}; + +void createMenuEntries(menu_state_t* menuState) +{ + int i; + for (i = 0; i < sizeof(timerInts) / sizeof(*timerInts); i++) + { + char temp[10] = {'\0'}; + /* flag current value */ + if ((*menuState->timer_time_ptr) == timerInts[i]) + temp[0] = '+'; + else + temp[0] = '-'; + + sprintf(temp + 1, " %4d ms", timerInts[i]); + + glutAddMenuEntry(temp, timerInts[i]); + } +} + +void updateMenuEntries(menu_state_t* menuState) +{ + int i; + for (i = 0; i < sizeof(timerInts) / sizeof(*timerInts); i++) + { + char temp[10] = { '\0' }; + /* flag current value */ + if ((*menuState->timer_time_ptr) == timerInts[i]) + temp[0] = '+'; + else + temp[0] = '-'; + + sprintf(temp + 1, " %4d ms", timerInts[i]); + + glutChangeToMenuEntry(i+1, temp, timerInts[i]); + } +} + +void MenuHandler(int timerInt, void* user_ptr) +{ + menu_state_t* menuState; + + if (!user_ptr) + { + /* In case main menu is selected somehow */ + return; + } + + menuState = (menu_state_t*)user_ptr; + + *menuState->timer_time_ptr = timerInt; + glutSetMenu(menuState->menu_id); + updateMenuEntries(menuState); +} + +int main(int argc, char **argv) +{ + int timerSurroundInt = 1000, timerCenterInt = 500; + display_index_t displayIndex = { 0, 2 }; + timer_state_t surroundTimerState = { &displayIndex.surround_color_index, &timerSurroundInt }; + timer_state_t centerTimerState = { &displayIndex.center_color_index, &timerCenterInt }; + menu_state_t surroundMenuState = { &timerSurroundInt, 0 }; + menu_state_t centerMenuState = { &timerCenterInt, 0 }; + + glutInit(&argc, argv); + glutInitWindowSize(128, 128); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); + glutCreateWindow("timer test"); + + glutDisplayFuncUcall(disp, &displayIndex); + + /* get timer started, its reset in the timer function itself */ + glutTimerFuncUcall(timerSurroundInt, timer_func, 1, &surroundTimerState); + glutTimerFuncUcall(timerCenterInt, timer_func, 2, ¢erTimerState); + + /* menus for setting timing */ + surroundMenuState.menu_id = glutCreateMenuUcall(MenuHandler, &surroundMenuState); + createMenuEntries(&surroundMenuState); + + centerMenuState.menu_id = glutCreateMenuUcall(MenuHandler, ¢erMenuState); + createMenuEntries(¢erMenuState); + + glutCreateMenuUcall(MenuHandler, NULL); /* doesn't matter, no clickable entries in this menu */ + glutAddSubMenu("Center", centerMenuState.menu_id); + glutAddSubMenu("Surround", surroundMenuState.menu_id); + glutAttachMenu(GLUT_RIGHT_BUTTON); + + glutMainLoop(); + return 0; +} + +void disp(void* user_ptr) +{ + const display_index_t* displayIndex; + int cidx, pcidx; + + displayIndex = (display_index_t*)user_ptr; + + cidx = displayIndex->surround_color_index; + glClearColor(color[cidx][0], color[cidx][1], color[cidx][2], 1); + glClear(GL_COLOR_BUFFER_BIT); + + pcidx = displayIndex->center_color_index; + glPointSize(10.f); + glColor3f(color[pcidx][0], color[pcidx][1], color[pcidx][2]); + glBegin(GL_POINTS); + glVertex2i(0,0); + glEnd(); + + glutSwapBuffers(); +} + +void timer_func(int which, void* user_ptr) +{ + const timer_state_t* timerState; + + timerState = (timer_state_t*)user_ptr; + + /* advance the color index and trigger a redisplay */ + *timerState->color_index_ptr = (*timerState->color_index_ptr + 1) % (sizeof color / sizeof *color); + + glutPostRedisplay(); + + /* (re)set the timer callback and ask glut to call it in x ms */ + glutTimerFuncUcall(*timerState->timer_time_ptr, timer_func, which, user_ptr); +} diff --git a/progs/test-shapes-gles1/AndroidManifest.xml b/progs/test-shapes-gles1/AndroidManifest.xml new file mode 100644 index 0000000..7839f74 --- /dev/null +++ b/progs/test-shapes-gles1/AndroidManifest.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/progs/test-shapes-gles1/CMakeLists.txt b/progs/test-shapes-gles1/CMakeLists.txt new file mode 100644 index 0000000..fc2c1c3 --- /dev/null +++ b/progs/test-shapes-gles1/CMakeLists.txt @@ -0,0 +1,42 @@ +cmake_minimum_required(VERSION 2.6) +project(test-shapes-gles1) + +IF(CMAKE_COMPILER_IS_GNUCC) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") + IF(!ANDROID) + # not setting -ansi as EGL/KHR headers doesn't support it + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ansi") + ENDIF() +ENDIF(CMAKE_COMPILER_IS_GNUCC) + +# FreeGLUT +include(FindPkgConfig) +pkg_check_modules(freeglut REQUIRED freeglut-gles>=3.0.0) +if(freeglut_FOUND) + include_directories(${freeglut_STATIC_INCLUDE_DIRS}) + link_directories(${freeglut_STATIC_LIBRARY_DIRS}) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${freeglut_STATIC_CFLAGS_OTHER}") + add_definitions(${freeglut_STATIC_CFLAGS_OTHER}) +endif() + +if(ANDROID) + add_library(test-shapes-gles1 SHARED test-shapes-gles1.c) + add_custom_target(apk ALL + DEPENDS test-shapes-gles1 + COMMAND ant clean || true + COMMAND rm -rf libs/ src/ res/ bin/ gen/ + COMMAND mkdir -p libs/armeabi/ src/ res/values/ + COMMAND cp -a ${PROJECT_SOURCE_DIR}/AndroidManifest.xml ${PROJECT_BINARY_DIR} + COMMAND cp -a $ libs/armeabi/ + COMMAND echo 'FG_GLES1 test' + > res/values/strings.xml + COMMAND android update project --name cmake-apk --path . --target "android-10" + COMMAND ant debug + COMMAND ant installd + COMMAND adb shell am start -a android.intenon.MAIN -n freeglut.test.gles1/android.app.NativeActivity + ) + # Note: at least one resource and an empty src/ dir is necessary for ant... +else() + add_executable(test-shapes-gles1 test-shapes-gles1.c) +endif() +target_link_libraries(test-shapes-gles1 ${freeglut_STATIC_LIBRARIES}) diff --git a/progs/test-shapes-gles1/android_toolchain.cmake b/progs/test-shapes-gles1/android_toolchain.cmake new file mode 120000 index 0000000..1a710d1 --- /dev/null +++ b/progs/test-shapes-gles1/android_toolchain.cmake @@ -0,0 +1 @@ +../../android_toolchain.cmake \ No newline at end of file diff --git a/progs/test-shapes-gles1/ndk/AndroidManifest.xml b/progs/test-shapes-gles1/ndk/AndroidManifest.xml new file mode 100644 index 0000000..b56c906 --- /dev/null +++ b/progs/test-shapes-gles1/ndk/AndroidManifest.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/progs/test-shapes-gles1/ndk/jni/Android.mk b/progs/test-shapes-gles1/ndk/jni/Android.mk new file mode 100644 index 0000000..361043c --- /dev/null +++ b/progs/test-shapes-gles1/ndk/jni/Android.mk @@ -0,0 +1,14 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := native-activity +LOCAL_SRC_FILES := +LOCAL_CPPFLAGS := -I/usr/src/glm +LOCAL_CXXFLAGS := -gstabs+ +LOCAL_LDLIBS := -llog -landroid -lGLESv2 -lEGL +LOCAL_STATIC_LIBRARIES := freeglut + +include $(BUILD_SHARED_LIBRARY) + +$(call import-module,freeglut) diff --git a/progs/test-shapes-gles1/ndk/jni/Application.mk b/progs/test-shapes-gles1/ndk/jni/Application.mk new file mode 100644 index 0000000..b31b6a5 --- /dev/null +++ b/progs/test-shapes-gles1/ndk/jni/Application.mk @@ -0,0 +1,2 @@ +APP_PLATFORM := android-9 +APP_STL := gnustl_static diff --git a/progs/test-shapes-gles1/test-shapes-gles1.c b/progs/test-shapes-gles1/test-shapes-gles1.c new file mode 100644 index 0000000..e0bdd01 --- /dev/null +++ b/progs/test-shapes-gles1/test-shapes-gles1.c @@ -0,0 +1,341 @@ +/*! \file shapes.c + \ingroup demos + + This program is a test harness for the various shapes + in OpenGLUT. It may also be useful to see which + parameters control what behavior in the OpenGLUT + objects. + + Spinning wireframe and solid-shaded shapes are + displayed. Some parameters can be adjusted. + + Keys: + - Esc   Quit + - q Q   Quit + - i I   Show info + - p P   Toggle perspective or orthographic projection + - = +   Increase \a slices + - - _   Decreate \a slices + - , <   Decreate \a stacks + - . >   Increase \a stacks + - 9 (   Decreate \a depth (Sierpinski Sponge) + - 0 )   Increase \a depth (Sierpinski Sponge) + - up    Increase "outer radius" + - down  Decrease "outer radius" + - left  Decrease "inner radius" + - right Increase "inner radius" + - PgUp  Next shape-drawing function + - PgDn  Prev shape-drawing function + + \author Written by Nigel Stewart November 2003 + + \author Portions Copyright (C) 2004, the OpenGLUT project contributors.
+ OpenGLUT branched from freeglut in February, 2004. + + \image html openglut_shapes.png OpenGLUT Geometric Shapes Demonstration + \include demos/shapes/shapes.c +*/ + +#include +#include + +#include +#include +#include + +#ifdef _MSC_VER +/* DUMP MEMORY LEAKS */ +#include +#endif + +/* + * This macro is only intended to be used on arrays, of course. + */ +#define NUMBEROF(x) ((sizeof(x))/(sizeof(x[0]))) + +#define glRotated glRotatef +#define glTranslated glTranslatef + +/* + * These global variables control which object is drawn, + * and how it is drawn. No object uses all of these + * variables. + */ +static int function_index; +static int slices = 16; +static int stacks = 16; +static double irad = .25; +static double orad = 1.0; /* doubles as size for objects other than Torus */ +static int depth = 4; +static double offset[ 3 ] = { 0, 0, 0 }; +static GLboolean show_info = GL_TRUE; +static float ar; +static GLboolean persProject = GL_TRUE; +static GLboolean animateXRot = GL_FALSE; + +/* + * These one-liners draw particular objects, fetching appropriate + * information from the above globals. They are just thin wrappers + * for the FreeGLUT objects. + */ +static void drawSolidTetrahedron(void) { glutSolidTetrahedron (); } +static void drawWireTetrahedron(void) { glutWireTetrahedron (); } +static void drawSolidCube(void) { glutSolidCube(orad); } /* orad doubles as size input */ +static void drawWireCube(void) { glutWireCube(orad); } /* orad doubles as size input */ +static void drawSolidOctahedron(void) { glutSolidOctahedron (); } +static void drawWireOctahedron(void) { glutWireOctahedron (); } +static void drawSolidDodecahedron(void) { glutSolidDodecahedron (); } +static void drawWireDodecahedron(void) { glutWireDodecahedron (); } +static void drawSolidRhombicDodecahedron(void) { glutSolidRhombicDodecahedron (); } +static void drawWireRhombicDodecahedron(void) { glutWireRhombicDodecahedron (); } +static void drawSolidIcosahedron(void) { glutSolidIcosahedron (); } +static void drawWireIcosahedron(void) { glutWireIcosahedron (); } +static void drawSolidSierpinskiSponge(void) { glutSolidSierpinskiSponge (depth, offset, orad);} /* orad doubles as size input */ +static void drawWireSierpinskiSponge(void) { glutWireSierpinskiSponge (depth, offset, orad); } /* orad doubles as size input */ +static void drawSolidTorus(void) { glutSolidTorus(irad,orad,slices,stacks); } +static void drawWireTorus(void) { glutWireTorus (irad,orad,slices,stacks); } +static void drawSolidSphere(void) { glutSolidSphere(orad,slices,stacks); } /* orad doubles as size input */ +static void drawWireSphere(void) { glutWireSphere(orad,slices,stacks); } /* orad doubles as size input */ +static void drawSolidCone(void) { glutSolidCone(orad,orad,slices,stacks); } /* orad doubles as size input */ +static void drawWireCone(void) { glutWireCone(orad,orad,slices,stacks); } /* orad doubles as size input */ +static void drawSolidCylinder(void) { glutSolidCylinder(orad,orad,slices,stacks); } /* orad doubles as size input */ +static void drawWireCylinder(void) { glutWireCylinder(orad,orad,slices,stacks); } /* orad doubles as size input */ +static void drawSolidTeapot(void) +{ glFrontFace(GL_CW); glutSolidTeapot(orad); glFrontFace(GL_CCW); /* orad doubles as size input */} +static void drawWireTeapot(void) +{ glFrontFace(GL_CW); glutWireTeapot(orad); glFrontFace(GL_CCW); /* orad doubles as size input */} + +/* + * This structure defines an entry in our function-table. + */ +typedef struct +{ + const char * const name; + void (*solid) (void); + void (*wire) (void); +} entry; + +#define ENTRY(e) {#e, drawSolid##e, drawWire##e} +static const entry table [] = +{ + ENTRY (Tetrahedron), + ENTRY (Cube), + ENTRY (Octahedron), + ENTRY (Dodecahedron), + ENTRY (RhombicDodecahedron), + ENTRY (Icosahedron), + ENTRY (SierpinskiSponge), + ENTRY (Teapot), + ENTRY (Torus), + ENTRY (Sphere), + ENTRY (Cone), + ENTRY (Cylinder), + /* ENTRY (Cuboctahedron) */ +}; +#undef ENTRY + +/*! + Does printf()-like work using freeglut + glutBitmapString(). Uses a fixed font. Prints + at the indicated row/column position. + + Limitation: Cannot address pixels. + Limitation: Renders in screen coords, not model coords. +*/ +static void shapesPrintf (int row, int col, const char *fmt, ...) +{ +} + +/* GLUT callback Handlers */ + +static void +resize(int width, int height) +{ + ar = (float) width / (float) height; + + glViewport(0, 0, width, height); +} + +static void display(void) +{ + const double t = glutGet(GLUT_ELAPSED_TIME) / 1000.0; + const double a = t*90.0; + const double b = (animateXRot?t:1)*60.0; + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustumf(-ar, ar, -1.0, 1.0, 2.0, 100.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glEnable(GL_LIGHTING); + + glColor4f(1,0,0,1); + + glPushMatrix(); + glTranslated(0,1.2,-6); + glRotated(b,1,0,0); + glRotated(a,0,0,1); + table [function_index].solid (); + glPopMatrix(); + + glPushMatrix(); + glTranslated(0,-1.2,-6); + glRotated(b,1,0,0); + glRotated(a,0,0,1); + table [function_index].wire (); + glPopMatrix(); + + glDisable(GL_LIGHTING); + glColor4f(0.1,0.1,0.4,1.0); + + glutSwapBuffers(); +} + + +static void +key(unsigned char key, int x, int y) +{ + switch (key) + { + case 27 : + case 'Q': + case 'q': glutLeaveMainLoop () ; break; + + case 'I': + case 'i': show_info = ( show_info == GL_TRUE ) ? GL_FALSE : GL_TRUE; break; + + case '=': + case '+': slices++; printf("%d,%d\n", slices, stacks); break; + + case '-': + case '_': if( slices > -1 ) slices--; break; + + case ',': + case '<': if( stacks > -1 ) stacks--; break; + + case '.': + case '>': stacks++; break; + + case '9': + case '(': if( depth > -1 ) depth--; break; + + case '0': + case ')': ++depth; break; + + case 'P': + case 'p': persProject=!persProject; break; + + case 'R': + case 'r': animateXRot=!animateXRot; break; + + default: + break; + } + + glutPostRedisplay(); +} + +static void special (int key, int x, int y) +{ + switch (key) + { + case GLUT_KEY_PAGE_UP: ++function_index; break; + case GLUT_KEY_PAGE_DOWN: --function_index; break; + case GLUT_KEY_UP: orad *= 2; break; + case GLUT_KEY_DOWN: orad /= 2; break; + + case GLUT_KEY_RIGHT: irad *= 2; break; + case GLUT_KEY_LEFT: irad /= 2; break; + + default: + break; + } + + if (0 > function_index) + function_index = NUMBEROF (table) - 1; + + if (NUMBEROF (table) <= ( unsigned )function_index) + function_index = 0; +} + + +static void +idle(void) +{ + glutPostRedisplay(); +} + +static void +onMouseClick(int button, int state, int x, int y) { + if (state == GLUT_DOWN) + special(GLUT_KEY_PAGE_UP, 0, 0); +} + +const GLfloat light_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f }; +const GLfloat light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f }; +const GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; +const GLfloat light_position[] = { 2.0f, 5.0f, 5.0f, 0.0f }; + +const GLfloat mat_ambient[] = { 0.7f, 0.7f, 0.7f, 1.0f }; +const GLfloat mat_diffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f }; +const GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; +const GLfloat high_shininess[] = { 100.0f }; + +/* Program entry point */ + +void init_context() { + printf("init_context\n"); fflush(stdout); + glClearColor(1,1,1,1); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + + glEnable(GL_LIGHT0); + glEnable(GL_NORMALIZE); + glEnable(GL_COLOR_MATERIAL); + + glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); + glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); + glLightfv(GL_LIGHT0, GL_POSITION, light_position); + + glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient); + glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); + glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); + glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess); +} + +int +main(int argc, char *argv[]) +{ + glutInitWindowSize(640,480); + glutInitWindowPosition(40,40); + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE); + + glutCreateWindow("FreeGLUT Shapes"); + + glutReshapeFunc(resize); + glutDisplayFunc(display); + glutKeyboardFunc(key); + glutSpecialFunc(special); + glutIdleFunc(idle); + glutMouseFunc(onMouseClick); + glutInitContextFunc(init_context); + + glutSetOption ( GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION ) ; + + glutMainLoop(); + +#ifdef _MSC_VER + /* DUMP MEMORY LEAK INFORMATION */ + _CrtDumpMemoryLeaks () ; +#endif + + return EXIT_SUCCESS; +} diff --git a/src/android/fg_cursor_android.c b/src/android/fg_cursor_android.c new file mode 100644 index 0000000..fe599d1 --- /dev/null +++ b/src/android/fg_cursor_android.c @@ -0,0 +1,42 @@ +/* + * fg_cursor_android.c + * + * The Windows-specific mouse cursor related stuff. + * + * Copyright (C) 2012 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "../fg_internal.h" + +void fgPlatformSetCursor ( SFG_Window *window, int cursorID ) +{ + /* No-op: no visible cursor on touchscreens */ +} + +void fgPlatformWarpPointer ( int x, int y ) +{ + /* Even if there's no pointer on touchscreen, keep track of the + last position, e.g. for menus */ + SFG_Window* window = fgStructure.CurrentWindow; + window->State.MouseX = x; + window->State.MouseY = y; + /* TODO: this should simulate a fake motion event */ +} diff --git a/src/android/fg_ext_android.c b/src/android/fg_ext_android.c new file mode 100644 index 0000000..baac806 --- /dev/null +++ b/src/android/fg_ext_android.c @@ -0,0 +1,48 @@ +/* + * fg_ext_android.c + * + * Functions related to OpenGL extensions. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Copied for Platform code by Evan Felix + * Copyright (C) 2012 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "../fg_internal.h" + +GLUTproc fgPlatformGetGLUTProcAddress( const char* procName ) +{ + /* optimization: quick initial check */ + if( strncmp( procName, "glut", 4 ) != 0 ) + return NULL; + +#define CHECK_NAME(x) if( strcmp( procName, #x ) == 0) return (GLUTproc)x; + CHECK_NAME(glutJoystickFunc); + CHECK_NAME(glutForceJoystickFunc); + CHECK_NAME(glutGameModeString); + CHECK_NAME(glutEnterGameMode); + CHECK_NAME(glutLeaveGameMode); + CHECK_NAME(glutGameModeGet); +#undef CHECK_NAME + + return NULL; +} diff --git a/src/android/fg_gamemode_android.c b/src/android/fg_gamemode_android.c new file mode 100644 index 0000000..14683ee --- /dev/null +++ b/src/android/fg_gamemode_android.c @@ -0,0 +1,57 @@ +/* + * fg_gamemode_x11.c + * + * The game mode handling code. + * + * Copyright (C) 2012 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" + +/* + * Changes the current display mode to match user's settings + */ +GLboolean fgPlatformChangeDisplayMode( GLboolean haveToTest ) +{ + fprintf(stderr, "fgPlatformChangeDisplayMode: STUB\n"); + return GL_FALSE; +} + +void fgPlatformEnterGameMode( void ) +{ + fprintf(stderr, "fgPlatformEnterGameMode: STUB\n"); +} + +void fgPlatformRememberState( void ) +{ + fprintf(stderr, "fgPlatformRememberState: STUB\n"); +} + +void fgPlatformRestoreState( void ) +{ + fprintf(stderr, "fgPlatformRestoreState: STUB\n"); +} + +void fgPlatformLeaveGameMode( void ) +{ + fprintf(stderr, "fgPlatformLeaveGameMode: STUB\n"); +} + diff --git a/src/android/fg_init_android.c b/src/android/fg_init_android.c new file mode 100644 index 0000000..d19e91d --- /dev/null +++ b/src/android/fg_init_android.c @@ -0,0 +1,54 @@ +/* + * fg_init_android.c + * + * Various freeglut initialization functions. + * + * Copyright (C) 2012 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" +#include "fg_init.h" +#include "egl/fg_init_egl.h" + +void fgPlatformInitialize() +{ + fghPlatformInitializeEGL(); + + /* Get start time */ + fgState.Time = fgSystemTime(); + + fgState.Initialised = GL_TRUE; +} + +void fgPlatformCloseDisplay() +{ + fghPlatformCloseDisplayEGL(); +} + +/** + * Close joystick and serial input devices + */ +void fgPlatformDeinitialiseInputDevices ( void ) +{ + fghCloseInputDevices (); + fgState.JoysticksInitialised = GL_FALSE; + fgState.InputDevsInitialised = GL_FALSE; +} diff --git a/src/android/fg_input_devices_android.c b/src/android/fg_input_devices_android.c new file mode 100644 index 0000000..008bfb4 --- /dev/null +++ b/src/android/fg_input_devices_android.c @@ -0,0 +1,52 @@ +/* + * fg_input_devices_android.c + * + * Handles miscellaneous input devices via direct serial-port access. + * + * Written by Joe Krahn 2005 + * Copyright (c) 2005 Stephen J. Baker. All Rights Reserved. + * Copied for Platform code by Evan Felix + * Copyright 2012 (C) Sylvain Beucler + * Creation date: Thur Feb 2 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA OR STEPHEN J. BAKER BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" +typedef struct _serialport SERIALPORT; +#include + +/* + * This is only used if the user calls: + * glutDeviceGet(GLUT_HAS_DIAL_AND_BUTTON_BOX) + * and has old hardware called 'dials&buttons box'. + * http://www.reputable.com/sgipix/sgi-dialnbutton1.jpg + * + * Not implemented on Android :) + * http://sourceforge.net/mailarchive/message.php?msg_id=29209505 + */ +void fgPlatformRegisterDialDevice ( const char *dial_device ) { + fgWarning("GLUT_HAS_DIAL_AND_BUTTON_BOX: not implemented"); +} +SERIALPORT *fg_serial_open ( const char *device ) { return NULL; } +void fg_serial_close(SERIALPORT *port) {} +int fg_serial_getchar(SERIALPORT *port) { return EOF; } +int fg_serial_putchar(SERIALPORT *port, unsigned char ch) { return 0; } +void fg_serial_flush ( SERIALPORT *port ) {} diff --git a/src/android/fg_internal_android.h b/src/android/fg_internal_android.h new file mode 100644 index 0000000..5504b44 --- /dev/null +++ b/src/android/fg_internal_android.h @@ -0,0 +1,120 @@ +/* + * fg_internal_android.h + * + * The freeglut library private include file. + * + * Copyright (C) 2012 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef FREEGLUT_INTERNAL_ANDROID_H +#define FREEGLUT_INTERNAL_ANDROID_H + + +/* -- PLATFORM-SPECIFIC INCLUDES ------------------------------------------- */ +/* Android OpenGL ES is accessed through EGL */ +#include "egl/fg_internal_egl.h" + +/* -- GLOBAL TYPE DEFINITIONS ---------------------------------------------- */ +/* The structure used by display initialization in fg_init.c */ +typedef struct tagSFG_PlatformDisplay SFG_PlatformDisplay; +struct android_app; +struct tagSFG_PlatformDisplay +{ + struct tagSFG_PlatformDisplayEGL egl; + EGLNativeWindowType single_native_window; + struct android_app* app; +}; + +typedef struct tagSFG_PlatformContext SFG_PlatformContext; +/* SFG_PlatformContext is used for SFG_Window.Window */ +struct tagSFG_PlatformContext +{ + struct tagSFG_PlatformContextEGL egl; +}; + + +/** + * Virtual PAD (spots on touchscreen that simulate keys) + */ +struct vpad_state { + bool on; + bool left; + bool right; + bool up; + bool down; +}; +struct touchscreen { + struct vpad_state vpad; + bool in_mmotion; +}; + + +/* -- JOYSTICK-SPECIFIC STRUCTURES AND TYPES ------------------------------- */ +/* + * Initial defines from "js.h" starting around line 33 with the existing "fg_joystick.c" + * interspersed + */ + + /* + * We'll put these values in and that should + * allow the code to at least compile when there is + * no support. The JS open routine should error out + * and shut off all the code downstream anyway and if + * the application doesn't use a joystick we'll be fine. + */ + + struct JS_DATA_TYPE + { + int buttons; + int x; + int y; + }; + +# define JS_RETURN (sizeof(struct JS_DATA_TYPE)) + +/* XXX It might be better to poll the operating system for the numbers of buttons and + * XXX axes and then dynamically allocate the arrays. + */ +# define _JS_MAX_AXES 16 +typedef struct tagSFG_PlatformJoystick SFG_PlatformJoystick; +struct tagSFG_PlatformJoystick +{ + struct JS_DATA_TYPE js; + + char fname [ 128 ]; + int fd; +}; + +/* Window's state description. This structure should be kept portable. */ +typedef struct tagSFG_PlatformWindowState SFG_PlatformWindowState; +struct tagSFG_PlatformWindowState +{ + char unused; +}; + +/* Menu font and color definitions */ +#define FREEGLUT_MENU_FONT NULL + +#define FREEGLUT_MENU_PEN_FORE_COLORS {0.0f, 0.0f, 0.0f, 1.0f} +#define FREEGLUT_MENU_PEN_BACK_COLORS {0.70f, 0.70f, 0.70f, 1.0f} +#define FREEGLUT_MENU_PEN_HFORE_COLORS {0.0f, 0.0f, 0.0f, 1.0f} +#define FREEGLUT_MENU_PEN_HBACK_COLORS {1.0f, 1.0f, 1.0f, 1.0f} + +#endif /* FREEGLUT_INTERNAL_ANDROID_H */ diff --git a/src/android/fg_joystick_android.c b/src/android/fg_joystick_android.c new file mode 100644 index 0000000..148c500 --- /dev/null +++ b/src/android/fg_joystick_android.c @@ -0,0 +1,55 @@ +/* + * fg_joystick_android.c + * + * Joystick handling code + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Steve Baker, + * Copied for Platform code by Evan Felix + * Copyright (C) 2012 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" + +/** + * TODO: Android has no joysticks at the moment (only touchscreens/touchpads), + * but we could expose the accelerometer as a 3-axis joystick. + */ + +void fgPlatformJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes ) +{ + fgWarning("fgPlatformJoystickRawRead: STUB\n"); +} + +void fgPlatformJoystickOpen( SFG_Joystick* joy ) +{ + fgWarning("fgPlatformJoystickOpen: STUB\n"); +} + +void fgPlatformJoystickInit( SFG_Joystick *fgJoystick[], int ident ) +{ + fgWarning("fgJoystick: STUB\n"); +} + +void fgPlatformJoystickClose ( int ident ) +{ + fgWarning("fgPlatformJoystickClose: STUB\n"); +} diff --git a/src/android/fg_main_android.c b/src/android/fg_main_android.c new file mode 100644 index 0000000..1df336c --- /dev/null +++ b/src/android/fg_main_android.c @@ -0,0 +1,558 @@ +/* + * fg_main_android.c + * + * The Android-specific windows message processing methods. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Copied for Platform code by Evan Felix + * Copyright (C) 2012 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" +#include "egl/fg_window_egl.h" + +#include +#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "FreeGLUT", __VA_ARGS__)) +#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "FreeGLUT", __VA_ARGS__)) +#include +#include + +extern void fghOnReshapeNotify(SFG_Window *window, int width, int height, GLboolean forceNotify); +extern void fghOnPositionNotify(SFG_Window *window, int x, int y, GLboolean forceNotify); +extern void fgPlatformFullScreenToggle( SFG_Window *win ); +extern void fgPlatformPositionWindow( SFG_Window *window, int x, int y ); +extern void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height ); +extern void fgPlatformPushWindow( SFG_Window *window ); +extern void fgPlatformPopWindow( SFG_Window *window ); +extern void fgPlatformHideWindow( SFG_Window *window ); +extern void fgPlatformIconifyWindow( SFG_Window *window ); +extern void fgPlatformShowWindow( SFG_Window *window ); + +static struct touchscreen touchscreen; +static unsigned char key_a2fg[256]; + +/* Cf. http://developer.android.com/reference/android/view/KeyEvent.html */ +/* These codes are missing in */ +/* Don't convert to enum, since it may conflict with future version of + that */ +#define AKEYCODE_FORWARD_DEL 112 +#define AKEYCODE_CTRL_LEFT 113 +#define AKEYCODE_CTRL_RIGHT 114 +#define AKEYCODE_MOVE_HOME 122 +#define AKEYCODE_MOVE_END 123 +#define AKEYCODE_INSERT 124 +#define AKEYCODE_ESCAPE 127 +#define AKEYCODE_F1 131 +#define AKEYCODE_F2 132 +#define AKEYCODE_F3 133 +#define AKEYCODE_F4 134 +#define AKEYCODE_F5 135 +#define AKEYCODE_F6 136 +#define AKEYCODE_F7 137 +#define AKEYCODE_F8 138 +#define AKEYCODE_F9 139 +#define AKEYCODE_F10 140 +#define AKEYCODE_F11 141 +#define AKEYCODE_F12 142 + +#define EVENT_HANDLED 1 +#define EVENT_NOT_HANDLED 0 + +/** + * Initialize Android keycode to GLUT keycode mapping + */ +static void key_init() { + memset(key_a2fg, 0, sizeof(key_a2fg)); + + key_a2fg[AKEYCODE_F1] = GLUT_KEY_F1; + key_a2fg[AKEYCODE_F2] = GLUT_KEY_F2; + key_a2fg[AKEYCODE_F3] = GLUT_KEY_F3; + key_a2fg[AKEYCODE_F4] = GLUT_KEY_F4; + key_a2fg[AKEYCODE_F5] = GLUT_KEY_F5; + key_a2fg[AKEYCODE_F6] = GLUT_KEY_F6; + key_a2fg[AKEYCODE_F7] = GLUT_KEY_F7; + key_a2fg[AKEYCODE_F8] = GLUT_KEY_F8; + key_a2fg[AKEYCODE_F9] = GLUT_KEY_F9; + key_a2fg[AKEYCODE_F10] = GLUT_KEY_F10; + key_a2fg[AKEYCODE_F11] = GLUT_KEY_F11; + key_a2fg[AKEYCODE_F12] = GLUT_KEY_F12; + + key_a2fg[AKEYCODE_PAGE_UP] = GLUT_KEY_PAGE_UP; + key_a2fg[AKEYCODE_PAGE_DOWN] = GLUT_KEY_PAGE_DOWN; + key_a2fg[AKEYCODE_MOVE_HOME] = GLUT_KEY_HOME; + key_a2fg[AKEYCODE_MOVE_END] = GLUT_KEY_END; + key_a2fg[AKEYCODE_INSERT] = GLUT_KEY_INSERT; + + key_a2fg[AKEYCODE_DPAD_UP] = GLUT_KEY_UP; + key_a2fg[AKEYCODE_DPAD_DOWN] = GLUT_KEY_DOWN; + key_a2fg[AKEYCODE_DPAD_LEFT] = GLUT_KEY_LEFT; + key_a2fg[AKEYCODE_DPAD_RIGHT] = GLUT_KEY_RIGHT; + + key_a2fg[AKEYCODE_ALT_LEFT] = GLUT_KEY_ALT_L; + key_a2fg[AKEYCODE_ALT_RIGHT] = GLUT_KEY_ALT_R; + key_a2fg[AKEYCODE_SHIFT_LEFT] = GLUT_KEY_SHIFT_L; + key_a2fg[AKEYCODE_SHIFT_RIGHT] = GLUT_KEY_SHIFT_R; + key_a2fg[AKEYCODE_CTRL_LEFT] = GLUT_KEY_CTRL_L; + key_a2fg[AKEYCODE_CTRL_RIGHT] = GLUT_KEY_CTRL_R; +} + +/** + * Convert an Android key event to ASCII. + */ +static unsigned char key_ascii(struct android_app* app, AInputEvent* event) { + int32_t code = AKeyEvent_getKeyCode(event); + + /* Handle a few special cases: */ + switch (code) { + case AKEYCODE_DEL: + return 8; + case AKEYCODE_FORWARD_DEL: + return 127; + case AKEYCODE_ESCAPE: + return 27; + } + + /* Get usable JNI context */ + JNIEnv* env = app->activity->env; + JavaVM* vm = app->activity->vm; + (*vm)->AttachCurrentThread(vm, &env, NULL); + + jclass KeyEventClass = (*env)->FindClass(env, "android/view/KeyEvent"); + jmethodID KeyEventConstructor = (*env)->GetMethodID(env, KeyEventClass, "", "(II)V"); + jobject keyEvent = (*env)->NewObject(env, KeyEventClass, KeyEventConstructor, + AKeyEvent_getAction(event), AKeyEvent_getKeyCode(event)); + jmethodID KeyEvent_getUnicodeChar = (*env)->GetMethodID(env, KeyEventClass, "getUnicodeChar", "(I)I"); + int ascii = (*env)->CallIntMethod(env, keyEvent, KeyEvent_getUnicodeChar, AKeyEvent_getMetaState(event)); + + /* LOGI("getUnicodeChar(%d) = %d ('%c')", AKeyEvent_getKeyCode(event), ascii, ascii); */ + (*vm)->DetachCurrentThread(vm); + + return ascii; +} + +unsigned long fgPlatformSystemTime ( void ) +{ + struct timeval now; + gettimeofday( &now, NULL ); + return now.tv_usec/1000 + now.tv_sec*1000; +} + +/* + * Does the magic required to relinquish the CPU until something interesting + * happens. + */ +void fgPlatformSleepForEvents( fg_time_t msec ) +{ + /* Android's NativeActivity relies on a Looper/ALooper object to + notify about events. The Looper object is plugged on two + internal pipe(2)s to detect system and input events. Sadly you + can only ask the Looper for an event, not just ask whether + there is a pending event (and process it later). Consequently, + short of redesigning NativeActivity, we cannot + SleepForEvents. */ +} + +/** + * Process the next input event. + */ +int32_t handle_input(struct android_app* app, AInputEvent* event) { + SFG_Window* window = fgWindowByHandle(app->window); + if (window == NULL) + return EVENT_NOT_HANDLED; + + /* FIXME: in Android, when a key is repeated, down + and up events happen most often at the exact same time. This + makes it impossible to animate based on key press time. */ + /* e.g. down/up/wait/down/up rather than down/wait/down/wait/up */ + /* This looks like a bug in the Android virtual keyboard system :/ + Real buttons such as the Back button appear to work correctly + (series of down events with proper getRepeatCount value). */ + + if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) { + /* LOGI("action: %d", AKeyEvent_getAction(event)); */ + /* LOGI("keycode: %d", code); */ + int32_t code = AKeyEvent_getKeyCode(event); + + if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN) { + int32_t keypress = 0; + unsigned char ascii = 0; + if ((keypress = key_a2fg[code]) && FETCH_WCB(*window, Special)) { + INVOKE_WCB(*window, Special, (keypress, window->State.MouseX, window->State.MouseY)); + return EVENT_HANDLED; + } else if ((ascii = key_ascii(app, event)) && FETCH_WCB(*window, Keyboard)) { + INVOKE_WCB(*window, Keyboard, (ascii, window->State.MouseX, window->State.MouseY)); + return EVENT_HANDLED; + } + } + else if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_UP) { + int32_t keypress = 0; + unsigned char ascii = 0; + if ((keypress = key_a2fg[code]) && FETCH_WCB(*window, Special)) { + INVOKE_WCB(*window, SpecialUp, (keypress, window->State.MouseX, window->State.MouseY)); + return EVENT_HANDLED; + } else if ((ascii = key_ascii(app, event)) && FETCH_WCB(*window, Keyboard)) { + INVOKE_WCB(*window, KeyboardUp, (ascii, window->State.MouseX, window->State.MouseY)); + return EVENT_HANDLED; + } + } + } + + int32_t source = AInputEvent_getSource(event); + if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION + && source == AINPUT_SOURCE_TOUCHSCREEN) { + int32_t action = AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_MASK; + /* Pointer ID for clicks */ + int32_t pidx = AMotionEvent_getAction(event) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; + /* TODO: Handle multi-touch; also handle multiple sources/devices */ + /* cf. http://sourceforge.net/mailarchive/forum.php?thread_name=20120518071314.GA28061%40perso.beuc.net&forum_name=freeglut-developer */ + if (0) { + LOGI("motion action=%d index=%d source=%d", action, pidx, source); + int count = AMotionEvent_getPointerCount(event); + int i; + for (i = 0; i < count; i++) { + LOGI("multi(%d): %.01f,%.01f", + AMotionEvent_getPointerId(event, i), + AMotionEvent_getX(event, i), AMotionEvent_getY(event, i)); + } + } + float x = AMotionEvent_getX(event, 0); + float y = AMotionEvent_getY(event, 0); + + /* Virtual arrows PAD */ + /* Don't interfere with existing mouse move event */ + if (!touchscreen.in_mmotion) { + struct vpad_state prev_vpad = touchscreen.vpad; + touchscreen.vpad.left = touchscreen.vpad.right + = touchscreen.vpad.up = touchscreen.vpad.down = false; + + /* int32_t width = ANativeWindow_getWidth(window->Window.Handle); */ + int32_t height = ANativeWindow_getHeight(window->Window.Handle); + if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_MOVE) { + if ((x > 0 && x < 100) && (y > (height - 100) && y < height)) + touchscreen.vpad.left = true; + if ((x > 200 && x < 300) && (y > (height - 100) && y < height)) + touchscreen.vpad.right = true; + if ((x > 100 && x < 200) && (y > (height - 100) && y < height)) + touchscreen.vpad.down = true; + if ((x > 100 && x < 200) && (y > (height - 200) && y < (height - 100))) + touchscreen.vpad.up = true; + } + if (action == AMOTION_EVENT_ACTION_DOWN && + (touchscreen.vpad.left || touchscreen.vpad.right || touchscreen.vpad.down || touchscreen.vpad.up)) + touchscreen.vpad.on = true; + if (action == AMOTION_EVENT_ACTION_UP) + touchscreen.vpad.on = false; + if (prev_vpad.left != touchscreen.vpad.left + || prev_vpad.right != touchscreen.vpad.right + || prev_vpad.up != touchscreen.vpad.up + || prev_vpad.down != touchscreen.vpad.down + || prev_vpad.on != touchscreen.vpad.on) { + if (FETCH_WCB(*window, Special)) { + if (prev_vpad.left == false && touchscreen.vpad.left == true) + INVOKE_WCB(*window, Special, (GLUT_KEY_LEFT, x, y)); + else if (prev_vpad.right == false && touchscreen.vpad.right == true) + INVOKE_WCB(*window, Special, (GLUT_KEY_RIGHT, x, y)); + else if (prev_vpad.up == false && touchscreen.vpad.up == true) + INVOKE_WCB(*window, Special, (GLUT_KEY_UP, x, y)); + else if (prev_vpad.down == false && touchscreen.vpad.down == true) + INVOKE_WCB(*window, Special, (GLUT_KEY_DOWN, x, y)); + } + if (FETCH_WCB(*window, SpecialUp)) { + if (prev_vpad.left == true && touchscreen.vpad.left == false) + INVOKE_WCB(*window, SpecialUp, (GLUT_KEY_LEFT, x, y)); + if (prev_vpad.right == true && touchscreen.vpad.right == false) + INVOKE_WCB(*window, SpecialUp, (GLUT_KEY_RIGHT, x, y)); + if (prev_vpad.up == true && touchscreen.vpad.up == false) + INVOKE_WCB(*window, SpecialUp, (GLUT_KEY_UP, x, y)); + if (prev_vpad.down == true && touchscreen.vpad.down == false) + INVOKE_WCB(*window, SpecialUp, (GLUT_KEY_DOWN, x, y)); + } + return EVENT_HANDLED; + } + } + + /* Normal mouse events */ + if (!touchscreen.vpad.on) { + window->State.MouseX = x; + window->State.MouseY = y; + if (action == AMOTION_EVENT_ACTION_DOWN && FETCH_WCB(*window, Mouse)) { + touchscreen.in_mmotion = true; + INVOKE_WCB(*window, Mouse, (GLUT_LEFT_BUTTON, GLUT_DOWN, x, y)); + } else if (action == AMOTION_EVENT_ACTION_UP && FETCH_WCB(*window, Mouse)) { + touchscreen.in_mmotion = false; + INVOKE_WCB(*window, Mouse, (GLUT_LEFT_BUTTON, GLUT_UP, x, y)); + } else if (action == AMOTION_EVENT_ACTION_MOVE && FETCH_WCB(*window, Motion)) { + INVOKE_WCB(*window, Motion, (x, y)); + } + } + + return EVENT_HANDLED; + } + + /* Let Android handle other events (e.g. Back and Menu buttons) */ + return EVENT_NOT_HANDLED; +} + +/** + * Process the next main command. + */ +void handle_cmd(struct android_app* app, int32_t cmd) { + SFG_Window* window = fgWindowByHandle(app->window); /* may be NULL */ + switch (cmd) { + /* App life cycle, in that order: */ + case APP_CMD_START: + LOGI("handle_cmd: APP_CMD_START"); + break; + case APP_CMD_RESUME: + LOGI("handle_cmd: APP_CMD_RESUME"); + /* Cf. fgPlatformProcessSingleEvent */ + break; + case APP_CMD_INIT_WINDOW: /* surfaceCreated */ + /* The window is being shown, get it ready. */ + LOGI("handle_cmd: APP_CMD_INIT_WINDOW %p", app->window); + fgDisplay.pDisplay.single_native_window = app->window; + /* start|resume: glPlatformOpenWindow was waiting for Handle to be + defined and will now continue processing */ + break; + case APP_CMD_GAINED_FOCUS: + LOGI("handle_cmd: APP_CMD_GAINED_FOCUS"); + break; + case APP_CMD_WINDOW_RESIZED: + LOGI("handle_cmd: APP_CMD_WINDOW_RESIZED"); + if (window->Window.pContext.egl.Surface != EGL_NO_SURFACE) + /* Make ProcessSingleEvent detect the new size, only available + after the next SwapBuffer */ + glutPostRedisplay(); + break; + + case APP_CMD_SAVE_STATE: /* onSaveInstanceState */ + /* The system has asked us to save our current state, when it + pauses the application without destroying it right after. */ + app->savedState = strdup("Detect me as non-NULL on next android_main"); + app->savedStateSize = strlen(app->savedState) + 1; + LOGI("handle_cmd: APP_CMD_SAVE_STATE"); + break; + case APP_CMD_PAUSE: + LOGI("handle_cmd: APP_CMD_PAUSE"); + /* Cf. fgPlatformProcessSingleEvent */ + break; + case APP_CMD_LOST_FOCUS: + LOGI("handle_cmd: APP_CMD_LOST_FOCUS"); + break; + case APP_CMD_TERM_WINDOW: /* surfaceDestroyed */ + /* The application is being hidden, but may be restored */ + LOGI("handle_cmd: APP_CMD_TERM_WINDOW"); + fghPlatformCloseWindowEGL(window); + fgDisplay.pDisplay.single_native_window = NULL; + break; + case APP_CMD_STOP: + LOGI("handle_cmd: APP_CMD_STOP"); + break; + case APP_CMD_DESTROY: /* Activity.onDestroy */ + LOGI("handle_cmd: APP_CMD_DESTROY"); + /* User closed the application for good, let's kill the window */ + { + /* Can't use fgWindowByHandle as app->window is NULL */ + SFG_Window* window = fgStructure.CurrentWindow; + if (window != NULL) { + fgDestroyWindow(window); + } else { + LOGI("APP_CMD_DESTROY: No current window"); + } + } + /* glue has already set android_app->destroyRequested=1 */ + break; + + case APP_CMD_CONFIG_CHANGED: + /* Handle rotation / orientation change */ + LOGI("handle_cmd: APP_CMD_CONFIG_CHANGED"); + break; + case APP_CMD_LOW_MEMORY: + LOGI("handle_cmd: APP_CMD_LOW_MEMORY"); + break; + default: + LOGI("handle_cmd: unhandled cmd=%d", cmd); + } +} + +void fgPlatformOpenWindow( SFG_Window* window, const char* title, + GLboolean positionUse, int x, int y, + GLboolean sizeUse, int w, int h, + GLboolean gameMode, GLboolean isSubWindow ); + +void fgPlatformProcessSingleEvent ( void ) +{ + /* When the screen is resized, the window handle still points to the + old window until the next SwapBuffer, while it's crucial to set + the size (onShape) correctly before the next onDisplay callback. + Plus we don't know if the next SwapBuffer already occurred at the + time we process the event (e.g. during onDisplay). */ + /* So we do the check each time rather than on event. */ + /* Interestingly, on a Samsung Galaxy S/PowerVR SGX540 GPU/Android + 2.3, that next SwapBuffer is fake (but still necessary to get the + new size). */ + SFG_Window* window = fgStructure.CurrentWindow; + if (window != NULL && window->Window.Handle != NULL) { + int32_t width = ANativeWindow_getWidth(window->Window.Handle); + int32_t height = ANativeWindow_getHeight(window->Window.Handle); + fghOnReshapeNotify(window,width,height,GL_FALSE); + } + + /* Read pending event. */ + int ident; + int events; + struct android_poll_source* source; + /* This is called "ProcessSingleEvent" but this means we'd only + process ~60 (screen Hz) mouse events per second, plus other ports + are processing all events already. So let's process all pending + events. */ + /* if ((ident=ALooper_pollOnce(0, NULL, &events, (void**)&source)) >= 0) { */ + while ((ident=ALooper_pollAll(0, NULL, &events, (void**)&source)) >= 0) { + /* Process this event. */ + if (source != NULL) { + source->process(source->app, source); + } + } + + /* If we're not in RESUME state, Android paused us, so wait */ + struct android_app* app = fgDisplay.pDisplay.app; + if (app->destroyRequested != 1 && app->activityState != APP_CMD_RESUME) { + INVOKE_WCB(*window, AppStatus, (GLUT_APPSTATUS_PAUSE)); + + int FOREVER = -1; + while (app->destroyRequested != 1 && (app->activityState != APP_CMD_RESUME)) { + if ((ident=ALooper_pollOnce(FOREVER, NULL, &events, (void**)&source)) >= 0) { + /* Process this event. */ + if (source != NULL) { + source->process(source->app, source); + } + } + } + /* Coming back from a pause: */ + /* - Recreate window context and surface */ + /* - Call user-defined hook to restore resources (textures...) */ + /* - Exit pause loop */ + if (app->destroyRequested != 1) { + /* Android is full-screen only, simplified call.. */ + /* Ideally we'd have a fgPlatformReopenWindow() */ + /* If we're hidden by a non-fullscreen or translucent activity, + we'll be paused but not stopped, and keep the current + surface; in which case fgPlatformOpenWindow will no-op. */ + fgPlatformOpenWindow(window, "", GL_FALSE, 0, 0, GL_FALSE, 0, 0, GL_FALSE, GL_FALSE); + + /* TODO: should there be a whole GLUT_INIT_WORK forced? probably... + * Could queue that up in APP_CMD_TERM_WINDOW handler, but it'll + * be not possible to ensure InitContext CB gets called before + * Resume CB like that.. so maybe just force calling initContext CB + * here is best. Or we could force work on the window in question.. + * 1) save old work mask, 2) set mask to init only, 3) call fgProcessWork directly + * 4) set work mask back to the one saved in step 1. + */ + if (!FETCH_WCB(*window, InitContext)) + fgWarning("Resuming application, but no callback to reload context resources (glutInitContextFunc)"); + } + + INVOKE_WCB(*window, AppStatus, (GLUT_APPSTATUS_RESUME)); + } +} + +void fgPlatformMainLoopPreliminaryWork ( void ) +{ + LOGI("fgPlatformMainLoopPreliminaryWork\n"); + + key_init(); + + /* Make sure glue isn't stripped. */ + /* JNI entry points need to be bundled even when linking statically */ + app_dummy(); +} + + +/* deal with work list items */ +void fgPlatformInitWork(SFG_Window* window) +{ + /* notify windowStatus/visibility */ + INVOKE_WCB( *window, WindowStatus, ( GLUT_FULLY_RETAINED ) ); + + /* Position callback, always at 0,0 */ + fghOnPositionNotify(window, 0, 0, GL_TRUE); + + /* Size gets notified on window creation with size detection in mainloop above + * XXX CHECK: does this messages happen too early like on windows, + * so client code cannot have registered a callback yet and the message + * is thus never received by client? + */ +} + +void fgPlatformPosResZordWork(SFG_Window* window, unsigned int workMask) +{ + if (workMask & GLUT_FULL_SCREEN_WORK) + fgPlatformFullScreenToggle( window ); + if (workMask & GLUT_POSITION_WORK) + fgPlatformPositionWindow( window, window->State.DesiredXpos, window->State.DesiredYpos ); + if (workMask & GLUT_SIZE_WORK) + fgPlatformReshapeWindow ( window, window->State.DesiredWidth, window->State.DesiredHeight ); + if (workMask & GLUT_ZORDER_WORK) + { + if (window->State.DesiredZOrder < 0) + fgPlatformPushWindow( window ); + else + fgPlatformPopWindow( window ); + } +} + +void fgPlatformVisibilityWork(SFG_Window* window) +{ + /* Visibility status of window should get updated in the window message handlers + * For now, none of these functions called below do anything, so don't worry + * about it + */ + SFG_Window *win = window; + switch (window->State.DesiredVisibility) + { + case DesireHiddenState: + fgPlatformHideWindow( window ); + break; + case DesireIconicState: + /* Call on top-level window */ + while (win->Parent) + win = win->Parent; + fgPlatformIconifyWindow( win ); + break; + case DesireNormalState: + fgPlatformShowWindow( window ); + break; + } +} + +/* dummy functions, not applicable on android */ +void fgPlatformSetColor(int idx, float r, float g, float b) +{ +} + +float fgPlatformGetColor(int idx, int comp) +{ +} + +void fgPlatformCopyColormap(int win) +{ +} diff --git a/src/android/fg_main_android.h b/src/android/fg_main_android.h new file mode 100644 index 0000000..c26ce52 --- /dev/null +++ b/src/android/fg_main_android.h @@ -0,0 +1,37 @@ +/* + * fg_main_android.h + * + * The Android-specific windows message processing methods. + * + * Copyright (C) 2012 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __FG_MAIN_ANDROID_H__ +#define __FG_MAIN_ANDROID_H__ + +#include +#include "fg_internal.h" + +extern void fgPlatformProcessSingleEvent(void); +extern unsigned long fgPlatformSystemTime(void); +extern void fgPlatformSleepForEvents(fg_time_t msec); +extern void fgPlatformMainLoopPreliminaryWork(void); + +#endif diff --git a/src/android/fg_runtime_android.c b/src/android/fg_runtime_android.c new file mode 100644 index 0000000..d96f3af --- /dev/null +++ b/src/android/fg_runtime_android.c @@ -0,0 +1,169 @@ +/* + * fg_runtime_android.c + * + * Android runtime + * + * Copyright (C) 2012 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* Parts taken from Android NDK's 'native-activity' sample: */ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include "android/native_app_glue/android_native_app_glue.h" +#include "android/fg_main_android.h" + +#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "FreeGLUT-jnicb", __VA_ARGS__)) +#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "FreeGLUT-jnicb", __VA_ARGS__)) + +/* Cf. fg_main_android.c */ +extern int32_t handle_input(struct android_app* app, AInputEvent* event); +extern void handle_cmd(struct android_app* app, int32_t cmd); + +extern int main(int argc, char* argv[]); + +/** NativeActivity Callbacks **/ +/* Caution: they are called in the native_activity thread, not the + FreeGLUT thread. Use android_app_write_cmd. */ + +/* Could be used instead of onNativeWindowRedrawNeeded */ +/* Deals with status bar presence */ +static void onContentRectChanged(ANativeActivity* activity, const ARect* rect) { + LOGI("onContentRectChanged: l=%d,t=%d,r=%d,b=%d", rect->left, rect->top, rect->right, rect->bottom); +} + +/* Bug: not called during a resize in android-9, only once on startup :/ */ +static void onNativeWindowResized(ANativeActivity* activity, ANativeWindow* window) { + LOGI("onNativeWindowResized: %p\n", (void*)activity); +} + +/* Called after a resize, compensate broken onNativeWindowResized */ +static void onNativeWindowRedrawNeeded(ANativeActivity* activity, ANativeWindow* window) { + LOGI("onNativeWindowRedrawNeeded: %p\n", (void*)activity); + struct android_app* app = (struct android_app*)activity->instance; + android_app_write_cmd(app, APP_CMD_WINDOW_RESIZED); +} + +/** + * Extract all .apk assets to the application directory so they can be + * accessed using accessed. + * TODO: parse directories recursively + */ +static void extract_assets(struct android_app* app) { + /* Get usable JNI context */ + JNIEnv* env = app->activity->env; + JavaVM* vm = app->activity->vm; + (*vm)->AttachCurrentThread(vm, &env, NULL); + + { + /* Get a handle on our calling NativeActivity class */ + jclass activityClass = (*env)->GetObjectClass(env, app->activity->clazz); + + /* Get path to cache dir (/data/data/org.myapp/cache) */ + jmethodID getCacheDir = (*env)->GetMethodID(env, activityClass, "getCacheDir", "()Ljava/io/File;"); + jobject file = (*env)->CallObjectMethod(env, app->activity->clazz, getCacheDir); + jclass fileClass = (*env)->FindClass(env, "java/io/File"); + jmethodID getAbsolutePath = (*env)->GetMethodID(env, fileClass, "getAbsolutePath", "()Ljava/lang/String;"); + jstring jpath = (jstring)(*env)->CallObjectMethod(env, file, getAbsolutePath); + const char* app_dir = (*env)->GetStringUTFChars(env, jpath, NULL); + + /* chdir in the application cache directory */ + LOGI("app_dir: %s", app_dir); + chdir(app_dir); + (*env)->ReleaseStringUTFChars(env, jpath, app_dir); + + /* Pre-extract assets, to avoid Android-specific file opening */ + { + AAssetManager* mgr = app->activity->assetManager; + AAssetDir* assetDir = AAssetManager_openDir(mgr, ""); + const char* filename = (const char*)NULL; + while ((filename = AAssetDir_getNextFileName(assetDir)) != NULL) { + AAsset* asset = AAssetManager_open(mgr, filename, AASSET_MODE_STREAMING); + char buf[BUFSIZ]; + int nb_read = 0; + FILE* out = fopen(filename, "w"); + while ((nb_read = AAsset_read(asset, buf, BUFSIZ)) > 0) + fwrite(buf, nb_read, 1, out); + fclose(out); + AAsset_close(asset); + } + AAssetDir_close(assetDir); + } + } + + (*vm)->DetachCurrentThread(vm); +} + +/** + * This is the main entry point of a native application that is using + * android_native_app_glue. It runs in its own thread, with its own + * event loop for receiving input events and doing other things. + */ +void android_main(struct android_app* app) { + LOGI("android_main savedState=%p", app->savedState); + + /* Register window resize callback */ + app->activity->callbacks->onNativeWindowResized = onNativeWindowResized; + app->activity->callbacks->onContentRectChanged = onContentRectChanged; + app->activity->callbacks->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded; + + app->onAppCmd = handle_cmd; + app->onInputEvent = handle_input; + + extract_assets(app); + + /* Call user's main */ + { + char progname[5] = "self"; + char* argv[] = {progname, NULL}; + fgDisplay.pDisplay.app = app; + main(1, argv); + /* FreeGLUT will exit() by itself if + GLUT_ACTION_ON_WINDOW_CLOSE == GLUT_ACTION_EXIT */ + } + + LOGI("android_main: end"); + + /* Let NativeActivity restart us */ + /* Users may want to forcibly exit() in their main() anyway because + NativeActivity doesn't dlclose() us, so all statically-assigned + variables keep their old values on restart.. */ +} diff --git a/src/android/fg_spaceball_android.c b/src/android/fg_spaceball_android.c new file mode 100644 index 0000000..b06410b --- /dev/null +++ b/src/android/fg_spaceball_android.c @@ -0,0 +1,58 @@ +/* + * fg_spaceball_android.c + * + * Spaceball support for Windows + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by Evan Felix + * Creation date: Sat Feb 4, 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +/* + * This code is a very complicated way of doing nothing. + * But is needed for Android platform builds. + */ + +#include +#include "fg_internal.h" + +void fgPlatformInitializeSpaceball(void) +{ + return; +} + +void fgPlatformSpaceballClose(void) +{ + return; +} + +int fgPlatformHasSpaceball(void) +{ + return 0; +} + +int fgPlatformSpaceballNumButtons(void) +{ + return 0; +} + +void fgPlatformSpaceballSetWindow(SFG_Window *window) +{ + return; +} diff --git a/src/android/fg_state_android.c b/src/android/fg_state_android.c new file mode 100644 index 0000000..bd2b034 --- /dev/null +++ b/src/android/fg_state_android.c @@ -0,0 +1,96 @@ +/* + * fg_state_android.c + * + * Android-specific freeglut state query methods. + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by John F. Fay, + * Copyright (C) 2012 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include "fg_internal.h" +#include "egl/fg_state_egl.h" + +int fgPlatformGlutDeviceGet ( GLenum eWhat ) +{ + switch( eWhat ) + { + case GLUT_HAS_KEYBOARD: + /* Android has a keyboard, though it may be virtual. */ + return 1; + + case GLUT_HAS_MOUSE: + /* Android has a touchscreen; until we get proper touchscreen + support, consider it as a mouse. */ + return 1 ; + + case GLUT_NUM_MOUSE_BUTTONS: + /* Android has a touchscreen; until we get proper touchscreen + support, consider it as a 1-button mouse. */ + return 1; + + default: + fgWarning( "glutDeviceGet(): missing enum handle %d", eWhat ); + break; + } + + /* And now -- the failure. */ + return -1; +} + +int fgPlatformGlutGet ( GLenum eWhat ) +{ + switch (eWhat) { + /* One full-screen window only */ + case GLUT_WINDOW_X: + case GLUT_WINDOW_Y: + case GLUT_WINDOW_BORDER_WIDTH: + case GLUT_WINDOW_HEADER_HEIGHT: + return 0; + + case GLUT_WINDOW_WIDTH: + case GLUT_WINDOW_HEIGHT: + { + if ( fgStructure.CurrentWindow == NULL ) + return 0; + int32_t width = ANativeWindow_getWidth(fgStructure.CurrentWindow->Window.Handle); + int32_t height = ANativeWindow_getHeight(fgStructure.CurrentWindow->Window.Handle); + switch ( eWhat ) + { + case GLUT_WINDOW_WIDTH: + return width; + case GLUT_WINDOW_HEIGHT: + return height; + } + } + + case GLUT_WINDOW_COLORMAP_SIZE: + /* 0 for RGBA/non-indexed mode */ + /* Under Android and GLES more generally, no indexed-mode */ + return 0; + + default: + return fghPlatformGlutGetEGL(eWhat); + } + return -1; +} diff --git a/src/android/fg_structure_android.c b/src/android/fg_structure_android.c new file mode 100644 index 0000000..b7acd20 --- /dev/null +++ b/src/android/fg_structure_android.c @@ -0,0 +1,36 @@ +/* + * fg_structure_android.c + * + * Windows and menus need tree structure + * + * Copyright (C) 2012 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" +#include "egl/fg_structure_egl.h" + +/** + * Initialize default platform-specific fields in SFG_Window + */ +void fgPlatformCreateWindow ( SFG_Window *window ) +{ + fghPlatformCreateWindowEGL(window); +} diff --git a/src/android/fg_window_android.c b/src/android/fg_window_android.c new file mode 100644 index 0000000..aad07db --- /dev/null +++ b/src/android/fg_window_android.c @@ -0,0 +1,183 @@ +/* + * fg_window_android.c + * + * Window management methods for Android + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Copied for Platform code by Evan Felix + * Copyright (C) 2012 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#define FREEGLUT_BUILDING_LIB +#include +#include "fg_internal.h" +#include "egl/fg_window_egl.h" +#include + +/* + * Opens a window. Requires a SFG_Window object created and attached + * to the freeglut structure. OpenGL context is created here. + */ +void fgPlatformOpenWindow( SFG_Window* window, const char* title, + GLboolean positionUse, int x, int y, + GLboolean sizeUse, int w, int h, + GLboolean gameMode, GLboolean isSubWindow ) +{ + /* TODO: only one full-screen window possible? */ + if (fgDisplay.pDisplay.single_native_window != NULL) { + fgWarning("You can't have more than one window on Android"); + return; + } + + /* First, wait until Activity surface is available */ + /* Normally events are processed through glutMainLoop(), but the + user didn't call it yet, and the Android may not have initialized + the View yet. So we need to wait for that to happen. */ + /* We can't return from this function before the OpenGL context is + properly made current with a valid surface. So we wait for the + surface. */ + while (fgDisplay.pDisplay.single_native_window == NULL) { + /* APP_CMD_INIT_WINDOW will do the job */ + int ident; + int events; + struct android_poll_source* source; + if ((ident=ALooper_pollOnce(0, NULL, &events, (void**)&source)) >= 0) + if (source != NULL) source->process(source->app, source); + /* fgPlatformProcessSingleEvent(); */ + } + window->Window.Handle = fgDisplay.pDisplay.single_native_window; + window->State.WorkMask |= GLUT_INIT_WORK; + + /* Create context */ + fghChooseConfig(&window->Window.pContext.egl.Config); + window->Window.Context = fghCreateNewContextEGL(window); + + EGLDisplay display = fgDisplay.pDisplay.egl.Display; + + /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is + * guaranteed to be accepted by ANativeWindow_setBuffersGeometry(). + * As soon as we picked a EGLConfig, we can safely reconfigure the + * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */ + EGLint vid; + eglGetConfigAttrib(display, window->Window.pContext.egl.Config, + EGL_NATIVE_VISUAL_ID, &vid); + ANativeWindow_setBuffersGeometry(window->Window.Handle, 0, 0, vid); + + fghPlatformOpenWindowEGL(window); + + /* Bind context to the current thread if it's lost */ + if (eglGetCurrentContext() == EGL_NO_CONTEXT && + eglMakeCurrent(fgDisplay.pDisplay.egl.Display, + window->Window.pContext.egl.Surface, + window->Window.pContext.egl.Surface, + window->Window.Context) == EGL_FALSE) + fgError("eglMakeCurrent: err=%x\n", eglGetError()); + + window->State.Visible = GL_TRUE; +} + +/* + * Request a window resize + */ +void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height ) +{ + fprintf(stderr, "fgPlatformReshapeWindow: STUB\n"); +} + +/* + * Closes a window, destroying the frame and OpenGL context + */ +void fgPlatformCloseWindow( SFG_Window* window ) +{ + fghPlatformCloseWindowEGL(window); + /* Window pre-created by Android, no way to delete it */ +} + +/* + * This function makes the specified window visible + */ +void fgPlatformShowWindow( SFG_Window *window ) +{ + fprintf(stderr, "fgPlatformShowWindow: STUB\n"); +} + +/* + * This function hides the specified window + */ +void fgPlatformHideWindow( SFG_Window *window ) +{ + fprintf(stderr, "fgPlatformHideWindow: STUB\n"); +} + +/* + * Iconify the specified window (top-level windows only) + */ +void fgPlatformIconifyWindow( SFG_Window *window ) +{ + fprintf(stderr, "fgPlatformGlutIconifyWindow: STUB\n"); +} + +/* + * Set the current window's title + */ +void fgPlatformGlutSetWindowTitle( const char* title ) +{ + fprintf(stderr, "fgPlatformGlutSetWindowTitle: STUB\n"); +} + +/* + * Set the current window's iconified title + */ +void fgPlatformGlutSetIconTitle( const char* title ) +{ + fprintf(stderr, "fgPlatformGlutSetIconTitle: STUB\n");} + +/* + * Change the specified window's position + */ +void fgPlatformPositionWindow( SFG_Window *window, int x, int y ) +{ + fprintf(stderr, "fgPlatformPositionWindow: STUB\n"); +} + +/* + * Lowers the specified window (by Z order change) + */ +void fgPlatformPushWindow( SFG_Window *window ) +{ + fprintf(stderr, "fgPlatformPushWindow: STUB\n"); +} + +/* + * Raises the specified window (by Z order change) + */ +void fgPlatformPopWindow( SFG_Window *window ) +{ + fprintf(stderr, "fgPlatformPopWindow: STUB\n"); +} + +/* + * Toggle the window's full screen state. + */ +void fgPlatformFullScreenToggle( SFG_Window *win ) +{ + fprintf(stderr, "fgPlatformFullScreenToggle: STUB\n"); +} diff --git a/src/android/native_app_glue/README b/src/android/native_app_glue/README new file mode 100644 index 0000000..5da3b36 --- /dev/null +++ b/src/android/native_app_glue/README @@ -0,0 +1,7 @@ +This code is copied from the Android NDK r7, from +source/android/native_app_glue/ . + +A few GCC warnings were suppressed. + +'android_app_write_cmd' was made non-static so that resize events can +be injected from FreeGLUT. diff --git a/src/android/native_app_glue/android_native_app_glue.c b/src/android/native_app_glue/android_native_app_glue.c new file mode 100644 index 0000000..be8d941 --- /dev/null +++ b/src/android/native_app_glue/android_native_app_glue.c @@ -0,0 +1,436 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include + +#include "android_native_app_glue.h" +#include + +#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__)) + +static void free_saved_state(struct android_app* android_app) { + pthread_mutex_lock(&android_app->mutex); + if (android_app->savedState != NULL) { + free(android_app->savedState); + android_app->savedState = NULL; + android_app->savedStateSize = 0; + } + pthread_mutex_unlock(&android_app->mutex); +} + +int8_t android_app_read_cmd(struct android_app* android_app) { + int8_t cmd; + if (read(android_app->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) { + switch (cmd) { + case APP_CMD_SAVE_STATE: + free_saved_state(android_app); + break; + } + return cmd; + } else { + LOGI("No data on command pipe!"); + } + return -1; +} + +static void print_cur_config(struct android_app* android_app) { + char lang[2], country[2]; + AConfiguration_getLanguage(android_app->config, lang); + AConfiguration_getCountry(android_app->config, country); + + LOGI("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d " + "keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d " + "modetype=%d modenight=%d", + AConfiguration_getMcc(android_app->config), + AConfiguration_getMnc(android_app->config), + lang[0], lang[1], country[0], country[1], + AConfiguration_getOrientation(android_app->config), + AConfiguration_getTouchscreen(android_app->config), + AConfiguration_getDensity(android_app->config), + AConfiguration_getKeyboard(android_app->config), + AConfiguration_getNavigation(android_app->config), + AConfiguration_getKeysHidden(android_app->config), + AConfiguration_getNavHidden(android_app->config), + AConfiguration_getSdkVersion(android_app->config), + AConfiguration_getScreenSize(android_app->config), + AConfiguration_getScreenLong(android_app->config), + AConfiguration_getUiModeType(android_app->config), + AConfiguration_getUiModeNight(android_app->config)); +} + +void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) { + switch (cmd) { + case APP_CMD_INPUT_CHANGED: + LOGI("APP_CMD_INPUT_CHANGED\n"); + pthread_mutex_lock(&android_app->mutex); + if (android_app->inputQueue != NULL) { + AInputQueue_detachLooper(android_app->inputQueue); + } + android_app->inputQueue = android_app->pendingInputQueue; + if (android_app->inputQueue != NULL) { + LOGI("Attaching input queue to looper"); + AInputQueue_attachLooper(android_app->inputQueue, + android_app->looper, LOOPER_ID_INPUT, NULL, + &android_app->inputPollSource); + } + pthread_cond_broadcast(&android_app->cond); + pthread_mutex_unlock(&android_app->mutex); + break; + + case APP_CMD_INIT_WINDOW: + LOGI("APP_CMD_INIT_WINDOW\n"); + pthread_mutex_lock(&android_app->mutex); + android_app->window = android_app->pendingWindow; + pthread_cond_broadcast(&android_app->cond); + pthread_mutex_unlock(&android_app->mutex); + break; + + case APP_CMD_TERM_WINDOW: + LOGI("APP_CMD_TERM_WINDOW\n"); + pthread_cond_broadcast(&android_app->cond); + break; + + case APP_CMD_RESUME: + case APP_CMD_START: + case APP_CMD_PAUSE: + case APP_CMD_STOP: + LOGI("activityState=%d\n", cmd); + pthread_mutex_lock(&android_app->mutex); + android_app->activityState = cmd; + pthread_cond_broadcast(&android_app->cond); + pthread_mutex_unlock(&android_app->mutex); + break; + + case APP_CMD_CONFIG_CHANGED: + LOGI("APP_CMD_CONFIG_CHANGED\n"); + AConfiguration_fromAssetManager(android_app->config, + android_app->activity->assetManager); + print_cur_config(android_app); + break; + + case APP_CMD_DESTROY: + LOGI("APP_CMD_DESTROY\n"); + android_app->destroyRequested = 1; + break; + } +} + +void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) { + switch (cmd) { + case APP_CMD_TERM_WINDOW: + LOGI("APP_CMD_TERM_WINDOW\n"); + pthread_mutex_lock(&android_app->mutex); + android_app->window = NULL; + pthread_cond_broadcast(&android_app->cond); + pthread_mutex_unlock(&android_app->mutex); + break; + + case APP_CMD_SAVE_STATE: + LOGI("APP_CMD_SAVE_STATE\n"); + pthread_mutex_lock(&android_app->mutex); + android_app->stateSaved = 1; + pthread_cond_broadcast(&android_app->cond); + pthread_mutex_unlock(&android_app->mutex); + break; + + case APP_CMD_RESUME: + free_saved_state(android_app); + break; + } +} + +void app_dummy() { + +} + +static void android_app_destroy(struct android_app* android_app) { + LOGI("android_app_destroy!"); + free_saved_state(android_app); + pthread_mutex_lock(&android_app->mutex); + if (android_app->inputQueue != NULL) { + AInputQueue_detachLooper(android_app->inputQueue); + } + AConfiguration_delete(android_app->config); + android_app->destroyed = 1; + pthread_cond_broadcast(&android_app->cond); + pthread_mutex_unlock(&android_app->mutex); + /* // Can't touch android_app object after this. */ +} + +static void process_input(struct android_app* app, struct android_poll_source* source) { + AInputEvent* event = NULL; + if (AInputQueue_getEvent(app->inputQueue, &event) >= 0) { + LOGI("New input event: type=%d\n", AInputEvent_getType(event)); + if (AInputQueue_preDispatchEvent(app->inputQueue, event)) { + return; + } + { + int32_t handled = 0; + if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event); + AInputQueue_finishEvent(app->inputQueue, event, handled); + } + } else { + LOGI("Failure reading next input event: %s\n", strerror(errno)); + } +} + +static void process_cmd(struct android_app* app, struct android_poll_source* source) { + int8_t cmd = android_app_read_cmd(app); + android_app_pre_exec_cmd(app, cmd); + if (app->onAppCmd != NULL) app->onAppCmd(app, cmd); + android_app_post_exec_cmd(app, cmd); +} + +static void* android_app_entry(void* param) { + struct android_app* android_app = (struct android_app*)param; + ALooper* looper; + + android_app->config = AConfiguration_new(); + AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager); + + print_cur_config(android_app); + + android_app->cmdPollSource.id = LOOPER_ID_MAIN; + android_app->cmdPollSource.app = android_app; + android_app->cmdPollSource.process = process_cmd; + android_app->inputPollSource.id = LOOPER_ID_INPUT; + android_app->inputPollSource.app = android_app; + android_app->inputPollSource.process = process_input; + + looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); + ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL, + &android_app->cmdPollSource); + android_app->looper = looper; + + pthread_mutex_lock(&android_app->mutex); + android_app->running = 1; + pthread_cond_broadcast(&android_app->cond); + pthread_mutex_unlock(&android_app->mutex); + + android_main(android_app); + + android_app_destroy(android_app); + return NULL; +} + +/* // -------------------------------------------------------------------- */ +/* // Native activity interaction (called from main thread) */ +/* // -------------------------------------------------------------------- */ + +static struct android_app* android_app_create(ANativeActivity* activity, + void* savedState, size_t savedStateSize) { + struct android_app* android_app = (struct android_app*)malloc(sizeof(struct android_app)); + int msgpipe[2]; + pthread_attr_t attr; + memset(android_app, 0, sizeof(struct android_app)); + android_app->activity = activity; + + pthread_mutex_init(&android_app->mutex, NULL); + pthread_cond_init(&android_app->cond, NULL); + + if (savedState != NULL) { + android_app->savedState = malloc(savedStateSize); + android_app->savedStateSize = savedStateSize; + memcpy(android_app->savedState, savedState, savedStateSize); + } + + if (pipe(msgpipe)) { + LOGI("could not create pipe: %s", strerror(errno)); + } + android_app->msgread = msgpipe[0]; + android_app->msgwrite = msgpipe[1]; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_create(&android_app->thread, &attr, android_app_entry, android_app); + + /* // Wait for thread to start. */ + pthread_mutex_lock(&android_app->mutex); + while (!android_app->running) { + pthread_cond_wait(&android_app->cond, &android_app->mutex); + } + pthread_mutex_unlock(&android_app->mutex); + + return android_app; +} + +/* static */void android_app_write_cmd(struct android_app* android_app, int8_t cmd) { + if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) { + LOGI("Failure writing android_app cmd: %s\n", strerror(errno)); + } +} + +static void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) { + pthread_mutex_lock(&android_app->mutex); + android_app->pendingInputQueue = inputQueue; + android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED); + while (android_app->inputQueue != android_app->pendingInputQueue) { + pthread_cond_wait(&android_app->cond, &android_app->mutex); + } + pthread_mutex_unlock(&android_app->mutex); +} + +static void android_app_set_window(struct android_app* android_app, ANativeWindow* window) { + pthread_mutex_lock(&android_app->mutex); + if (android_app->pendingWindow != NULL) { + android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW); + } + android_app->pendingWindow = window; + if (window != NULL) { + android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW); + } + while (android_app->window != android_app->pendingWindow) { + pthread_cond_wait(&android_app->cond, &android_app->mutex); + } + pthread_mutex_unlock(&android_app->mutex); +} + +static void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) { + pthread_mutex_lock(&android_app->mutex); + android_app_write_cmd(android_app, cmd); + while (android_app->activityState != cmd) { + pthread_cond_wait(&android_app->cond, &android_app->mutex); + } + pthread_mutex_unlock(&android_app->mutex); +} + +static void android_app_free(struct android_app* android_app) { + pthread_mutex_lock(&android_app->mutex); + android_app_write_cmd(android_app, APP_CMD_DESTROY); + while (!android_app->destroyed) { + pthread_cond_wait(&android_app->cond, &android_app->mutex); + } + pthread_mutex_unlock(&android_app->mutex); + + close(android_app->msgread); + close(android_app->msgwrite); + pthread_cond_destroy(&android_app->cond); + pthread_mutex_destroy(&android_app->mutex); + free(android_app); +} + +static void onDestroy(ANativeActivity* activity) { + LOGI("Destroy: %p\n", (void*)activity); + android_app_free((struct android_app*)activity->instance); +} + +static void onStart(ANativeActivity* activity) { + LOGI("Start: %p\n", (void*)activity); + android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_START); +} + +static void onResume(ANativeActivity* activity) { + LOGI("Resume: %p\n", (void*)activity); + android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_RESUME); +} + +static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) { + struct android_app* android_app = (struct android_app*)activity->instance; + void* savedState = NULL; + + LOGI("SaveInstanceState: %p\n", (void*)activity); + pthread_mutex_lock(&android_app->mutex); + android_app->stateSaved = 0; + android_app_write_cmd(android_app, APP_CMD_SAVE_STATE); + while (!android_app->stateSaved) { + pthread_cond_wait(&android_app->cond, &android_app->mutex); + } + + if (android_app->savedState != NULL) { + savedState = android_app->savedState; + *outLen = android_app->savedStateSize; + android_app->savedState = NULL; + android_app->savedStateSize = 0; + } + + pthread_mutex_unlock(&android_app->mutex); + + return savedState; +} + +static void onPause(ANativeActivity* activity) { + LOGI("Pause: %p\n", (void*)activity); + android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_PAUSE); +} + +static void onStop(ANativeActivity* activity) { + LOGI("Stop: %p\n", (void*)activity); + android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_STOP); +} + +static void onConfigurationChanged(ANativeActivity* activity) { + struct android_app* android_app = (struct android_app*)activity->instance; + LOGI("ConfigurationChanged: %p\n", (void*)activity); + android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED); +} + +static void onLowMemory(ANativeActivity* activity) { + struct android_app* android_app = (struct android_app*)activity->instance; + LOGI("LowMemory: %p\n", (void*)activity); + android_app_write_cmd(android_app, APP_CMD_LOW_MEMORY); +} + +static void onWindowFocusChanged(ANativeActivity* activity, int focused) { + LOGI("WindowFocusChanged: %p -- %d\n", (void*)activity, focused); + android_app_write_cmd((struct android_app*)activity->instance, + focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS); +} + +static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) { + LOGI("NativeWindowCreated: %p -- %p\n", (void*)activity, (void*)window); + android_app_set_window((struct android_app*)activity->instance, window); +} + +static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) { + LOGI("NativeWindowDestroyed: %p -- %p\n", (void*)activity, (void*)window); + android_app_set_window((struct android_app*)activity->instance, NULL); +} + +static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) { + LOGI("InputQueueCreated: %p -- %p\n", (void*)activity, (void*)queue); + android_app_set_input((struct android_app*)activity->instance, queue); +} + +static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) { + LOGI("InputQueueDestroyed: %p -- %p\n", (void*)activity, (void*)queue); + android_app_set_input((struct android_app*)activity->instance, NULL); +} + +void ANativeActivity_onCreate(ANativeActivity* activity, + void* savedState, size_t savedStateSize) { + LOGI("Creating: %p\n", (void*)activity); + activity->callbacks->onDestroy = onDestroy; + activity->callbacks->onStart = onStart; + activity->callbacks->onResume = onResume; + activity->callbacks->onSaveInstanceState = onSaveInstanceState; + activity->callbacks->onPause = onPause; + activity->callbacks->onStop = onStop; + activity->callbacks->onConfigurationChanged = onConfigurationChanged; + activity->callbacks->onLowMemory = onLowMemory; + activity->callbacks->onWindowFocusChanged = onWindowFocusChanged; + activity->callbacks->onNativeWindowCreated = onNativeWindowCreated; + activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed; + activity->callbacks->onInputQueueCreated = onInputQueueCreated; + activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed; + + activity->instance = android_app_create(activity, savedState, savedStateSize); +} diff --git a/src/android/native_app_glue/android_native_app_glue.h b/src/android/native_app_glue/android_native_app_glue.h new file mode 100644 index 0000000..0c59ec2 --- /dev/null +++ b/src/android/native_app_glue/android_native_app_glue.h @@ -0,0 +1,351 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _ANDROID_NATIVE_APP_GLUE_H +#define _ANDROID_NATIVE_APP_GLUE_H + +#include +#include +#include + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * The native activity interface provided by + * is based on a set of application-provided callbacks that will be called + * by the Activity's main thread when certain events occur. + * + * This means that each one of this callbacks _should_ _not_ block, or they + * risk having the system force-close the application. This programming + * model is direct, lightweight, but constraining. + * + * The 'threaded_native_app' static library is used to provide a different + * execution model where the application can implement its own main event + * loop in a different thread instead. Here's how it works: + * + * 1/ The application must provide a function named "android_main()" that + * will be called when the activity is created, in a new thread that is + * distinct from the activity's main thread. + * + * 2/ android_main() receives a pointer to a valid "android_app" structure + * that contains references to other important objects, e.g. the + * ANativeActivity obejct instance the application is running in. + * + * 3/ the "android_app" object holds an ALooper instance that already + * listens to two important things: + * + * - activity lifecycle events (e.g. "pause", "resume"). See APP_CMD_XXX + * declarations below. + * + * - input events coming from the AInputQueue attached to the activity. + * + * Each of these correspond to an ALooper identifier returned by + * ALooper_pollOnce with values of LOOPER_ID_MAIN and LOOPER_ID_INPUT, + * respectively. + * + * Your application can use the same ALooper to listen to additional + * file-descriptors. They can either be callback based, or with return + * identifiers starting with LOOPER_ID_USER. + * + * 4/ Whenever you receive a LOOPER_ID_MAIN or LOOPER_ID_INPUT event, + * the returned data will point to an android_poll_source structure. You + * can call the process() function on it, and fill in android_app->onAppCmd + * and android_app->onInputEvent to be called for your own processing + * of the event. + * + * Alternatively, you can call the low-level functions to read and process + * the data directly... look at the process_cmd() and process_input() + * implementations in the glue to see how to do this. + * + * See the sample named "native-activity" that comes with the NDK with a + * full usage example. Also look at the JavaDoc of NativeActivity. + */ + +struct android_app; + +/** + * Data associated with an ALooper fd that will be returned as the "outData" + * when that source has data ready. + */ +struct android_poll_source { + /* // The identifier of this source. May be LOOPER_ID_MAIN or */ + /* // LOOPER_ID_INPUT. */ + int32_t id; + + /* // The android_app this ident is associated with. */ + struct android_app* app; + + /* // Function to call to perform the standard processing of data from */ + /* // this source. */ + void (*process)(struct android_app* app, struct android_poll_source* source); +}; + +/** + * This is the interface for the standard glue code of a threaded + * application. In this model, the application's code is running + * in its own thread separate from the main thread of the process. + * It is not required that this thread be associated with the Java + * VM, although it will need to be in order to make JNI calls any + * Java objects. + */ +struct android_app { + /* // The application can place a pointer to its own state object */ + /* // here if it likes. */ + void* userData; + + /* // Fill this in with the function to process main app commands (APP_CMD_*) */ + void (*onAppCmd)(struct android_app* app, int32_t cmd); + + /* // Fill this in with the function to process input events. At this point */ + /* // the event has already been pre-dispatched, and it will be finished upon */ + /* // return. Return 1 if you have handled the event, 0 for any default */ + /* // dispatching. */ + int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event); + + /* // The ANativeActivity object instance that this app is running in. */ + ANativeActivity* activity; + + /* // The current configuration the app is running in. */ + AConfiguration* config; + + /* // This is the last instance's saved state, as provided at creation time. */ + /* // It is NULL if there was no state. You can use this as you need; the */ + /* // memory will remain around until you call android_app_exec_cmd() for */ + /* // APP_CMD_RESUME, at which point it will be freed and savedState set to NULL. */ + /* // These variables should only be changed when processing a APP_CMD_SAVE_STATE, */ + /* // at which point they will be initialized to NULL and you can malloc your */ + /* // state and place the information here. In that case the memory will be */ + /* // freed for you later. */ + void* savedState; + size_t savedStateSize; + + /* // The ALooper associated with the app's thread. */ + ALooper* looper; + + /* // When non-NULL, this is the input queue from which the app will */ + /* // receive user input events. */ + AInputQueue* inputQueue; + + /* // When non-NULL, this is the window surface that the app can draw in. */ + ANativeWindow* window; + + /* // Current content rectangle of the window; this is the area where the */ + /* // window's content should be placed to be seen by the user. */ + ARect contentRect; + + /* // Current state of the app's activity. May be either APP_CMD_START, */ + /* // APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below. */ + int activityState; + + /* // This is non-zero when the application's NativeActivity is being */ + /* // destroyed and waiting for the app thread to complete. */ + int destroyRequested; + + /* // ------------------------------------------------- */ + /* // Below are "private" implementation of the glue code. */ + + pthread_mutex_t mutex; + pthread_cond_t cond; + + int msgread; + int msgwrite; + + pthread_t thread; + + struct android_poll_source cmdPollSource; + struct android_poll_source inputPollSource; + + int running; + int stateSaved; + int destroyed; + int redrawNeeded; + AInputQueue* pendingInputQueue; + ANativeWindow* pendingWindow; + ARect pendingContentRect; +}; + +enum { + /** + * Looper data ID of commands coming from the app's main thread, which + * is returned as an identifier from ALooper_pollOnce(). The data for this + * identifier is a pointer to an android_poll_source structure. + * These can be retrieved and processed with android_app_read_cmd() + * and android_app_exec_cmd(). + */ + LOOPER_ID_MAIN = 1, + + /** + * Looper data ID of events coming from the AInputQueue of the + * application's window, which is returned as an identifier from + * ALooper_pollOnce(). The data for this identifier is a pointer to an + * android_poll_source structure. These can be read via the inputQueue + * object of android_app. + */ + LOOPER_ID_INPUT = 2, + + /** + * Start of user-defined ALooper identifiers. + */ + LOOPER_ID_USER = 3 +}; + +enum { + /** + * Command from main thread: the AInputQueue has changed. Upon processing + * this command, android_app->inputQueue will be updated to the new queue + * (or NULL). + */ + APP_CMD_INPUT_CHANGED, + + /** + * Command from main thread: a new ANativeWindow is ready for use. Upon + * receiving this command, android_app->window will contain the new window + * surface. + */ + APP_CMD_INIT_WINDOW, + + /** + * Command from main thread: the existing ANativeWindow needs to be + * terminated. Upon receiving this command, android_app->window still + * contains the existing window; after calling android_app_exec_cmd + * it will be set to NULL. + */ + APP_CMD_TERM_WINDOW, + + /** + * Command from main thread: the current ANativeWindow has been resized. + * Please redraw with its new size. + */ + APP_CMD_WINDOW_RESIZED, + + /** + * Command from main thread: the system needs that the current ANativeWindow + * be redrawn. You should redraw the window before handing this to + * android_app_exec_cmd() in order to avoid transient drawing glitches. + */ + APP_CMD_WINDOW_REDRAW_NEEDED, + + /** + * Command from main thread: the content area of the window has changed, + * such as from the soft input window being shown or hidden. You can + * find the new content rect in android_app::contentRect. + */ + APP_CMD_CONTENT_RECT_CHANGED, + + /** + * Command from main thread: the app's activity window has gained + * input focus. + */ + APP_CMD_GAINED_FOCUS, + + /** + * Command from main thread: the app's activity window has lost + * input focus. + */ + APP_CMD_LOST_FOCUS, + + /** + * Command from main thread: the current device configuration has changed. + */ + APP_CMD_CONFIG_CHANGED, + + /** + * Command from main thread: the system is running low on memory. + * Try to reduce your memory use. + */ + APP_CMD_LOW_MEMORY, + + /** + * Command from main thread: the app's activity has been started. + */ + APP_CMD_START, + + /** + * Command from main thread: the app's activity has been resumed. + */ + APP_CMD_RESUME, + + /** + * Command from main thread: the app should generate a new saved state + * for itself, to restore from later if needed. If you have saved state, + * allocate it with malloc and place it in android_app.savedState with + * the size in android_app.savedStateSize. The will be freed for you + * later. + */ + APP_CMD_SAVE_STATE, + + /** + * Command from main thread: the app's activity has been paused. + */ + APP_CMD_PAUSE, + + /** + * Command from main thread: the app's activity has been stopped. + */ + APP_CMD_STOP, + + /** + * Command from main thread: the app's activity is being destroyed, + * and waiting for the app thread to clean up and exit before proceeding. + */ + APP_CMD_DESTROY +}; + +/** + * Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next + * app command message. + */ +int8_t android_app_read_cmd(struct android_app* android_app); + +/** + * Call with the command returned by android_app_read_cmd() to do the + * initial pre-processing of the given command. You can perform your own + * actions for the command after calling this function. + */ +void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd); + +/** + * Call with the command returned by android_app_read_cmd() to do the + * final post-processing of the given command. You must have done your own + * actions for the command before calling this function. + */ +void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd); + +/** + * Dummy function you can call to ensure glue code isn't stripped. + */ +void app_dummy(); + +/** + * This is the function that application code must implement, representing + * the main entry to the app. + */ +extern void android_main(struct android_app* app); + +/* static */void android_app_write_cmd(struct android_app* android_app, int8_t cmd); + +#ifdef __cplusplus +} +#endif + +#endif /* _ANDROID_NATIVE_APP_GLUE_H */ diff --git a/src/blackberry/fg_init_blackberry.c b/src/blackberry/fg_init_blackberry.c new file mode 100644 index 0000000..ed1b1c9 --- /dev/null +++ b/src/blackberry/fg_init_blackberry.c @@ -0,0 +1,107 @@ +/* + * fg_init_blackberry.c + * + * Various freeglut initialization functions. + * + * Copyright (C) 2012 Sylvain Beucler + * Copyright (C) 2013 Vincent Simonetti + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" +#include "fg_init.h" +#include "egl/fg_init_egl.h" +#include +#include + +void fgPlatformInitialize() +{ + bps_initialize(); + + fghPlatformInitializeEGL(); + + /* Prepare for screen events */ + fgDisplay.pDisplay.event = NULL; + fgDisplay.pDisplay.screenContext = NULL; + + /* Create window */ + if (screen_create_context(&fgDisplay.pDisplay.screenContext, 0)) { + fgError("Could not create screen context"); + return; + } + + /* Get screen size */ + int displayCount; + screen_display_t* displays; + int vals[2]; + if(screen_get_context_property_iv(fgDisplay.pDisplay.screenContext, SCREEN_PROPERTY_DISPLAY_COUNT, &displayCount)) { + fgWarning("Could not get display count. Screen size not determined and will be left at default values"); + } else if(displayCount >= 1) { + displays = (screen_display_t*)calloc(displayCount, sizeof(screen_display_t)); + if(screen_get_context_property_pv(fgDisplay.pDisplay.screenContext, SCREEN_PROPERTY_DISPLAYS, (void**)displays)) { + fgWarning("Could not get displays. Screen size not determined and will be left at default values"); + } else { + /* We only care about the first one, which is the device display */ + if(screen_get_display_property_iv(displays[0], SCREEN_PROPERTY_SIZE, vals)) { + fgWarning("Could not get display size. Values will be left at default"); + } else { + if(screen_get_display_property_iv(displays[0], SCREEN_PROPERTY_ROTATION, &displayCount) || (displayCount == 0 || displayCount == 180)) { + fgDisplay.ScreenWidth = vals[0]; + fgDisplay.ScreenHeight = vals[1]; + } else { + fgDisplay.ScreenWidth = vals[1]; + fgDisplay.ScreenHeight = vals[0]; + } + } + if(screen_get_display_property_iv(displays[0], SCREEN_PROPERTY_PHYSICAL_SIZE, vals)) { + fgWarning("Could not get physical display size. Values will be left at default"); + } else { + fgDisplay.ScreenWidthMM = vals[0]; + fgDisplay.ScreenHeightMM = vals[1]; + } + } + free(displays); + } + + /* Get start time */ + fgState.Time = fgSystemTime(); + + fgState.Initialised = GL_TRUE; +} + +void fgPlatformCloseDisplay() +{ + fghPlatformCloseDisplayEGL(); + + screen_destroy_context(fgDisplay.pDisplay.screenContext); + fgDisplay.pDisplay.screenContext = NULL; + + bps_shutdown(); +} + +/** + * Close joystick and serial input devices + */ +void fgPlatformDeinitialiseInputDevices ( void ) +{ + fghCloseInputDevices (); + fgState.JoysticksInitialised = GL_FALSE; + fgState.InputDevsInitialised = GL_FALSE; +} diff --git a/src/blackberry/fg_internal_blackberry.h b/src/blackberry/fg_internal_blackberry.h new file mode 100644 index 0000000..eae1bd9 --- /dev/null +++ b/src/blackberry/fg_internal_blackberry.h @@ -0,0 +1,134 @@ +/* + * fg_internal_blackberry.h + * + * The freeglut library private include file. + * + * Copyright (C) 2012 Sylvain Beucler + * Copyright (C) 2013 Vincent Simonetti + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef FREEGLUT_INTERNAL_BLACKBERRY_H +#define FREEGLUT_INTERNAL_BLACKBERRY_H + +//Minor modified version of fg_internal_android.h + +/* -- PLATFORM-SPECIFIC INCLUDES ------------------------------------------- */ +/* BlackBerry OpenGL ES is accessed through EGL */ +#include "egl/fg_internal_egl.h" +#include +#include +#include + +/* -- GLOBAL TYPE DEFINITIONS ---------------------------------------------- */ +/* The structure used by display initialization in fg_init.c */ +typedef struct tagSFG_PlatformDisplay SFG_PlatformDisplay; +struct tagSFG_PlatformDisplay +{ + struct tagSFG_PlatformDisplayEGL egl; + screen_context_t screenContext; + bps_event_t* event; + EGLNativeWindowType single_native_window; +}; + +typedef struct tagSFG_PlatformContext SFG_PlatformContext; +/* SFG_PlatformContext is used for SFG_Window.Window */ +struct tagSFG_PlatformContext +{ + struct tagSFG_PlatformContextEGL egl; +}; + + +/** + * Virtual PAD (spots on touchscreen that simulate keys) + */ +struct vpad_state { + bool on; + bool left; + bool right; + bool up; + bool down; +}; +struct touchscreen { + struct vpad_state vpad; + bool in_mmotion; +}; + +/* -- INPUT DEFINITIONS ---------------------------------------------------- */ +#define WHEEL_DELTA 120 //This is taken from http://msdn.microsoft.com/en-us/library/windows/desktop/ms646254(v=vs.85).aspx + + +/* -- JOYSTICK-SPECIFIC STRUCTURES AND TYPES ------------------------------- */ +/* + * Initial defines from "js.h" starting around line 33 with the existing "fg_joystick.c" + * interspersed + */ + +/* + * We'll put these values in and that should + * allow the code to at least compile when there is + * no support. The JS open routine should error out + * and shut off all the code downstream anyway and if + * the application doesn't use a joystick we'll be fine. + */ + +struct JS_DATA_TYPE +{ + int buttons; + int x; + int y; +}; + +#define JS_RETURN (sizeof(struct JS_DATA_TYPE)) + +/* XXX It might be better to poll the operating system for the numbers of buttons and + * XXX axes and then dynamically allocate the arrays. + */ +#define _JS_MAX_AXES 16 +typedef struct tagSFG_PlatformJoystick SFG_PlatformJoystick; +struct tagSFG_PlatformJoystick +{ + struct JS_DATA_TYPE js; + + char fname [ 128 ]; + int fd; +}; + +/* Window's state description. This structure should be kept portable. */ +typedef struct tagSFG_PlatformWindowState SFG_PlatformWindowState; +struct tagSFG_PlatformWindowState +{ + int newWidth; + int newHeight; + int originalRotation; + navigator_window_state_t windowState; + GLboolean windowCovered; + int keyboardHeight; + GLboolean keyboardOpen; +}; + +/* Menu font and color definitions */ +#define FREEGLUT_MENU_FONT NULL + +#define FREEGLUT_MENU_PEN_FORE_COLORS {0.0f, 0.0f, 0.0f, 1.0f} +#define FREEGLUT_MENU_PEN_BACK_COLORS {0.70f, 0.70f, 0.70f, 1.0f} +#define FREEGLUT_MENU_PEN_HFORE_COLORS {0.0f, 0.0f, 0.0f, 1.0f} +#define FREEGLUT_MENU_PEN_HBACK_COLORS {1.0f, 1.0f, 1.0f, 1.0f} + +#endif /* FREEGLUT_INTERNAL_BLACKBERRY_H */ diff --git a/src/blackberry/fg_main_blackberry.c b/src/blackberry/fg_main_blackberry.c new file mode 100644 index 0000000..1935acd --- /dev/null +++ b/src/blackberry/fg_main_blackberry.c @@ -0,0 +1,893 @@ +/* + * fg_main_blackberry.c + * + * The BlackBerry-specific windows message processing methods. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Copied for Platform code by Evan Felix + * Copyright (C) 2012 Sylvain Beucler + * Copyright (C) 2013 Vincent Simonetti + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" +#include "egl/fg_window_egl.h" + +#ifdef NDEBUG +#define LOGI(...) +#endif + +#ifdef __PLAYBOOK__ +#include +#ifndef LOGI +#define LOGI(...) ((void)slogf(1337, _SLOG_INFO, __VA_ARGS__)) +#endif +#define LOGW(...) ((void)slogf(1337, _SLOG_WARNING, __VA_ARGS__)) +#ifndef SLOG2_FA_SIGNED +#define SLOG2_FA_SIGNED(x) (x) +#endif +#else +#include +#ifndef LOGI +#define LOGI(...) ((void)slog2fa(NULL, 1337, SLOG2_INFO, __VA_ARGS__, SLOG2_FA_END)) +#endif +#define LOGW(...) ((void)slog2fa(NULL, 1337, SLOG2_WARNING, __VA_ARGS__, SLOG2_FA_END)) +#endif +#include +#include +#include +#include +#include +#include +#include + +extern void fghOnReshapeNotify(SFG_Window *window, int width, int height, GLboolean forceNotify); +extern void fghOnPositionNotify(SFG_Window *window, int x, int y, GLboolean forceNotify); +extern void fgPlatformFullScreenToggle( SFG_Window *win ); +extern void fgPlatformPositionWindow( SFG_Window *window, int x, int y ); +extern void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height ); +extern void fgPlatformPushWindow( SFG_Window *window ); +extern void fgPlatformPopWindow( SFG_Window *window ); +extern void fgPlatformHideWindow( SFG_Window *window ); +extern void fgPlatformIconifyWindow( SFG_Window *window ); +extern void fgPlatformShowWindow( SFG_Window *window ); +extern void fgPlatformMainLoopPostWork ( void ); +extern void fgPlatformRotateWindow( SFG_Window *window, int rotation ); +extern void fgPlatformFlushCommands ( void ); + +static struct touchscreen touchscreen; + +#define ESCAPE_BUTTON_KEY 0x001B + +unsigned int key_special(int qnxKeycode) +{ + switch(qnxKeycode) { + case KEYCODE_F1: + return GLUT_KEY_F1; + case KEYCODE_F2: + return GLUT_KEY_F2; + case KEYCODE_F3: + return GLUT_KEY_F3; + case KEYCODE_F4: + return GLUT_KEY_F4; + case KEYCODE_F5: + return GLUT_KEY_F5; + case KEYCODE_F6: + return GLUT_KEY_F6; + case KEYCODE_F7: + return GLUT_KEY_F7; + case KEYCODE_F8: + return GLUT_KEY_F8; + case KEYCODE_F9: + return GLUT_KEY_F9; + case KEYCODE_F10: + return GLUT_KEY_F10; + case KEYCODE_F11: + return GLUT_KEY_F11; + case KEYCODE_F12: + return GLUT_KEY_F12; + case KEYCODE_PG_UP: + return GLUT_KEY_PAGE_UP; + case KEYCODE_PG_DOWN: + return GLUT_KEY_PAGE_DOWN; + case KEYCODE_HOME: + return GLUT_KEY_HOME; + case KEYCODE_END: + return GLUT_KEY_END; + case KEYCODE_INSERT: + return GLUT_KEY_INSERT; + case KEYCODE_UP: + //case KEYCODE_KP_UP: + return GLUT_KEY_UP; + case KEYCODE_DOWN: + //case KEYCODE_KP_DOWN: + return GLUT_KEY_DOWN; + case KEYCODE_LEFT: + //case KEYCODE_KP_LEFT: + return GLUT_KEY_LEFT; + case KEYCODE_RIGHT: + //case KEYCODE_KP_RIGHT: + return GLUT_KEY_RIGHT; + case KEYCODE_NUM_LOCK: + return GLUT_KEY_NUM_LOCK; + case KEYCODE_LEFT_ALT: + return GLUT_KEY_ALT_L; + case KEYCODE_RIGHT_ALT: + return GLUT_KEY_ALT_R; + case KEYCODE_LEFT_SHIFT: + return GLUT_KEY_SHIFT_L; + case KEYCODE_RIGHT_SHIFT: + return GLUT_KEY_SHIFT_R; + case KEYCODE_LEFT_CTRL: + return GLUT_KEY_CTRL_L; + case KEYCODE_RIGHT_CTRL: + return GLUT_KEY_CTRL_R; + } + return 0; +} + +unsigned char key_ascii(int qnxKeycode) +{ + if (qnxKeycode >= KEYCODE_PC_KEYS && qnxKeycode <= UNICODE_PRIVATE_USE_AREA_LAST) { + switch (qnxKeycode) { + case KEYCODE_BACKSPACE: + return 0x0008; + case KEYCODE_TAB: + return 0x0009; + case KEYCODE_KP_ENTER: + case KEYCODE_RETURN: + return 0x000A; + case KEYCODE_ESCAPE: + return ESCAPE_BUTTON_KEY; + } + } + return qnxKeycode; +} + +//From fg_main_x11 +fg_time_t fgPlatformSystemTime ( void ) +{ +#ifdef CLOCK_MONOTONIC + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + return now.tv_nsec/1000000 + now.tv_sec*1000; +#elif defined(HAVE_GETTIMEOFDAY) + struct timeval now; + gettimeofday( &now, NULL ); + return now.tv_usec/1000 + now.tv_sec*1000; +#endif +} + +/* + * Does the magic required to relinquish the CPU until something interesting + * happens. + */ +void fgPlatformSleepForEvents( fg_time_t msec ) +{ + if(fgStructure.CurrentWindow && fgDisplay.pDisplay.event == NULL && + bps_get_event(&fgDisplay.pDisplay.event, (int)msec) != BPS_SUCCESS) { + LOGW("BPS couldn't get event"); + } +} + +void handle_left_mouse(int x, int y, int height, int eventType, SFG_Window* window) +{ + bool handled = false; + /* Virtual arrows PAD */ + /* Don't interfere with existing mouse move event */ + if (!touchscreen.in_mmotion) { + struct vpad_state prev_vpad = touchscreen.vpad; + touchscreen.vpad.left = touchscreen.vpad.right = touchscreen.vpad.up = touchscreen.vpad.down = false; + + if (eventType == SCREEN_EVENT_MTOUCH_TOUCH || eventType == SCREEN_EVENT_MTOUCH_MOVE) { + if ((x > 0 && x < 100) && (y > (height - 100) && y < height)) + { + touchscreen.vpad.left = true; + } + if ((x > 200 && x < 300) && (y > (height - 100) && y < height)) + { + touchscreen.vpad.right = true; + } + if ((x > 100 && x < 200) && (y > (height - 100) && y < height)) + { + touchscreen.vpad.down = true; + } + if ((x > 100 && x < 200) && (y > (height - 200) && y < (height - 100))) + { + touchscreen.vpad.up = true; + } + } + + if (eventType == SCREEN_EVENT_MTOUCH_TOUCH && + (touchscreen.vpad.left || touchscreen.vpad.right || touchscreen.vpad.down || touchscreen.vpad.up)) { + touchscreen.vpad.on = true; + } + if (eventType == SCREEN_EVENT_MTOUCH_RELEASE) { + touchscreen.vpad.on = false; + } + + if (prev_vpad.left != touchscreen.vpad.left + || prev_vpad.right != touchscreen.vpad.right + || prev_vpad.up != touchscreen.vpad.up + || prev_vpad.down != touchscreen.vpad.down + || prev_vpad.on != touchscreen.vpad.on) { + if (FETCH_WCB(*window, Special)) { + if (prev_vpad.left == false && touchscreen.vpad.left == true) { + INVOKE_WCB(*window, Special, (GLUT_KEY_LEFT, x, y)); + } + else if (prev_vpad.right == false && touchscreen.vpad.right == true) { + INVOKE_WCB(*window, Special, (GLUT_KEY_RIGHT, x, y)); + } + else if (prev_vpad.up == false && touchscreen.vpad.up == true) { + INVOKE_WCB(*window, Special, (GLUT_KEY_UP, x, y)); + } + else if (prev_vpad.down == false && touchscreen.vpad.down == true) { + INVOKE_WCB(*window, Special, (GLUT_KEY_DOWN, x, y)); + } + } + if (FETCH_WCB(*window, SpecialUp)) { + if (prev_vpad.left == true && touchscreen.vpad.left == false) { + INVOKE_WCB(*window, SpecialUp, (GLUT_KEY_LEFT, x, y)); + } + if (prev_vpad.right == true && touchscreen.vpad.right == false) { + INVOKE_WCB(*window, SpecialUp, (GLUT_KEY_RIGHT, x, y)); + } + if (prev_vpad.up == true && touchscreen.vpad.up == false) { + INVOKE_WCB(*window, SpecialUp, (GLUT_KEY_UP, x, y)); + } + if (prev_vpad.down == true && touchscreen.vpad.down == false) { + INVOKE_WCB(*window, SpecialUp, (GLUT_KEY_DOWN, x, y)); + } + } + handled = true; + } + } + + /* Normal mouse events */ + if (!handled && !touchscreen.vpad.on) { + window->State.MouseX = x; + window->State.MouseY = y; + + if(eventType == SCREEN_EVENT_MTOUCH_MOVE) { + INVOKE_WCB(*window, Motion, (x, y)); + } else if(FETCH_WCB(*window, Mouse)) { + touchscreen.in_mmotion = eventType == SCREEN_EVENT_MTOUCH_TOUCH; + int glutTouchType = eventType == SCREEN_EVENT_MTOUCH_TOUCH ? GLUT_DOWN : GLUT_UP; + INVOKE_WCB(*window, Mouse, (GLUT_LEFT_BUTTON, glutTouchType, x, y)); + } + } +} + +/* + * Determine a GLUT modifier mask based on BlackBerry modifier info. + */ +int fgPlatformGetModifiers (int mod) +{ + return (((mod & KEYMOD_SHIFT) ? GLUT_ACTIVE_SHIFT : 0) | + ((mod & KEYMOD_CTRL) ? GLUT_ACTIVE_CTRL : 0) | + ((mod & KEYMOD_ALT) ? GLUT_ACTIVE_ALT : 0)); +} + +void fgPlatformHandleKeyboardHeight(SFG_Window* window, int height) +{ + int size[2]; + int screenHeight; + int nScreenHeight = -1; + + screenHeight = glutGet(GLUT_WINDOW_HEIGHT); //Using this takes rotation into account + if(height == 0) { + nScreenHeight = screenHeight; + } + else if(!screen_get_window_property_iv(window->Window.Handle, SCREEN_PROPERTY_POSITION, size)) { + /* Calculate the new screen size */ //XXX Make sure to use display size instead of screen size + nScreenHeight = ((size[1] + screenHeight) - height) - size[1]; + } + + if(nScreenHeight != -1) { + /* If nScreenHeight is less then zero then window is covered. If nScreenHeight == height, then no change in size. Else, change in size */ + + int screenWidth = glutGet(GLUT_WINDOW_WIDTH); + if(nScreenHeight < 0) { + LOGI("fgPlatformHandleKeyboardHeight: Covered window state"); + window->State.Visible = GL_FALSE; + window->State.pWState.windowCovered = GL_TRUE; + INVOKE_WCB(*window, WindowStatus, (GLUT_FULLY_COVERED)); + fghOnReshapeNotify(window, screenWidth, 0, GL_FALSE); + } else { + if(window->State.pWState.windowCovered == GL_TRUE) { + LOGI("fgPlatformHandleKeyboardHeight: Resetting window state"); + + /* Reset window status if it was previously covered */ + switch(window->State.pWState.windowState) { + case NAVIGATOR_WINDOW_FULLSCREEN: + window->State.Visible = GL_TRUE; + INVOKE_WCB(*window, WindowStatus, (GLUT_FULLY_RETAINED)); + break; + case NAVIGATOR_WINDOW_THUMBNAIL: + window->State.Visible = GL_TRUE; + INVOKE_WCB(*window, WindowStatus, (GLUT_PARTIALLY_RETAINED)); + break; + case NAVIGATOR_WINDOW_INVISIBLE: + window->State.Visible = GL_FALSE; + INVOKE_WCB(*window, WindowStatus, (GLUT_HIDDEN)); + break; + } + window->State.pWState.windowCovered = GL_FALSE; + } + fghOnReshapeNotify(window, screenWidth, nScreenHeight, GL_FALSE); + } + } +} + +void fgPlatformProcessSingleEvent ( void ) +{ + if(fgStructure.CurrentWindow == NULL) { + //XXX Is this right? Would this just cause a whole lot of busy looping while we wait for events? + LOGW("fgPlatformProcessSingleEvent: Missing current window. Skipping event processing"); + return; + } + + if(fgDisplay.pDisplay.event == NULL) + /* Nothing to do */ + return; + + int domain; + do + { + SFG_Window* window = fgStructure.CurrentWindow; + /* Get the keyboard height before doing anything since we otherwise don't get it until it changes */ + if(window->State.pWState.keyboardHeight == 0) { + virtualkeyboard_get_height(&window->State.pWState.keyboardHeight); + } + domain = bps_event_get_domain(fgDisplay.pDisplay.event); + if (domain == screen_get_domain()) { + int eventType; + int mod; + screen_event_t screenEvent = screen_event_get_event(fgDisplay.pDisplay.event); + screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_TYPE, &eventType); + switch (eventType) { + + //Mostly from fg_main_android + case SCREEN_EVENT_MTOUCH_TOUCH: + case SCREEN_EVENT_MTOUCH_RELEASE: + case SCREEN_EVENT_MTOUCH_MOVE: + { + mtouch_event_t touchEvent; + screen_get_mtouch_event(screenEvent, &touchEvent, 0); +#ifndef __PLAYBOOK__ + screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_KEY_MODIFIERS, &mod); +#else + mod = 0; +#endif + + LOGI("fgPlatformProcessSingleEvent: SCREEN_EVENT_MTOUCH_*: Type: 0x%X, X: %d, Y: %d, Contact Id: %d, Mod: 0x%X", SLOG2_FA_SIGNED(eventType), SLOG2_FA_SIGNED(touchEvent.x), SLOG2_FA_SIGNED(touchEvent.y), SLOG2_FA_SIGNED(touchEvent.contact_id), SLOG2_FA_SIGNED(mod)); + + /* Remember the current modifiers state so user can query it from their callback */ + fgState.Modifiers = fgPlatformGetModifiers(mod); + + if(touchEvent.contact_id == 0) { + int size[2]; + screen_get_window_property_iv(window->Window.Handle, SCREEN_PROPERTY_BUFFER_SIZE, size); + handle_left_mouse(touchEvent.x, touchEvent.y, size[1], eventType, window); + } + + //Now handle mutlitouch (adapted from fg_main_windows) + if (eventType == SCREEN_EVENT_MTOUCH_TOUCH) { + INVOKE_WCB( *window, MultiEntry, ( touchEvent.contact_id, GLUT_ENTERED ) ); + INVOKE_WCB( *window, MultiButton, ( touchEvent.contact_id, touchEvent.x, touchEvent.y, 0, GLUT_DOWN ) ); + } else if (eventType == SCREEN_EVENT_MTOUCH_MOVE) { + INVOKE_WCB( *window, MultiMotion, ( touchEvent.contact_id, touchEvent.x, touchEvent.y ) ); + //XXX No motion is performed without contact, thus MultiPassive is never used + } else if (eventType == SCREEN_EVENT_MTOUCH_RELEASE) { + INVOKE_WCB( *window, MultiButton, ( touchEvent.contact_id, touchEvent.x, touchEvent.y, 0, GLUT_UP ) ); + INVOKE_WCB( *window, MultiEntry, ( touchEvent.contact_id, GLUT_LEFT ) ); + } + + fgState.Modifiers = INVALID_MODIFIERS; + break; + } + + case SCREEN_EVENT_POINTER: + { + //Based off/part taken from GamePlay3d PlatformBlackBerry + static int mouse_pressed = 0; + int buttons; + int position[2]; + int wheel; + // A move event will be fired unless a button state changed. + bool move = true; + bool left_move = false; + // This is a mouse move event, it is applicable to a device with a usb mouse or simulator. + screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_BUTTONS, &buttons); + screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_SOURCE_POSITION, position); +#ifndef __PLAYBOOK__ + screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_MOUSE_WHEEL, &wheel); + screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_KEY_MODIFIERS, &mod); +#else + wheel = mod = 0; +#endif + int size[2]; + screen_get_window_property_iv(window->Window.Handle, SCREEN_PROPERTY_BUFFER_SIZE, size); + + LOGI("fgPlatformProcessSingleEvent: SCREEN_EVENT_POINTER: Buttons: 0x%X, X: %d, Y: %d, Wheel: %d, Mod: 0x%X", SLOG2_FA_SIGNED(buttons), SLOG2_FA_SIGNED(position[0]), SLOG2_FA_SIGNED(position[1]), SLOG2_FA_SIGNED(wheel), SLOG2_FA_SIGNED(mod)); + + //XXX Is multitouch be handled in a good way? + + /* Remember the current modifiers state so user can query it from their callback */ + fgState.Modifiers = fgPlatformGetModifiers(mod); + + // Handle left mouse. Interpret as touch if the left mouse event is not consumed. + if (buttons & SCREEN_LEFT_MOUSE_BUTTON) { + if (mouse_pressed & SCREEN_LEFT_MOUSE_BUTTON) { + left_move = true; + } else { + move = false; + mouse_pressed |= SCREEN_LEFT_MOUSE_BUTTON; + handle_left_mouse(position[0], position[1], size[1], SCREEN_EVENT_MTOUCH_TOUCH, window); + } + } else if (mouse_pressed & SCREEN_LEFT_MOUSE_BUTTON) { + move = false; + mouse_pressed &= ~SCREEN_LEFT_MOUSE_BUTTON; + handle_left_mouse(position[0], position[1], size[1], SCREEN_EVENT_MTOUCH_RELEASE, window); + } + + // Handle right mouse. + if (buttons & SCREEN_RIGHT_MOUSE_BUTTON) { + if ((mouse_pressed & SCREEN_RIGHT_MOUSE_BUTTON) == 0) { + move = false; + mouse_pressed |= SCREEN_RIGHT_MOUSE_BUTTON; + INVOKE_WCB(*window, Mouse, (GLUT_RIGHT_BUTTON, GLUT_DOWN, position[0], position[1])); + } + } else if (mouse_pressed & SCREEN_RIGHT_MOUSE_BUTTON) { + move = false; + mouse_pressed &= ~SCREEN_RIGHT_MOUSE_BUTTON; + INVOKE_WCB(*window, Mouse, (GLUT_RIGHT_BUTTON, GLUT_UP, position[0], position[1])); + } + + // Handle middle mouse. + if (buttons & SCREEN_MIDDLE_MOUSE_BUTTON) { + if ((mouse_pressed & SCREEN_MIDDLE_MOUSE_BUTTON) == 0) { + move = false; + mouse_pressed |= SCREEN_MIDDLE_MOUSE_BUTTON; + INVOKE_WCB(*window, Mouse, (GLUT_MIDDLE_BUTTON, GLUT_DOWN, position[0], position[1])); + } + } else if (mouse_pressed & SCREEN_MIDDLE_MOUSE_BUTTON) { + move = false; + mouse_pressed &= ~SCREEN_MIDDLE_MOUSE_BUTTON; + INVOKE_WCB(*window, Mouse, (GLUT_MIDDLE_BUTTON, GLUT_UP, position[0], position[1])); + } + + // Fire a move event if none of the buttons changed. + if (left_move || move) { + handle_left_mouse(position[0], position[1], size[1], SCREEN_EVENT_MTOUCH_MOVE, window); + } + + if (wheel) { + /* Very slightly modified from fg_main_mswin. + * Because we don't want MouseWheel to be called every. single. time. + * That the action occurs, we mimic the Windows version with "wheel deltas" + * XXX Do we even want this? + * XXX If we want this, it's possible to get horizontal scroll as well. + * XXX -Vertical scroll=wheel 0, horizontal=wheel 1? */ + fgState.MouseWheelTicks -= wheel; + if (abs(fgState.MouseWheelTicks) >= WHEEL_DELTA) + { + int wheel_number = 0; + int direction = (fgState.MouseWheelTicks > 0) ? -1 : 1; + + if (!FETCH_WCB(*window, MouseWheel) && !FETCH_WCB(*window, Mouse)) + break; + + //XXX fgSetWindow(window); + + while(abs(fgState.MouseWheelTicks) >= WHEEL_DELTA) + { + if (FETCH_WCB(*window, MouseWheel)) + INVOKE_WCB(*window, MouseWheel, (wheel_number, direction, window->State.MouseX, window->State.MouseY)); + else /* No mouse wheel, call the mouse button callback twice */ + { + /* + * Map wheel zero to button 3 and 4; +1 to 3, -1 to 4 + * " " one +1 to 5, -1 to 6, ... + * + * XXX The below assumes that you have no more than 3 mouse + * XXX buttons. Sorry. + */ + int button = wheel_number * 2 + 3; + if (direction < 0) + ++button; + INVOKE_WCB(*window, Mouse, (button, GLUT_DOWN, window->State.MouseX, window->State.MouseY)); + INVOKE_WCB(*window, Mouse, (button, GLUT_UP, window->State.MouseX, window->State.MouseY)); + } + + fgState.MouseWheelTicks -= WHEEL_DELTA * direction; + } + } + } + + fgState.Modifiers = INVALID_MODIFIERS; + break; + } + + //Based off fg_main_android + case SCREEN_EVENT_KEYBOARD: + { + int flags; + int value; + screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_KEY_FLAGS, &flags); + screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_KEY_SYM, &value); + screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_KEY_MODIFIERS, &mod); + + LOGI("fgPlatformProcessSingleEvent: SCREEN_EVENT_KEYBOARD. Flags: 0x%X, Sym: 0x%X, Mod: 0x%X", SLOG2_FA_SIGNED(flags), SLOG2_FA_SIGNED(value), SLOG2_FA_SIGNED(mod)); + + /* Suppress key repeats if desired. Based off fg_main_mswin */ + if ((flags & KEY_REPEAT) == 0 || (fgState.KeyRepeat == GLUT_KEY_REPEAT_OFF && fgStructure.CurrentWindow->State.IgnoreKeyRepeat == GL_TRUE)) { + unsigned int keypress = 0; + unsigned char ascii = 0; + + /* Remember the current modifiers state so user can query it from their callback */ + fgState.Modifiers = fgPlatformGetModifiers(mod); + + /* Process keys */ + if ((keypress = key_special(value))) { + if(flags & KEY_DOWN) { + INVOKE_WCB(*window, Special, (keypress, window->State.MouseX, window->State.MouseY)); + } else { + INVOKE_WCB(*window, SpecialUp, (keypress, window->State.MouseX, window->State.MouseY)); + } + } else if((flags & KEY_SYM_VALID) && (ascii = key_ascii(value))) { + if(flags & KEY_DOWN) { + INVOKE_WCB(*window, Keyboard, (ascii, window->State.MouseX, window->State.MouseY)); + } else { + INVOKE_WCB(*window, KeyboardUp, (ascii, window->State.MouseX, window->State.MouseY)); + } + } else { + LOGW("fgPlatformProcessSingleEvent: SCREEN_EVENT_KEYBOARD. Unhandled key event"); + } + + fgState.Modifiers = INVALID_MODIFIERS; + } + break; + } + + case SCREEN_EVENT_PROPERTY: + case SCREEN_EVENT_IDLE: + break; + + default: + LOGW("fgPlatformProcessSingleEvent: unknown screen event: 0x%X", SLOG2_FA_SIGNED(eventType)); + break; + } + } else if (domain == navigator_get_domain()) { + unsigned int eventType = bps_event_get_code(fgDisplay.pDisplay.event); + switch (eventType) { + + case NAVIGATOR_WINDOW_STATE: + { + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE"); + + /* Covered only happens due to keyboard. When the app is minimized, the keyboard is closed. + When the keyboard is open, and the app is fullscreened, the keyboard is also closed. + If a window is covered and the app is minimized, the state will be set and the keyboard event + will adjust the screen size and change window status. */ + navigator_window_state_t state = navigator_event_get_window_state(fgDisplay.pDisplay.event); + if(window->State.pWState.windowCovered == GL_FALSE) + { + switch (state) + { + case NAVIGATOR_WINDOW_FULLSCREEN: + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE-NAVIGATOR_WINDOW_FULLSCREEN"); + window->State.Visible = GL_TRUE; + INVOKE_WCB(*window, WindowStatus, (GLUT_FULLY_RETAINED)); + break; + case NAVIGATOR_WINDOW_THUMBNAIL: + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE-NAVIGATOR_WINDOW_THUMBNAIL"); + window->State.Visible = GL_TRUE; + INVOKE_WCB(*window, WindowStatus, (GLUT_PARTIALLY_RETAINED)); + break; + case NAVIGATOR_WINDOW_INVISIBLE: + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE-NAVIGATOR_WINDOW_INVISIBLE"); + window->State.Visible = GL_FALSE; + INVOKE_WCB(*window, WindowStatus, (GLUT_HIDDEN)); + break; + default: + LOGW("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE unknown: 0x%X", SLOG2_FA_SIGNED(state)); + break; + } + } + window->State.pWState.windowState = state; + break; + } + + case NAVIGATOR_EXIT: + { + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_EXIT"); + + fgPlatformMainLoopPostWork(); + + /* User closed the application for good, let's kill the window */ + SFG_Window* window = fgStructure.CurrentWindow; + if (window != NULL) { + fgDestroyWindow(window); + } else { + LOGW("NAVIGATOR_EXIT: No current window"); + } + + //XXX Should this be a bit more "forceful" so that it doesn't continue to loop through events? + break; + } + + case NAVIGATOR_SWIPE_DOWN: + /* XXX Open app menu */ + break; + + /* Orientation is a bunch of handshakes. + - First the app get's asked if it wants to rotate (NAVIGATOR_ORIENTATION_CHECK) + - If the app wants to rotate, then it will be told what size it will be after rotate (NAVIGATOR_ORIENTATION_SIZE). + - Once the OS confirms that it's ready to rotate, it tells the app to handle rotation (NAVIGATOR_ORIENTATION). + - Once rotation is complete, the OS tells the app it's done (NAVIGATOR_ORIENTATION_DONE) */ + case NAVIGATOR_ORIENTATION_CHECK: + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_ORIENTATION_CHECK"); + + /* Reset sizes */ + window->State.pWState.newWidth = 0; + window->State.pWState.newHeight = 0; + +#ifdef __PLAYBOOK__ + /* On rotation, the keyboard is closed. This prevents two resize calls */ + window->State.pWState.keyboardOpen = GL_FALSE; +#endif + + /* Notify that we want to rotate */ + navigator_orientation_check_response(fgDisplay.pDisplay.event, true); + break; + + case NAVIGATOR_ORIENTATION: + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_ORIENTATION"); + + /* NAVIGATOR_ORIENTATION occurs before NAVIGATOR_KEYBOARD_POSITION */ + + /* Rotate and resize the window */ + fgPlatformRotateWindow(window, navigator_event_get_orientation_angle(fgDisplay.pDisplay.event)); + fgPlatformFlushCommands(); +#ifdef __PLAYBOOK__ + /* PlayBook doesn't indicate what the new size will be, so we need to retrieve it from the window itself */ + window->State.pWState.newWidth = glutGet(GLUT_WINDOW_WIDTH); + window->State.pWState.newHeight = glutGet(GLUT_WINDOW_HEIGHT); + fghOnReshapeNotify(window, window->State.pWState.newWidth, window->State.pWState.newHeight, GL_FALSE); +#else + if(window->State.pWState.keyboardOpen == GL_FALSE) { + /* On rotation, if the keyboard is open, it will get the keyboard resize events anyway. Otherwise, handle the resize. */ + fghOnReshapeNotify(window, window->State.pWState.newWidth, window->State.pWState.newHeight, GL_FALSE); + } +#endif + + /* Reset sizes */ + window->State.pWState.newWidth = 0; + window->State.pWState.newHeight = 0; + + /* Done rotating */ + navigator_done_orientation(fgDisplay.pDisplay.event); + break; + + case NAVIGATOR_BACK: + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_BACK"); + INVOKE_WCB(*window, Keyboard, (ESCAPE_BUTTON_KEY, window->State.MouseX, window->State.MouseY)); + INVOKE_WCB(*window, KeyboardUp, (ESCAPE_BUTTON_KEY, window->State.MouseX, window->State.MouseY)); + break; + + case NAVIGATOR_WINDOW_ACTIVE: + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_ACTIVE"); + INVOKE_WCB(*window, AppStatus, (GLUT_APPSTATUS_RESUME)); + break; + + case NAVIGATOR_WINDOW_INACTIVE: + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_INACTIVE"); + INVOKE_WCB(*window, AppStatus, (GLUT_APPSTATUS_PAUSE)); + break; + + case NAVIGATOR_ORIENTATION_DONE: + case NAVIGATOR_ORIENTATION_RESULT: + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_ORIENTATION_DONE/NAVIGATOR_ORIENTATION_RESULT"); + break; + +#ifndef __PLAYBOOK__ + case NAVIGATOR_KEYBOARD_STATE: + case NAVIGATOR_KEYBOARD_POSITION: + /* See virtual keyboard handling for info on why this is not used. */ + break; + + case NAVIGATOR_DEVICE_LOCK_STATE: + break; + + case NAVIGATOR_WINDOW_COVER: + case NAVIGATOR_WINDOW_COVER_ENTER: + case NAVIGATOR_WINDOW_COVER_EXIT: + /* BlackBerry specific. Let app status and window status take care of everything */ + break; + + case NAVIGATOR_APP_STATE: + /* Can do the same as NAVIGATOR_WINDOW_ACTIVE/NAVIGATOR_WINDOW_INACTIVE but + seems like it doesn't work when the app comes to the foreground. Might be a bug */ + break; + + case NAVIGATOR_ORIENTATION_SIZE: + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_ORIENTATION_SIZE"); + + /* Get new window size */ + window->State.pWState.newWidth = navigator_event_get_orientation_size_width(fgDisplay.pDisplay.event); + window->State.pWState.newHeight = navigator_event_get_orientation_size_height(fgDisplay.pDisplay.event); + break; +#endif + + case 0: //Doesn't exist in header, but shows up when keyboard shows and resizes + case NAVIGATOR_OTHER: + break; + + default: + LOGW("fgPlatformProcessSingleEvent: unknown navigator event: 0x%X", SLOG2_FA_SIGNED(eventType)); + break; + } + } + /* + * BlackBerry 10 navigator provides keyboard events, but they conflict with how we handle keyboard events. + * Causing multiple reshape messages and can leave window state incorrectly setup. + */ + else if(domain == virtualkeyboard_get_domain()) { + unsigned int eventType = bps_event_get_code(fgDisplay.pDisplay.event); + switch (eventType) { + case VIRTUALKEYBOARD_EVENT_VISIBLE: + LOGI("fgPlatformProcessSingleEvent: VIRTUALKEYBOARD_EVENT_VISIBLE"); + if(window->State.pWState.keyboardOpen != GL_TRUE) { + window->State.pWState.keyboardOpen = GL_TRUE; + fgPlatformHandleKeyboardHeight(window, window->State.pWState.keyboardHeight); + } + break; + + case VIRTUALKEYBOARD_EVENT_HIDDEN: + LOGI("fgPlatformProcessSingleEvent: VIRTUALKEYBOARD_EVENT_HIDDEN"); + if(window->State.pWState.keyboardOpen != GL_FALSE) { + window->State.pWState.keyboardOpen = GL_FALSE; + fgPlatformHandleKeyboardHeight(window, 0); + } + break; + + case VIRTUALKEYBOARD_EVENT_INFO: + LOGI("fgPlatformProcessSingleEvent: VIRTUALKEYBOARD_EVENT_INFO"); + window->State.pWState.keyboardHeight = virtualkeyboard_event_get_height(fgDisplay.pDisplay.event); + if(window->State.pWState.keyboardOpen == GL_TRUE) { + fgPlatformHandleKeyboardHeight(window, window->State.pWState.keyboardHeight); + } + break; + + default: + LOGW("fgPlatformProcessSingleEvent: unknown virtualkeyboard event: 0x%X", eventType); + break; + } + } + } while(bps_get_event(&fgDisplay.pDisplay.event, 1) == BPS_SUCCESS && fgDisplay.pDisplay.event != NULL); + + /* Reset event to reduce chances of triggering something */ + fgDisplay.pDisplay.event = NULL; +} + +void fgPlatformMainLoopPreliminaryWork ( void ) +{ + LOGI("fgPlatformMainLoopPreliminaryWork"); + + /* Request navigator events */ + navigator_request_events(NAVIGATOR_EXTENDED_DATA); + + /* Allow rotation */ + navigator_rotation_lock(false); + + /* Request keyboard events */ + virtualkeyboard_request_events(0); + + /* Request window events */ + screen_request_events(fgDisplay.pDisplay.screenContext); +} + +void fgPlatformMainLoopPostWork ( void ) +{ + LOGI("fgPlatformMainLoopPostWork"); + + /* Stop all events */ + screen_stop_events(fgDisplay.pDisplay.screenContext); + +#ifndef __PLAYBOOK__ + navigator_stop_events(0); +#endif +} + +/* deal with work list items */ +void fgPlatformInitWork(SFG_Window* window) +{ + LOGI("fgPlatformInitWork"); + + /* Position callback, always at 0,0 */ + fghOnPositionNotify(window, 0, 0, GL_TRUE); + + /* Get window size */ + int size[2]; + screen_get_window_property_iv(window->Window.Handle, SCREEN_PROPERTY_BUFFER_SIZE, size); + fghOnReshapeNotify(window, size[0], size[1], GL_FALSE); + + /* Size gets notified on window creation with size detection in mainloop above + * XXX CHECK: does this messages happen too early like on windows, + * so client code cannot have registered a callback yet and the message + * is thus never received by client? + */ +} + +void fgPlatformPosResZordWork(SFG_Window* window, unsigned int workMask) +{ + if (workMask & GLUT_FULL_SCREEN_WORK) + fgPlatformFullScreenToggle( window ); + if (workMask & GLUT_POSITION_WORK) + fgPlatformPositionWindow( window, window->State.DesiredXpos, window->State.DesiredYpos ); + if (workMask & GLUT_SIZE_WORK) + fgPlatformReshapeWindow ( window, window->State.DesiredWidth, window->State.DesiredHeight ); + if (workMask & GLUT_ZORDER_WORK) + { + if (window->State.DesiredZOrder < 0) + fgPlatformPushWindow( window ); + else + fgPlatformPopWindow( window ); + } +} + +void fgPlatformVisibilityWork(SFG_Window* window) +{ + /* Visibility status of window should get updated in the window message handlers + * For now, none of these functions called below do anything, so don't worry + * about it + */ + SFG_Window *win = window; + switch (window->State.DesiredVisibility) + { + case DesireHiddenState: + fgPlatformHideWindow( window ); + break; + case DesireIconicState: + /* Call on top-level window */ + while (win->Parent) + win = win->Parent; + fgPlatformIconifyWindow( win ); + break; + case DesireNormalState: + fgPlatformShowWindow( window ); + break; + } +} + +/* dummy functions, not applicable on blackberry */ +void fgPlatformSetColor(int idx, float r, float g, float b) +{ +} + +float fgPlatformGetColor(int idx, int comp) +{ +} + +void fgPlatformCopyColormap(int win) +{ +} diff --git a/src/blackberry/fg_state_blackberry.c b/src/blackberry/fg_state_blackberry.c new file mode 100644 index 0000000..246ba04 --- /dev/null +++ b/src/blackberry/fg_state_blackberry.c @@ -0,0 +1,144 @@ +/* + * fg_state_blackberry.c + * + * BlackBerry-specific freeglut state query methods. + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by John F. Fay, + * Copyright (C) 2012 Sylvain Beucler + * Copyright (C) 2013 Vincent Simonetti + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include "fg_internal.h" +#include "egl/fg_state_egl.h" + +//From fg_state_android.c +int fgPlatformGlutDeviceGet ( GLenum eWhat ) +{ +#ifndef __PLAYBOOK__ + int deviceCount, i, value; + screen_device_t* devices; +#endif + + switch( eWhat ) + { + case GLUT_HAS_KEYBOARD: + /* BlackBerry has a keyboard, though it may be virtual. */ + return 1; + + case GLUT_HAS_MOUSE: + /* BlackBerry has a touchscreen. Consider it as a mouse since we have no guarantee + that a mouse will be used (in which case it's a simulator). */ + return 1 ; + + case GLUT_NUM_MOUSE_BUTTONS: + /* BlackBerry has a touchscreen, which we can consider a 1-button mouse at min. + Otherwise check for an actual mouse, else get max touch points. PlayBook does not support this. */ +#ifndef __PLAYBOOK__ + if(!screen_get_context_property_iv(fgDisplay.pDisplay.screenContext, SCREEN_PROPERTY_DEVICE_COUNT, &deviceCount)) { + devices = (screen_device_t*)calloc(deviceCount, sizeof(screen_device_t)); + if(!screen_get_context_property_pv(fgDisplay.pDisplay.screenContext, SCREEN_PROPERTY_DEVICES, (void**)devices)) { + /* Check for a pointer */ + for(i = 0; i < deviceCount; i++) { + if(!screen_get_device_property_iv(devices[i], SCREEN_PROPERTY_TYPE, &value) && + value == SCREEN_EVENT_POINTER && + !screen_get_device_property_iv(devices[i], SCREEN_PROPERTY_BUTTON_COUNT, &value)) { + free(devices); + return value; + } + } + /* Check for mtouch */ + for(i = 0; i < deviceCount; i++) { + if(!screen_get_device_property_iv(devices[i], SCREEN_PROPERTY_TYPE, &value) && + value == SCREEN_EVENT_MTOUCH_TOUCH && + !screen_get_device_property_iv(devices[i], SCREEN_PROPERTY_MAXIMUM_TOUCH_ID, &value)) { + free(devices); + return value; + } + } + } + free(devices); + } +#endif + /* Backup, pretend it's a 1-button mouse */ + return 1; + + default: + fgWarning( "glutDeviceGet(): missing enum handle %d", eWhat ); + break; + } + + /* And now -- the failure. */ + return -1; +} + +int fgPlatformGlutGet ( GLenum eWhat ) +{ + switch (eWhat) { + /* One full-screen window only */ + case GLUT_WINDOW_X: + case GLUT_WINDOW_Y: + case GLUT_WINDOW_BORDER_WIDTH: + case GLUT_WINDOW_HEADER_HEIGHT: + return 0; + + case GLUT_WINDOW_WIDTH: + case GLUT_WINDOW_HEIGHT: + { + if ( fgStructure.CurrentWindow == NULL ) + return 0; + + int size[2]; + int orientation; + if ( screen_get_window_property_iv(fgStructure.CurrentWindow->Window.Handle, SCREEN_PROPERTY_BUFFER_SIZE, size) != 0 ) + return 0; + if ( screen_get_window_property_iv(fgStructure.CurrentWindow->Window.Handle, SCREEN_PROPERTY_ROTATION, &orientation) != 0 ) + return 0; + + int orientationDif = abs(orientation - fgStructure.CurrentWindow->State.pWState.originalRotation); + if (orientationDif == 90 || orientationDif == 270) { + /* Swap dim. if screen is rotated */ + int tmp = size[0]; + size[0] = size[1]; + size[1] = tmp; + } + switch ( eWhat ) + { + case GLUT_WINDOW_WIDTH: + return size[0]; + case GLUT_WINDOW_HEIGHT: + return size[1]; + } + break; + } + + case GLUT_WINDOW_COLORMAP_SIZE: + /* 0 for RGBA/non-indexed mode */ + /* Under BlackBerry and GLES more generally, no indexed-mode */ + return 0; + + default: + return fghPlatformGlutGetEGL(eWhat); + } + return -1; +} diff --git a/src/blackberry/fg_structure_blackberry.c b/src/blackberry/fg_structure_blackberry.c new file mode 100644 index 0000000..d6eab8f --- /dev/null +++ b/src/blackberry/fg_structure_blackberry.c @@ -0,0 +1,43 @@ +/* + * fg_structure_blackberry.c + * + * Windows and menus need tree structure + * + * Copyright (C) 2012 Sylvain Beucler + * Copyright (C) 2013 Vincent Simonetti + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" +#include "egl/fg_structure_egl.h" + +/** + * Initialize default platform-specific fields in SFG_Window + */ +void fgPlatformCreateWindow ( SFG_Window *window ) +{ + fghPlatformCreateWindowEGL(window); + + memset(&(window->State.pWState), 0, sizeof(SFG_PlatformWindowState)); + window->State.pWState.windowCovered = GL_FALSE; +#ifdef __PLAYBOOK__ + window->State.pWState.keyboardOpen = GL_FALSE; +#endif +} diff --git a/src/blackberry/fg_window_blackberry.c b/src/blackberry/fg_window_blackberry.c new file mode 100644 index 0000000..86668af --- /dev/null +++ b/src/blackberry/fg_window_blackberry.c @@ -0,0 +1,327 @@ +/* + * fg_window_blackberry.c + * + * Window management methods for BlackBerry + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Copied for Platform code by Evan Felix + * Copyright (C) 2012 Sylvain Beucler + * Copyright (C) 2013 Vincent Simonetti + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#define FREEGLUT_BUILDING_LIB +#include +#include "fg_internal.h" +#include "egl/fg_window_egl.h" +#include + +/* + * Opens a window. Requires a SFG_Window object created and attached + * to the freeglut structure. OpenGL context is created here. + */ +void fgPlatformOpenWindow( SFG_Window* window, const char* title, + GLboolean positionUse, int x, int y, + GLboolean sizeUse, int w, int h, + GLboolean gameMode, GLboolean isSubWindow ) +{ + /* TODO: only one full-screen window possible? */ + if (fgDisplay.pDisplay.single_native_window != NULL) { + fgWarning("You can't have more than one window on BlackBerry"); + return; + } + + /* Create window */ + screen_window_t sWindow; + if (screen_create_window(&sWindow, fgDisplay.pDisplay.screenContext)) { + fgError("Could not create window"); + return; + } + fgDisplay.pDisplay.single_native_window = sWindow; + + /* Choose config and screen format */ + fghChooseConfig(&window->Window.pContext.egl.Config); + int screenFormat = SCREEN_FORMAT_RGBA8888; //Only SCREEN_FORMAT_RGBA8888 and SCREEN_FORMAT_RGB565 are supported. See fg_window_egl for more info + int configAttri; +#define EGL_QUERY_COMP(att, comp) (eglGetConfigAttrib(fgDisplay.pDisplay.egl.Display, window->Window.pContext.egl.Config, att, &configAttri) == GL_TRUE && (configAttri comp)) + if (EGL_QUERY_COMP(EGL_ALPHA_SIZE, <= 0) && EGL_QUERY_COMP(EGL_RED_SIZE, <= 5) && + EGL_QUERY_COMP(EGL_GREEN_SIZE, <= 6) && EGL_QUERY_COMP(EGL_BLUE_SIZE, <= 5)) { + screenFormat = SCREEN_FORMAT_RGB565; + } +#undef EGL_QUERY_COMP + + /* Set window properties */ + int orientation = atoi(getenv("ORIENTATION")); + int screenUsage = SCREEN_USAGE_ROTATION; +#ifdef SCREEN_USAGE_OPENGL_ES3 + if (fgState.MajorVersion >= 3) { + screenUsage |= SCREEN_USAGE_OPENGL_ES3; + } else +#endif + if (fgState.MajorVersion >= 2) { + screenUsage |= SCREEN_USAGE_OPENGL_ES2; + } else { + screenUsage |= SCREEN_USAGE_OPENGL_ES1; + } +#if !defined(__X86__) && !defined(__PLAYBOOK__) + screenUsage |= SCREEN_USAGE_DISPLAY; // Physical device copy directly into physical display +#endif + if (screen_set_window_property_iv(sWindow, SCREEN_PROPERTY_FORMAT, &screenFormat)) { + screen_destroy_window(sWindow); + fgError("Could not set window format"); + return; + } + if (screen_set_window_property_iv(sWindow, SCREEN_PROPERTY_USAGE, &screenUsage)) { + screen_destroy_window(sWindow); + fgError("Could not set window usage"); + return; + } + + int value[2]; + /* Uncomment when multiple windows are supported + if(positionUse) { + value[0] = x; + value[1] = y; + if (screen_set_window_property_iv(sWindow, SCREEN_PROPERTY_POSITION, value)) { + screen_destroy_window(sWindow); + fgError("Could not set window position"); + return; + } + }*/ + + if(sizeUse) { + /* Uncomment when multiple windows are supported + value[0] = w; + value[1] = h; + */ + //TEMP until ^^ is uncommented + if (screen_get_window_property_iv(sWindow, SCREEN_PROPERTY_BUFFER_SIZE, value)) { + screen_destroy_window(sWindow); + fgError("Could not get window mode"); + return; + } + } else { + /* From PlatformBlackBerry in GamePlay3d */ + screen_display_t display; + if (screen_get_window_property_pv(sWindow, SCREEN_PROPERTY_DISPLAY, (void**)&display)) { + screen_destroy_window(sWindow); + fgError("Could not get window display"); + return; + } + + screen_display_mode_t displayMode; + if (screen_get_display_property_pv(display, SCREEN_PROPERTY_MODE, (void**)&displayMode)) { + screen_destroy_window(sWindow); + fgError("Could not get display mode"); + return; + } + + if (screen_get_window_property_iv(sWindow, SCREEN_PROPERTY_BUFFER_SIZE, value)) { + screen_destroy_window(sWindow); + fgError("Could not get window mode"); + return; + } + + /* Adjust buffer sizes based on rotation */ + if ((orientation == 0) || (orientation == 180)) + { + if (((displayMode.width > displayMode.height) && (value[0] < value[1])) || + ((displayMode.width < displayMode.height) && (value[0] > value[1]))) + { + int tmp = value[1]; + value[1] = value[0]; + value[0] = tmp; + } + } + else if ((orientation == 90) || (orientation == 270)) + { + if (((displayMode.width > displayMode.height) && (value[0] > value[1])) || + ((displayMode.width < displayMode.height) && (value[0] < value[1]))) + { + int tmp = value[1]; + value[1] = value[0]; + value[0] = tmp; + } + } + else + { + screen_destroy_window(sWindow); + fgError("Unexpected rotation angle"); + return; + } + } + + /* Set rotation if usage allows it */ + if (screen_set_window_property_iv(sWindow, SCREEN_PROPERTY_ROTATION, &orientation)) { + screen_destroy_window(sWindow); + fgError("Could not set window rotation"); + return; + } + window->State.pWState.originalRotation = orientation; + + /* Set buffer sizes */ + if (screen_set_window_property_iv(sWindow, SCREEN_PROPERTY_BUFFER_SIZE, value)) { + screen_destroy_window(sWindow); + fgError("Could not set window buffer size"); + return; + } + + /* Create window buffers */ + if (screen_create_window_buffers(sWindow, (fgState.DisplayMode & GLUT_DOUBLE) ? 2 : 1)) { + screen_destroy_window(sWindow); + fgError("Could not create window buffers"); + return; + } + + /* Save window and set state */ + window->Window.Handle = sWindow; + window->State.WorkMask |= GLUT_INIT_WORK; + window->State.IsFullscreen = GL_TRUE; //XXX Always fullscreen for now + + /* Create context */ + window->Window.Context = EGL_NO_CONTEXT; + if( fgState.UseCurrentContext == GL_TRUE ) + window->Window.Context = eglGetCurrentContext(); + if( window->Window.Context == EGL_NO_CONTEXT ) + window->Window.Context = fghCreateNewContextEGL(window); + + /* Create EGL window */ + fghPlatformOpenWindowEGL(window); + + window->State.Visible = GL_TRUE; +} + +void fgPlatformFlushCommands() +{ + if(screen_flush_context(fgDisplay.pDisplay.screenContext, 0)) { + fgWarning("Could not flush screen context"); + } +} + +void fgPlatformRotateWindow(SFG_Window* window, int rotation) +{ + if(screen_set_window_property_iv(window->Window.Handle, SCREEN_PROPERTY_ROTATION, &rotation)) { + fgWarning("Could not set window rotation"); + } +} + +/* + * Request a window resize + */ +void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height ) +{ + fprintf(stderr, "fgPlatformReshapeWindow: STUB\n"); +} + +/* + * Closes a window, destroying the frame and OpenGL context + */ +void fgPlatformCloseWindow( SFG_Window* window ) +{ + fghPlatformCloseWindowEGL(window); + + screen_destroy_window((screen_window_t)window->Window.Handle); +} + +/* + * This function makes the specified window visible + */ +void fgPlatformShowWindow( void ) +{ + fprintf(stderr, "fgPlatformShowWindow: STUB\n"); +} + +/* + * This function hides the specified window + */ +void fgPlatformHideWindow( SFG_Window *window ) +{ + fprintf(stderr, "fgPlatformHideWindow: STUB\n"); +} + +/* + * Iconify the specified window (top-level windows only) + */ +void fgPlatformIconifyWindow( SFG_Window *window ) +{ +#ifndef __PLAYBOOK__ + pps_encoder_t encoder; + + pps_encoder_initialize(&encoder, false); + pps_encoder_add_string(&encoder, "msg", "minimizeWindow"); + + if (navigator_raw_write(pps_encoder_buffer(&encoder), pps_encoder_length(&encoder)) != BPS_SUCCESS) { + fgWarning("Could not iconify window on BlackBerry"); + } + + pps_encoder_cleanup(&encoder); +#else + fprintf(stderr, "fgPlatformGlutIconifyWindow: STUB\n"); +#endif +} + +/* + * Set the current window's title + */ +void fgPlatformGlutSetWindowTitle( const char* title ) +{ + fprintf(stderr, "fgPlatformGlutSetWindowTitle: STUB\n"); +} + +/* + * Set the current window's iconified title + */ +void fgPlatformGlutSetIconTitle( const char* title ) +{ + //XXX Possibly a window cover label? + fprintf(stderr, "fgPlatformGlutSetIconTitle: STUB\n"); +} + +/* + * Change the specified window's position + */ +void fgPlatformPositionWindow( SFG_Window *window, int x, int y ) +{ + fprintf(stderr, "fgPlatformPositionWindow: STUB\n"); +} + +/* + * Lowers the specified window (by Z order change) + */ +void fgPlatformPushWindow( SFG_Window *window ) +{ + fprintf(stderr, "fgPlatformPushWindow: STUB\n"); +} + +/* + * Raises the specified window (by Z order change) + */ +void fgPlatformPopWindow( SFG_Window *window ) +{ + fprintf(stderr, "fgPlatformPopWindow: STUB\n"); +} + +/* + * Toggle the window's full screen state. + */ +void fgPlatformFullScreenToggle( SFG_Window *win ) +{ + fprintf(stderr, "fgPlatformFullScreenToggle: STUB\n"); +} diff --git a/src/egl/fg_display_egl.c b/src/egl/fg_display_egl.c new file mode 100644 index 0000000..f094221 --- /dev/null +++ b/src/egl/fg_display_egl.c @@ -0,0 +1,33 @@ +/* + * fg_display_android.c + * + * Display message posting, context buffer swapping. + * + * Copyright (C) 2012 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" + +void fgPlatformGlutSwapBuffers( SFG_PlatformDisplay *pDisplayPtr, SFG_Window* CurrentWindow ) +{ + if (!eglSwapBuffers(pDisplayPtr->egl.Display, CurrentWindow->Window.pContext.egl.Surface)) + fgError("eglSwapBuffers: error %x\n", eglGetError()); +} diff --git a/src/egl/fg_ext_egl.c b/src/egl/fg_ext_egl.c new file mode 100644 index 0000000..417f6ed --- /dev/null +++ b/src/egl/fg_ext_egl.c @@ -0,0 +1,32 @@ +/* + * fg_ext_egl.c + * + * Functions related to OpenGL extensions. + * + * Copyright (c) 2012 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "../fg_internal.h" + +SFG_Proc fgPlatformGetProcAddress( const char *procName ) +{ + return (SFG_Proc)eglGetProcAddress(procName); +} diff --git a/src/egl/fg_init_egl.c b/src/egl/fg_init_egl.c new file mode 100644 index 0000000..3c83fb2 --- /dev/null +++ b/src/egl/fg_init_egl.c @@ -0,0 +1,79 @@ +/* + * fg_init_egl.c + * + * Various freeglut initialization functions. + * + * Copyright (C) 2012 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#define FREEGLUT_BUILDING_LIB +#include +#include "fg_internal.h" + +/* + * A call to this function should initialize all the display stuff... + */ +void fghPlatformInitializeEGL() +{ + /* CreateDisplay */ + /* Using EGL_DEFAULT_DISPLAY, or a specific native display */ +#ifdef FREEGLUT_WAYLAND + fgDisplay.pDisplay.egl.Display = eglGetDisplay( + (EGLNativeDisplayType)fgDisplay.pDisplay.display); +#else + EGLNativeDisplayType nativeDisplay = EGL_DEFAULT_DISPLAY; + fgDisplay.pDisplay.egl.Display = eglGetDisplay(nativeDisplay); +#endif + + FREEGLUT_INTERNAL_ERROR_EXIT(fgDisplay.pDisplay.egl.Display != EGL_NO_DISPLAY, + "No display available", "fgPlatformInitialize"); + if (eglInitialize(fgDisplay.pDisplay.egl.Display, &fgDisplay.pDisplay.egl.MajorVersion, &fgDisplay.pDisplay.egl.MinorVersion) != EGL_TRUE) + fgError("eglInitialize: error %x\n", eglGetError()); + +# ifdef GL_VERSION_1_1 /* or later */ + eglBindAPI(EGL_OPENGL_API); +# else + eglBindAPI(EGL_OPENGL_ES_API); +# endif + + /* fgDisplay.ScreenWidth = ...; */ + /* fgDisplay.ScreenHeight = ...; */ + /* fgDisplay.ScreenWidthMM = ...; */ + /* fgDisplay.ScreenHeightMM = ...; */ +} + +void fghPlatformCloseDisplayEGL() +{ + if (fgDisplay.pDisplay.egl.Display != EGL_NO_DISPLAY) { + eglTerminate(fgDisplay.pDisplay.egl.Display); + fgDisplay.pDisplay.egl.Display = EGL_NO_DISPLAY; + fgDisplay.pDisplay.egl.MajorVersion = 0; + fgDisplay.pDisplay.egl.MinorVersion = 0; + } +} + +/** + * Destroy a menu context + */ +void fgPlatformDestroyContext ( SFG_PlatformDisplay pDisplay, SFG_WindowContextType MContext ) +{ + if (MContext != EGL_NO_CONTEXT) + eglDestroyContext(pDisplay.egl.Display, MContext); +} diff --git a/src/egl/fg_init_egl.h b/src/egl/fg_init_egl.h new file mode 100644 index 0000000..592c522 --- /dev/null +++ b/src/egl/fg_init_egl.h @@ -0,0 +1,33 @@ +/* + * fg_init_egl.h + * + * Various freeglut initialization functions. + * + * Copyright (C) 2012 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __FG_INIT_EGL_H__ +#define __FG_INIT_EGL_H__ + +extern void fghPlatformInitializeEGL(); +extern void fghPlatformCloseDisplayEGL(); +extern void fgPlatformDestroyContext(); + +#endif diff --git a/src/egl/fg_internal_egl.h b/src/egl/fg_internal_egl.h new file mode 100644 index 0000000..01b3a38 --- /dev/null +++ b/src/egl/fg_internal_egl.h @@ -0,0 +1,56 @@ +/* + * fg_internal_android.h + * + * The freeglut library private include file. + * + * Copyright (C) 2012 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef FREEGLUT_INTERNAL_EGL_H +#define FREEGLUT_INTERNAL_EGL_H + +#include + +/* -- GLOBAL TYPE DEFINITIONS ---------------------------------------------- */ +/* The structure used by display initialization in fg_init.c */ +struct tagSFG_Window; +struct tagSFG_PlatformDisplayEGL +{ + /* Used to initialize and deinitialize EGL */ + EGLDisplay Display; + EGLint MajorVersion; + EGLint MinorVersion; +}; + + +/* + * Make "freeglut" window handle and context types so that we don't need so + * much conditionally-compiled code later in the library. + */ +typedef EGLNativeWindowType SFG_WindowHandleType; +typedef EGLContext SFG_WindowContextType; +typedef int SFG_WindowColormapType; /* dummy */ +struct tagSFG_PlatformContextEGL +{ + EGLSurface Surface; + EGLConfig Config; +}; + +#endif diff --git a/src/egl/fg_state_egl.c b/src/egl/fg_state_egl.c new file mode 100644 index 0000000..cea0405 --- /dev/null +++ b/src/egl/fg_state_egl.c @@ -0,0 +1,172 @@ +/* + * fg_state_egl.c + * + * EGL-specific freeglut state query methods. + * + * Copyright (C) 2012 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" +#include "egl/fg_window_egl.h" + +/* + * Queries the GL context about some attributes + */ +static int fgPlatformGetConfig( int attribute ) +{ + int returnValue = 0; + int result __fg_unused; /* Not checked */ + + if( fgStructure.CurrentWindow ) + result = eglGetConfigAttrib( fgDisplay.pDisplay.egl.Display, + fgStructure.CurrentWindow->Window.pContext.egl.Config, + attribute, + &returnValue ); + + return returnValue; +} + +int fghPlatformGlutGetEGL ( GLenum eWhat ) +{ + int nsamples = 0; + + switch( eWhat ) + { + /* + * The window/context specific queries are handled mostly by + * fgPlatformGetConfig(). + */ + case GLUT_WINDOW_NUM_SAMPLES: + glGetIntegerv(GL_SAMPLES, &nsamples); + return nsamples; + + /* + * The rest of GLX queries under X are general enough to use a macro to + * check them + */ +# define EGL_QUERY(a,b) case a: return fgPlatformGetConfig( b ); + + EGL_QUERY( GLUT_WINDOW_BUFFER_SIZE, EGL_BUFFER_SIZE ); + EGL_QUERY( GLUT_WINDOW_STENCIL_SIZE, EGL_STENCIL_SIZE ); + EGL_QUERY( GLUT_WINDOW_DEPTH_SIZE, EGL_DEPTH_SIZE ); + EGL_QUERY( GLUT_WINDOW_RED_SIZE, EGL_RED_SIZE ); + EGL_QUERY( GLUT_WINDOW_GREEN_SIZE, EGL_GREEN_SIZE ); + EGL_QUERY( GLUT_WINDOW_BLUE_SIZE, EGL_BLUE_SIZE ); + EGL_QUERY( GLUT_WINDOW_ALPHA_SIZE, EGL_ALPHA_SIZE ); + +# undef EGL_QUERY + + /* I do not know yet if there will be a fgChooseVisual() function for Win32 */ + case GLUT_DISPLAY_MODE_POSSIBLE: + { + /* We should not have to call fghChooseConfig again here. */ + EGLConfig config; + return fghChooseConfig(&config); + } + + /* This is system-dependent */ + case GLUT_WINDOW_FORMAT_ID: + if( fgStructure.CurrentWindow == NULL ) + return 0; + return fgPlatformGetConfig( EGL_NATIVE_VISUAL_ID ); + + case GLUT_WINDOW_DOUBLEBUFFER: + return 1; /* EGL is always double-buffered */ + + default: + fgWarning( "glutGet(): missing enum handle %d", eWhat ); + break; + } + + return -1; +} + +int* fgPlatformGlutGetModeValues(GLenum eWhat, int *size) +{ + int *array; + + int attributes[9]; + int attribute_name = 0; + + array = NULL; + *size = 0; + + switch (eWhat) + { + case GLUT_AUX: + break; + + case GLUT_MULTISAMPLE: + attributes[0] = EGL_BUFFER_SIZE; + attributes[1] = EGL_DONT_CARE; + attributes[2] = EGL_SAMPLE_BUFFERS; + attributes[3] = 1; + attributes[4] = EGL_SAMPLES; + attributes[5] = 1; + attributes[6] = EGL_NONE; + + attribute_name = EGL_SAMPLES; + + EGLConfig* configArray; + EGLint configArraySize = 0; + + /* Get number of available configs */ + if (!eglChooseConfig(fgDisplay.pDisplay.egl.Display, + attributes, NULL, 0, + &configArraySize)) + break; + configArray = calloc(configArraySize, sizeof(EGLConfig)); + + if (!eglChooseConfig(fgDisplay.pDisplay.egl.Display, + attributes, configArray, configArraySize, + &configArraySize)) + break; + + /* We get results in ascending order */ + { + int previous_value = 0; + int i; + + array = malloc(sizeof(int) * configArraySize); + + for (i = 0; i < configArraySize; i++) { + int value = 0; + eglGetConfigAttrib(fgDisplay.pDisplay.egl.Display, + configArray[i], attribute_name, &value); + if (value > previous_value) + { + previous_value = value; + array[*size] = value; + (*size)++; + } + } + + array = realloc(array, sizeof(int) * (*size)); + } + free(configArray); + break; + + default: + break; + } + + return array; +} diff --git a/src/egl/fg_state_egl.h b/src/egl/fg_state_egl.h new file mode 100644 index 0000000..bdb93c5 --- /dev/null +++ b/src/egl/fg_state_egl.h @@ -0,0 +1,33 @@ +/* + * fg_state_egl.c + * + * EGL-specific freeglut state query methods. + * + * Copyright (C) 2012 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __FG_STATE_EGL_H__ +#define __FG_STATE_EGL_H__ + +#include +#include "fg_internal.h" +int fghPlatformGlutGetEGL(GLenum eWhat); + +#endif diff --git a/src/egl/fg_structure_egl.c b/src/egl/fg_structure_egl.c new file mode 100644 index 0000000..135f049 --- /dev/null +++ b/src/egl/fg_structure_egl.c @@ -0,0 +1,36 @@ +/* + * fg_structure_egl.c + * + * Windows and menus need tree structure + * + * Copyright (C) 2012 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" + +/** + * Initialize default platform-specific fields in SFG_Window + */ +void fghPlatformCreateWindowEGL ( SFG_Window *window ) +{ + window->Window.pContext.egl.Surface = EGL_NO_SURFACE; + window->Window.pContext.egl.Config = NULL; +} diff --git a/src/egl/fg_structure_egl.h b/src/egl/fg_structure_egl.h new file mode 100644 index 0000000..45703be --- /dev/null +++ b/src/egl/fg_structure_egl.h @@ -0,0 +1,31 @@ +/* + * fg_structure_egl.h + * + * Windows and menus need tree structure + * + * Copyright (C) 2012 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __FG_STRUCTURE_EGL_H__ +#define __FG_STRUCTURE_EGL_H__ + +extern void fghPlatformCreateWindowEGL ( SFG_Window *window ); + +#endif diff --git a/src/egl/fg_window_egl.c b/src/egl/fg_window_egl.c new file mode 100644 index 0000000..b7a76d6 --- /dev/null +++ b/src/egl/fg_window_egl.c @@ -0,0 +1,191 @@ +/* + * fg_display_android.c + * + * Window management methods for EGL + * + * Copyright (C) 2012, 2014 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" + +int fghChooseConfig(EGLConfig* config) { + EGLint num_config; + EGLint attributes[32]; + int where = 0; + ATTRIB_VAL(EGL_SURFACE_TYPE, EGL_WINDOW_BIT); +#ifdef EGL_OPENGL_ES3_BIT + if (fgDisplay.pDisplay.egl.MinorVersion >= 5 && fgState.MajorVersion >= 3) { + ATTRIB_VAL(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT); + } else +#endif + if (fgState.MajorVersion >= 2) { + /* + * Khronos does not specify a EGL_OPENGL_ES3_BIT outside of the OpenGL extension "EGL_KHR_create_context" and EGL 1.5. There are numerous references on the internet + * that say to use EGL_OPENGL_ES3_BIT (pre-EGL 1.5), followed by many saying they can't find it in any headers. In fact, the official updated specification for EGL + * does not have any references to OpenGL ES 3.x. Tests have shown that EGL_OPENGL_ES2_BIT will work with ES 3.x. + */ + ATTRIB_VAL(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT); + } else { + ATTRIB_VAL(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT); + } + /* Technically it's possible to request a standard OpenGL (non-ES) + context, but currently our build system assumes EGL => GLES */ + /* attribs[i++] = EGL_RENDERABLE_TYPE; */ + /* attribs[i++] = EGL_OPENGL_BIT; */ +#ifdef TARGET_HOST_BLACKBERRY + /* Only 888 and 565 seem to work. Based on + http://qt.gitorious.org/qt/qtbase/source/893deb1a93021cdfabe038cdf1869de33a60cbc9:src/plugins/platforms/qnx/qqnxglcontext.cpp and + https://twitter.com/BlackBerryDev/status/380720927475912706 */ + ATTRIB_VAL(EGL_BLUE_SIZE, 8); + ATTRIB_VAL(EGL_GREEN_SIZE, 8); + ATTRIB_VAL(EGL_RED_SIZE, 8); +#else + ATTRIB_VAL(EGL_BLUE_SIZE, 1); + ATTRIB_VAL(EGL_GREEN_SIZE, 1); + ATTRIB_VAL(EGL_RED_SIZE, 1); +#endif + ATTRIB_VAL(EGL_ALPHA_SIZE, (fgState.DisplayMode & GLUT_ALPHA) ? 1 : 0); + ATTRIB_VAL(EGL_DEPTH_SIZE, (fgState.DisplayMode & GLUT_DEPTH) ? 1 : 0); + ATTRIB_VAL(EGL_STENCIL_SIZE, (fgState.DisplayMode & GLUT_STENCIL) ? 1 : 0); + ATTRIB_VAL(EGL_SAMPLE_BUFFERS, (fgState.DisplayMode & GLUT_MULTISAMPLE) ? 1 : 0); + ATTRIB_VAL(EGL_SAMPLES, (fgState.DisplayMode & GLUT_MULTISAMPLE) ? fgState.SampleNumber : 0); + ATTRIB(EGL_NONE); + + if (!eglChooseConfig(fgDisplay.pDisplay.egl.Display, + attributes, config, 1, &num_config)) { + fgWarning("eglChooseConfig: error %x\n", eglGetError()); + return 0; + } + + return 1; +} + +/** + * Initialize an EGL context for the current display. + */ +EGLContext fghCreateNewContextEGL( SFG_Window* window ) { + EGLContext context; + EGLint ver = -1; + + EGLDisplay eglDisplay = fgDisplay.pDisplay.egl.Display; + EGLConfig eglConfig = window->Window.pContext.egl.Config; + + /* On GLES, user specifies the target version with glutInitContextVersion */ + EGLint attributes[32]; + int where = 0; + ATTRIB_VAL(EGL_CONTEXT_CLIENT_VERSION, fgState.MajorVersion); +#ifdef EGL_CONTEXT_MINOR_VERSION + if (fgDisplay.pDisplay.egl.MinorVersion >= 5) { + /* EGL_CONTEXT_CLIENT_VERSION == EGL_CONTEXT_MAJOR_VERSION */ + ATTRIB_VAL(EGL_CONTEXT_MINOR_VERSION, fgState.MinorVersion); + } +#endif + ATTRIB(EGL_NONE); + + context = eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, attributes); + if (context == EGL_NO_CONTEXT) { + fgWarning("Cannot initialize EGL context, err=%x\n", eglGetError()); + fghContextCreationError(); + } + + eglQueryContext(fgDisplay.pDisplay.egl.Display, context, EGL_CONTEXT_CLIENT_VERSION, &ver); + if (ver < fgState.MajorVersion) { + fgError("Wrong GLES major version: %d\n", ver); + } +#ifdef EGL_CONTEXT_MINOR_VERSION + if (fgDisplay.pDisplay.egl.MinorVersion >= 5) { + eglQueryContext(fgDisplay.pDisplay.egl.Display, context, EGL_CONTEXT_MINOR_VERSION, &ver); + if (ver < fgState.MinorVersion) { + fgError("Wrong GLES minor version: %d\n", ver); + } + } +#endif + + return context; +} + +void fgPlatformSetWindow ( SFG_Window *window ) +{ + if ( window != fgStructure.CurrentWindow && window) { + if (eglMakeCurrent(fgDisplay.pDisplay.egl.Display, + window->Window.pContext.egl.Surface, + window->Window.pContext.egl.Surface, + window->Window.Context) == EGL_FALSE) + fgError("eglMakeCurrent: err=%x\n", eglGetError()); + } +} + +/* + * Really opens a window when handle is available + */ +void fghPlatformOpenWindowEGL( SFG_Window* window ) +{ + EGLDisplay display = fgDisplay.pDisplay.egl.Display; + EGLConfig config = window->Window.pContext.egl.Config; + + EGLSurface surface = eglCreateWindowSurface(display, config, window->Window.Handle, NULL); + if (surface == EGL_NO_SURFACE) + fgError("Cannot create EGL window surface, err=%x\n", eglGetError()); + window->Window.pContext.egl.Surface = surface; + + fgPlatformSetWindow(window); + + /* EGLint w, h; */ + /* eglQuerySurface(display, surface, EGL_WIDTH, &w); */ + /* eglQuerySurface(display, surface, EGL_HEIGHT, &h); */ + +} + +/* + * Closes a window, destroying the frame and OpenGL context + */ +void fghPlatformCloseWindowEGL( SFG_Window* window ) +{ + /* Based on fg_window_mswin fgPlatformCloseWindow */ + if( fgStructure.CurrentWindow == window ) + eglMakeCurrent(fgDisplay.pDisplay.egl.Display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + + if (window->Window.Context != EGL_NO_CONTEXT) { + /* Step through the list of windows. If the rendering context is not being used by another window, then delete it */ + { + GLboolean used = GL_FALSE; + SFG_Window *iter; + + for( iter = (SFG_Window*)fgStructure.Windows.First; + iter && used == GL_FALSE; + iter = (SFG_Window*)iter->Node.Next) + { + if( (iter->Window.Context == window->Window.Context) && + (iter != window) ) + used = GL_TRUE; + } + + if( !used ) + eglDestroyContext(fgDisplay.pDisplay.egl.Display, window->Window.Context); + } + window->Window.Context = EGL_NO_CONTEXT; + } + + if (window->Window.pContext.egl.Surface != EGL_NO_SURFACE) { + eglDestroySurface(fgDisplay.pDisplay.egl.Display, window->Window.pContext.egl.Surface); + window->Window.pContext.egl.Surface = EGL_NO_SURFACE; + } +} diff --git a/src/egl/fg_window_egl.h b/src/egl/fg_window_egl.h new file mode 100644 index 0000000..8f5898d --- /dev/null +++ b/src/egl/fg_window_egl.h @@ -0,0 +1,35 @@ +/* + * fg_window_egl.h + * + * Window management methods for EGL + * + * Copyright (C) 2012 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __FG_WINDOW_EGL_H__ +#define __FG_WINDOW_EGL_H__ + +extern int fghChooseConfig(EGLConfig* config); +extern void fghPlatformOpenWindowEGL( SFG_Window* window ); +extern EGLConfig fghCreateNewContextEGL( SFG_Window* window ); +extern void fghPlatformCloseWindowEGL( SFG_Window* window ); +extern void fgPlatformSetWindow ( SFG_Window *window ); + +#endif diff --git a/src/fg_callback_macros.h b/src/fg_callback_macros.h new file mode 100644 index 0000000..a1b8c38 --- /dev/null +++ b/src/fg_callback_macros.h @@ -0,0 +1,336 @@ +/* + * fg_callback_macros.h + * + * The freeglut library callback macro file. + * + * Copyright (C) 2016 Vincent Simonetti + * Creation date: Sat Jan 16 2016 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef FREEGLUT_CALLBACK_MACROS_H +#define FREEGLUT_CALLBACK_MACROS_H + +/* + * ---------------------------------------------------------------------------------------------------------------------- + * There are two sets of macros here. One is for executing window callbacks, the others are for setting window callbacks. + * ---------------------------------------------------------------------------------------------------------------------- + */ + +/* + * Compiler define: FG_COMPILER_SUPPORTS_VA_ARGS: if the compiler supports variadic macros + */ + +/* What supports variadic macros based off Wikipedia article on it (GCC-like must support C99 or higher to use variadic macros) */ +#if (((defined(__GNUC__) && (__GNUC__ >= 3)) || \ + (defined(__clang__))) && \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L))) || \ + (defined(_MSC_VER) && (_MSC_VER >= 1400)) || \ + (defined(__BORLANDC__) && (__BORLANDC__ >= 0x570)) || \ + (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x530)) +#define FG_COMPILER_SUPPORTS_VA_ARGS 1 +#else +#define FG_COMPILER_SUPPORTS_VA_ARGS 0 +#endif + +/* + * -------------------------- + * Executing window callbacks + * -------------------------- + * + * Info: + * + * This took a while to figure out, so be sure try to understand what is happening so that you can ensure that whatever you + * change won't break other areas. + * + * If you are just adding a new callback/changing it's argument count, just go to the bottom of the file. + * + * This whole file exists purely for the sake of preventing the need to implement additional parsing logic for each callback + * to pass user arguments. Of course, the necessity to support older compilers means that, as seen in the line above, there + * is still a requirement to add/modify code to handle callbacks. If freeglut ever requires newer compilers (at minimum, ones + * that support C99 or higher), code can very slowly be removed from this file. Even better would be if the C standard eventually + * supports something similar to what GCC has implemented or offers an alternative. Another option is if C++ would be "allowed" by + * project maintaners, as then templates can be used and function overloading. Ironically, the template would probably look worse + * then the GCC macro, so maybe it's good to stay as is. + * + * Onto the different "versions" of macros: + * + * The first is for any compiler that supports C99 by default. It requires each callback to have a specific argument count + * passthrough macro. The only reason there are specific count macros is so that (see paraghraph below) don't need have their own + * set of callback macros. Ideally, there would only be ZERO and ONE_OR_MORE. This works by having callback-specific macros call a + * specific handler macro to return user data (ZERO) or return one or more arguments along with userData (ONE_OR_MORE) where, with + * variadic macros, it just reuses the arguments. + * + * The last macro set is for the poor individual who has to use a compiler that doesn't support C99 by default, or may not support + * it at all. Stuff like MSVC6... It works by having a specific-count macro that "extracts" each argument to have them reused without + * the parathesis. + * + * There is a 3rd macro set that only worked on GCC/Clang, and thus was removed (last seen in revision e9676fc of the GIT mirror. + * Not sure at this time what the SVN number is.) as it's a non-standard functionality. + */ + +/* + * EXPAND_WCB() is used as: + * + * EXPAND_WCB( cbname )(( arg_list, userData )) + * + * ... where {(arg_list)} is the parameter list and userData is user + * provided data. + * + * This will take the arg_list and extend it by one argument, adding + * the argument "userData" to the end of the list. + * + * In order for this to work, each callback must have a define that + * properly handles the arguments as needed by the callback. + * This callback is in the format of EXPAND_WCB_SUB_. + * Helper functions exist for zero to five parameters: EXPAND_WCB_ZERO, + * EXPAND_WCB_ONE, EXPAND_WCB_TWO, EXPAND_WCB_THREE< EXPAND_WCB_FOUR, + * and EXPAND_WCB_FIVE. Each handle the callback argument counts. + * + * An example for the "Entry" callback, where "Entry" is the cbname: + * typedef void (* FGCBEntry )( int ); + * typedef void (* FGCBEntryUC)( int, FGCBUserData ); + * #define EXPAND_WCB_SUB_Entry(args) EXPAND_WCB_ONE args + */ + +#if FG_COMPILER_SUPPORTS_VA_ARGS + +#define EXPAND_WCB_UNPARAN(...) __VA_ARGS__ +#define EXPAND_WCB_ONE_OR_MORE(args, userData) ( EXPAND_WCB_UNPARAN args, userData ) + +#define EXPAND_WCB_ONE(args, userData) EXPAND_WCB_ONE_OR_MORE( args, userData ) +#define EXPAND_WCB_TWO(args, userData) EXPAND_WCB_ONE_OR_MORE( args, userData ) +#define EXPAND_WCB_THREE(args, userData) EXPAND_WCB_ONE_OR_MORE( args, userData ) +#define EXPAND_WCB_FOUR(args, userData) EXPAND_WCB_ONE_OR_MORE( args, userData ) +#define EXPAND_WCB_FIVE(args, userData) EXPAND_WCB_ONE_OR_MORE( args, userData ) + +#else + +#define EXPAND_WCB_EXTRACT_ONE_ARGS(arg1) arg1 +#define EXPAND_WCB_EXTRACT_TWO_ARGS(arg1, arg2) arg1, arg2 +#define EXPAND_WCB_EXTRACT_THREE_ARGS(arg1, arg2, arg3) arg1, arg2, arg3 +#define EXPAND_WCB_EXTRACT_FOUR_ARGS(arg1, arg2, arg3, arg4) arg1, arg2, arg3, arg4 +#define EXPAND_WCB_EXTRACT_FIVE_ARGS(arg1, arg2, arg3, arg4, arg5) arg1, arg2, arg3, arg4, arg5 + +#define EXPAND_WCB_ONE(args, userData) (EXPAND_WCB_EXTRACT_ONE_ARGS args, userData) +#define EXPAND_WCB_TWO(args, userData) (EXPAND_WCB_EXTRACT_TWO_ARGS args, userData) +#define EXPAND_WCB_THREE(args, userData) (EXPAND_WCB_EXTRACT_THREE_ARGS args, userData) +#define EXPAND_WCB_FOUR(args, userData) (EXPAND_WCB_EXTRACT_FOUR_ARGS args, userData) +#define EXPAND_WCB_FIVE(args, userData) (EXPAND_WCB_EXTRACT_FIVE_ARGS args, userData) + +#endif + +#define EXPAND_WCB_ZERO(args, userData) ( userData ) + +#define EXPAND_WCB(cbname) EXPAND_WCB_SUB_ ## cbname + +/* + * Freeglut callbacks type definitions macros + * + * Every time a callback is updated in fg_internal.h is updated, this needs updated + * if argument counts change, new callbacks are added, or callbacks are removed. + */ + +#define EXPAND_WCB_SUB_Display(args) EXPAND_WCB_ZERO args +#define EXPAND_WCB_SUB_Reshape(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_Position(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_Visibility(args) EXPAND_WCB_ONE args +#define EXPAND_WCB_SUB_Keyboard(args) EXPAND_WCB_THREE args +#define EXPAND_WCB_SUB_KeyboardUp(args) EXPAND_WCB_THREE args +#define EXPAND_WCB_SUB_Special(args) EXPAND_WCB_THREE args +#define EXPAND_WCB_SUB_SpecialUp(args) EXPAND_WCB_THREE args +#define EXPAND_WCB_SUB_Mouse(args) EXPAND_WCB_FOUR args +#define EXPAND_WCB_SUB_MouseWheel(args) EXPAND_WCB_FOUR args +#define EXPAND_WCB_SUB_Motion(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_Passive(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_Entry(args) EXPAND_WCB_ONE args +#define EXPAND_WCB_SUB_WindowStatus(args) EXPAND_WCB_ONE args +#define EXPAND_WCB_SUB_Joystick(args) EXPAND_WCB_FOUR args +#define EXPAND_WCB_SUB_OverlayDisplay(args) EXPAND_WCB_ZERO args +#define EXPAND_WCB_SUB_SpaceMotion(args) EXPAND_WCB_THREE args +#define EXPAND_WCB_SUB_SpaceRotation(args) EXPAND_WCB_THREE args +#define EXPAND_WCB_SUB_SpaceButton(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_Dials(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_ButtonBox(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_TabletMotion(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_TabletButton(args) EXPAND_WCB_FOUR args +#define EXPAND_WCB_SUB_Destroy(args) EXPAND_WCB_ZERO args +#define EXPAND_WCB_SUB_MultiEntry(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_MultiButton(args) EXPAND_WCB_FIVE args +#define EXPAND_WCB_SUB_MultiMotion(args) EXPAND_WCB_THREE args +#define EXPAND_WCB_SUB_MultiPassive(args) EXPAND_WCB_THREE args +#define EXPAND_WCB_SUB_InitContext(args) EXPAND_WCB_ZERO args +#define EXPAND_WCB_SUB_AppStatus(args) EXPAND_WCB_ONE args + +/* + * ------------------------ + * Setting window callbacks + * ------------------------ + * + * These originally existed in fg_callbacks.c + */ + +/* + * All of the window-specific callbacks setting methods can be generalized to this: + */ +#define SET_CURRENT_WINDOW_CALLBACK(a) \ +do \ +{ \ + if( fgStructure.CurrentWindow == NULL ) \ + return; \ + SET_WCB( ( *( fgStructure.CurrentWindow ) ), a, callback, userData ); \ +} while( 0 ) + +/* + * Types need to be defined for callbacks. It's not ideal, but it works for this. + */ +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,b) \ +static void fgh##a##FuncCallback( FGCBUserData userData ) \ +{ \ + FGCB##b* callback = (FGCB##b*)&userData; \ + (*callback)(); \ +} +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG1(a,b) \ +static void fgh##a##FuncCallback( int arg1val, FGCBUserData userData ) \ +{ \ + FGCB##b* callback = (FGCB##b*)&userData; \ + (*callback)( arg1val ); \ +} +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,b) \ +static void fgh##a##FuncCallback( int arg1val, int arg2val, FGCBUserData userData ) \ +{ \ + FGCB##b* callback = (FGCB##b*)&userData; \ + (*callback)( arg1val, arg2val ); \ +} +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG3_USER(a,b,arg1,arg2,arg3) \ +static void fgh##a##FuncCallback( arg1 arg1val, arg2 arg2val, arg3 arg3val, FGCBUserData userData ) \ +{ \ + FGCB##b* callback = (FGCB##b*)&userData; \ + (*callback)( arg1val, arg2val, arg3val ); \ +} +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG3(a,b) IMPLEMENT_CALLBACK_FUNC_CB_ARG3_USER(a,b,int,int,int) +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG4(a,b) \ +static void fgh##a##FuncCallback( int arg1val, int arg2val, int arg3val, int arg4val, FGCBUserData userData ) \ +{ \ + FGCB##b* callback = (FGCB##b*)&userData; \ + (*callback)( arg1val, arg2val, arg3val, arg4val ); \ +} +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG5(a,b) \ +static void fgh##a##FuncCallback( int arg1val, int arg2val, int arg3val, int arg4val, int arg5val, FGCBUserData userData ) \ +{ \ + FGCB##b* callback = (FGCB##b*)&userData; \ + (*callback)( arg1val, arg2val, arg3val, arg4val, arg5val ); \ +} + +/* + * And almost every time the callback setter function can be implemented with these: + */ +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT_UCALL(a,b) \ +void FGAPIENTRY glut##a##FuncUcall( FGCB##b##UC callback, FGCBUserData userData ) \ +{ \ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glut"#a"FuncUcall" ); \ + SET_CURRENT_WINDOW_CALLBACK( b ); \ +} +#define IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,b) \ +void FGAPIENTRY glut##a##Func( FGCB##b callback ) \ +{ \ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glut"#a"Func" ); \ + if( callback ) \ + { \ + FGCB##b* reference = &callback; \ + glut##a##FuncUcall( fgh##a##FuncCallback, *((FGCBUserData*)reference) ); \ + } \ + else \ + glut##a##FuncUcall( NULL, NULL ); \ +} + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,b) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT_UCALL(a,b) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,b) + +/* + * Combine _glut and _cb macros: + */ +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,a) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0_2NAME(a,b) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,b) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,b) + +#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG0(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,a) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,a) + +#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG0_2NAME(a,b) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,b) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,b) + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG1(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG1(a,a) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG1(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG1(a,a) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,a) + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,a) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2_2NAME(a,b) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,b) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,b) + +#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG2(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,a) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,a) + +#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG2_2NAME(a,b) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,b) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,b) + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG3(a,a) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3_USER(a,arg1,arg2,arg3) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG3_USER(a,a,arg1,arg2,arg3) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG3(a,a) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,a) + +#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3_2NAME(a,b) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG3(a,b) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,b) + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG4(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG4(a,a) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG5(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG5(a,a) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#endif /* FREEGLUT_CALLBACK_MACROS_H */ + +/*** END OF FILE ***/ diff --git a/src/fg_callbacks.c b/src/fg_callbacks.c new file mode 100644 index 0000000..2ce266e --- /dev/null +++ b/src/fg_callbacks.c @@ -0,0 +1,331 @@ +/* + * fg_callbacks.c + * + * The callbacks setting methods. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Fri Dec 3 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" + +/* -- INTERFACE FUNCTIONS -------------------------------------------------- */ + +/* + * Global callbacks. + */ + +/* Sets the global idle callback */ +void FGAPIENTRY glutIdleFuncUcall( FGCBIdleUC callback, FGCBUserData userData ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIdleFuncUcall" ); + fgState.IdleCallback = callback; + fgState.IdleCallbackData = userData; +} + +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG0(Idle) + +/* Creates a timer and sets its callback */ +void FGAPIENTRY glutTimerFuncUcall( unsigned int timeOut, FGCBTimerUC callback, int timerID, FGCBUserData userData ) +{ + SFG_Timer *timer, *node; + + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTimerFuncUcall" ); + + if( (timer = fgState.FreeTimers.Last) ) + { + fgListRemove( &fgState.FreeTimers, &timer->Node ); + } + else + { + if( ! (timer = malloc(sizeof(SFG_Timer))) ) + fgError( "Fatal error: " + "Memory allocation failure in glutTimerFunc()" ); + } + + timer->Callback = callback; + timer->CallbackData = userData; + timer->ID = timerID; + timer->TriggerTime = fgElapsedTime() + timeOut; + + /* Insert such that timers are sorted by end-time */ + for( node = fgState.Timers.First; node; node = node->Node.Next ) + { + if( node->TriggerTime > timer->TriggerTime ) + break; + } + + fgListInsert( &fgState.Timers, node ? &node->Node : 0, &timer->Node ); +} + +IMPLEMENT_CALLBACK_FUNC_CB_ARG1(Timer, Timer) + +void FGAPIENTRY glutTimerFunc( unsigned int timeOut, FGCBTimer callback, int timerID ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTimerFunc" ); + if( callback ) + { + FGCBTimer* reference = &callback; + glutTimerFuncUcall( timeOut, fghTimerFuncCallback, timerID, *((FGCBUserData*)reference) ); + } + else + glutTimerFuncUcall( timeOut, NULL, timerID, NULL ); +} + +/* Deprecated version of glutMenuStatusFunc callback setting method */ +void FGAPIENTRY glutMenuStateFunc( FGCBMenuState callback ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStateFunc" ); + fgState.MenuStateCallback = callback; +} + +/* Sets the global menu status callback for the current window */ +void FGAPIENTRY glutMenuStatusFuncUcall( FGCBMenuStatusUC callback, FGCBUserData userData ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStatusFuncUcall" ); + fgState.MenuStatusCallback = callback; + fgState.MenuStatusCallbackData = userData; +} + +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3(MenuStatus) + +/* + * Menu specific callbacks. + */ +/* Callback upon menu destruction */ +void FGAPIENTRY glutMenuDestroyFuncUcall( FGCBDestroyUC callback, FGCBUserData userData ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuDestroyFuncUcall" ); + if( fgStructure.CurrentMenu ) + { + fgStructure.CurrentMenu->Destroy = callback; + fgStructure.CurrentMenu->DestroyData = userData; + } +} + +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG0_2NAME(MenuDestroy, Destroy) + +/* Implement all these callback setter functions... */ +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(Position) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3_USER(Keyboard,unsigned char,int,int) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3_USER(KeyboardUp,unsigned char,int,int) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(Special) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(SpecialUp) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG4(Mouse) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG4(MouseWheel) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(Motion) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2_2NAME(PassiveMotion,Passive) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG1(Entry) +/* glutWMCloseFunc is an alias for glutCloseFunc; both set the window's Destroy callback */ +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0_2NAME(Close,Destroy) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0_2NAME(WMClose,Destroy) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0(OverlayDisplay) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG1(WindowStatus) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(ButtonBox) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(Dials) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(TabletMotion) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG4(TabletButton) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(MultiEntry) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG5(MultiButton) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(MultiMotion) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(MultiPassive) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0(InitContext) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG1(AppStatus) + +/* + * Sets the Display callback for the current window + */ +void FGAPIENTRY glutDisplayFuncUcall( FGCBDisplayUC callback, FGCBUserData userData ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDisplayFuncUcall" ); + if( !callback ) + fgError( "Fatal error in program. NULL display callback not " + "permitted in GLUT 3.0+ or freeglut 2.0.1+" ); + SET_CURRENT_WINDOW_CALLBACK( Display ); +} + +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG0(Display) + +void fghDefaultReshape( int width, int height, FGCBUserData userData ) +{ + glViewport( 0, 0, width, height ); +} + +void FGAPIENTRY glutReshapeFuncUcall( FGCBReshapeUC callback, FGCBUserData userData ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeFuncUcall" ); + + if( !callback ) + { + callback = fghDefaultReshape; + userData = NULL; + } + + SET_CURRENT_WINDOW_CALLBACK( Reshape ); +} + +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG2(Reshape) + +/* + * Sets the Visibility callback for the current window. + * NB: the Visibility func is deprecated in favor of the WindowStatus func, + * which provides more detail. The visibility func callback is implemented + * as a translation step from the windowStatus func. When the user sets the + * windowStatus func, any visibility func is overwritten. + * DEVELOPER NOTE: in the library, only invoke the window status func, this + * gets automatically translated to the visibility func if thats what the + * user has set. + * window status is kind of anemic on win32 as there are no window messages + * to notify us that the window is covered by other windows or not. + * Should one want to query this, see + * http://stackoverflow.com/questions/5445889/get-which-process-window-is-actually-visible-in-c-sharp + * for an implementation outline (but it would be polling based, not push based). + */ +static void fghVisibility( int status, FGCBUserData userData ) +{ + int vis_status; + + FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED ( "Visibility Callback" ); + freeglut_return_if_fail( fgStructure.CurrentWindow ); + + /* Translate window status func states to visibility states */ + if( ( status == GLUT_HIDDEN) || ( status == GLUT_FULLY_COVERED) ) + vis_status = GLUT_NOT_VISIBLE; + else /* GLUT_FULLY_RETAINED, GLUT_PARTIALLY_RETAINED */ + vis_status = GLUT_VISIBLE; + + INVOKE_WCB( *( fgStructure.CurrentWindow ), Visibility, ( vis_status ) ); +} + +void FGAPIENTRY glutVisibilityFuncUcall( FGCBVisibilityUC callback, FGCBUserData userData ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutVisibilityFuncUcall" ); + + if ( !callback ) + { + userData = NULL; + } + + SET_CURRENT_WINDOW_CALLBACK( Visibility ); + + if( callback ) + glutWindowStatusFuncUcall( fghVisibility, NULL ); + else + glutWindowStatusFuncUcall( NULL, NULL ); +} + +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG1(Visibility) + +/* + * Sets the joystick callback and polling rate for the current window + */ +void FGAPIENTRY glutJoystickFuncUcall( FGCBJoystickUC callback, int pollInterval, FGCBUserData userData ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickFuncUcall" ); + fgInitialiseJoysticks (); + + if ( ( + fgStructure.CurrentWindow->State.JoystickPollRate <= 0 || /* Joystick callback was disabled */ + !FETCH_WCB(*fgStructure.CurrentWindow,Joystick) + ) && + ( + callback && ( pollInterval > 0 ) /* but is now enabled */ + ) ) + ++fgState.NumActiveJoysticks; + else if ( ( + fgStructure.CurrentWindow->State.JoystickPollRate > 0 && /* Joystick callback was enabled */ + FETCH_WCB(*fgStructure.CurrentWindow,Joystick) + ) && + ( + !callback || ( pollInterval <= 0 ) /* but is now disabled */ + ) ) + --fgState.NumActiveJoysticks; + + SET_CURRENT_WINDOW_CALLBACK( Joystick ); + fgStructure.CurrentWindow->State.JoystickPollRate = pollInterval; + + /* set last poll time such that joystick will be polled asap */ + fgStructure.CurrentWindow->State.JoystickLastPoll = fgElapsedTime(); + if (fgStructure.CurrentWindow->State.JoystickLastPoll < pollInterval) + fgStructure.CurrentWindow->State.JoystickLastPoll = 0; + else + fgStructure.CurrentWindow->State.JoystickLastPoll -= pollInterval; +} + +static void fghJoystickFuncCallback( unsigned int buttons, int axis0, int axis1, int axis2, FGCBUserData userData ) +{ + FGCBJoystick* callback = (FGCBJoystick*)&userData; + (*callback)( buttons, axis0, axis1, axis2 ); +} + +void FGAPIENTRY glutJoystickFunc( FGCBJoystick callback, int pollInterval ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickFunc" ); + if( callback ) + { + FGCBJoystick* reference = &callback; + glutJoystickFuncUcall( fghJoystickFuncCallback, pollInterval, *((FGCBUserData*)reference) ); + } + else + glutJoystickFuncUcall( NULL, pollInterval, NULL ); +} + +/* + * Sets the spaceball motion callback for the current window + */ +void FGAPIENTRY glutSpaceballMotionFuncUcall( FGCBSpaceMotionUC callback, FGCBUserData userData ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballMotionFuncUcall" ); + fgInitialiseSpaceball(); + + SET_CURRENT_WINDOW_CALLBACK( SpaceMotion ); +} + +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3_2NAME(SpaceballMotion, SpaceMotion) + +/* + * Sets the spaceball rotate callback for the current window + */ +void FGAPIENTRY glutSpaceballRotateFuncUcall( FGCBSpaceRotationUC callback, FGCBUserData userData ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballRotateFuncUcall" ); + fgInitialiseSpaceball(); + + SET_CURRENT_WINDOW_CALLBACK( SpaceRotation ); +} + +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3_2NAME(SpaceballRotate, SpaceRotation) + +/* + * Sets the spaceball button callback for the current window + */ +void FGAPIENTRY glutSpaceballButtonFuncUcall( FGCBSpaceButtonUC callback, FGCBUserData userData ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballButtonFuncUcall" ); + fgInitialiseSpaceball(); + + SET_CURRENT_WINDOW_CALLBACK( SpaceButton ); +} + +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG2_2NAME(SpaceballButton, SpaceButton) + +/*** END OF FILE ***/ diff --git a/src/fg_cursor.c b/src/fg_cursor.c new file mode 100644 index 0000000..bd60b04 --- /dev/null +++ b/src/fg_cursor.c @@ -0,0 +1,79 @@ +/* + * fg_cursor.c + * + * The mouse cursor related stuff. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Thu Dec 16 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" + +/* + * TODO BEFORE THE STABLE RELEASE: + * glutSetCursor() -- Win32 mappings are incomplete. + * + * It would be good to use custom mouse cursor shapes, and introduce + * an option to display them using glBitmap() and/or texture mapping, + * apart from the windowing system version. + */ + +/* -- PRIVATE FUNCTIONS --------------------------------------------------- */ + +extern void fgPlatformSetCursor ( SFG_Window *window, int cursorID ); +extern void fgPlatformWarpPointer ( int x, int y ); + + + +/* -- INTERNAL FUNCTIONS ---------------------------------------------------- */ +void fgSetCursor ( SFG_Window *window, int cursorID ) +{ + fgPlatformSetCursor ( window, cursorID ); +} + + +/* -- INTERFACE FUNCTIONS -------------------------------------------------- */ + +/* + * Set the cursor image to be used for the current window + */ +void FGAPIENTRY glutSetCursor( int cursorID ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetCursor" ); + FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetCursor" ); + + fgPlatformSetCursor ( fgStructure.CurrentWindow, cursorID ); + fgStructure.CurrentWindow->State.Cursor = cursorID; +} + +/* + * Moves the mouse pointer to given window coordinates + */ +void FGAPIENTRY glutWarpPointer( int x, int y ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWarpPointer" ); + FREEGLUT_EXIT_IF_NO_WINDOW ( "glutWarpPointer" ); + + fgPlatformWarpPointer ( x, y ); +} + +/*** END OF FILE ***/ diff --git a/src/fg_display.c b/src/fg_display.c new file mode 100644 index 0000000..7688015 --- /dev/null +++ b/src/fg_display.c @@ -0,0 +1,104 @@ +/* + * fg_display.c + * + * Display message posting, context buffer swapping. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Fri Dec 3 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" + + +/* Function prototypes */ +extern void fgPlatformGlutSwapBuffers( SFG_PlatformDisplay *pDisplayPtr, SFG_Window* CurrentWindow ); + + +/* -- INTERFACE FUNCTIONS -------------------------------------------------- */ + +/* + * Marks the current window to have the redisplay performed when possible... + */ +void FGAPIENTRY glutPostRedisplay( void ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPostRedisplay" ); + if ( ! fgStructure.CurrentWindow ) + { + fgError ( " ERROR: Function <%s> called" + " with no current window defined.", "glutPostRedisplay" ) ; + } + + fgStructure.CurrentWindow->State.WorkMask |= GLUT_DISPLAY_WORK; +} + +/* + * Swaps the buffers for the current window (if any) + */ +void FGAPIENTRY glutSwapBuffers( void ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSwapBuffers" ); + FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSwapBuffers" ); + + /* + * "glXSwapBuffers" already performs an implicit call to "glFlush". What + * about "SwapBuffers"? + */ + glFlush( ); + if( ! fgStructure.CurrentWindow->Window.DoubleBuffered ) + return; + + fgPlatformGlutSwapBuffers( &fgDisplay.pDisplay, fgStructure.CurrentWindow ); + + /* GLUT_FPS env var support */ + if( fgState.FPSInterval ) + { + GLint t = glutGet( GLUT_ELAPSED_TIME ); + fgState.SwapCount++; + if( fgState.SwapTime == 0 ) + fgState.SwapTime = t; + else if( t - fgState.SwapTime > fgState.FPSInterval ) + { + float time = 0.001f * ( t - fgState.SwapTime ); + float fps = ( float )fgState.SwapCount / time; + fprintf( stderr, + "freeglut: %d frames in %.2f seconds = %.2f FPS\n", + fgState.SwapCount, time, fps ); + fgState.SwapTime = t; + fgState.SwapCount = 0; + } + } +} + +/* + * Mark appropriate window to be displayed + */ +void FGAPIENTRY glutPostWindowRedisplay( int windowID ) +{ + SFG_Window* window; + + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPostWindowRedisplay" ); + window = fgWindowByID( windowID ); + freeglut_return_if_fail( window ); + window->State.WorkMask |= GLUT_DISPLAY_WORK; +} + +/*** END OF FILE ***/ diff --git a/src/fg_ext.c b/src/fg_ext.c new file mode 100644 index 0000000..0ddb560 --- /dev/null +++ b/src/fg_ext.c @@ -0,0 +1,274 @@ +/* + * fg_ext.c + * + * Functions related to OpenGL extensions. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Thu Dec 9 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#define GLX_GLXEXT_PROTOTYPES +#include +#include "fg_internal.h" + +extern SFG_Proc fgPlatformGetProcAddress( const char *procName ); +extern GLUTproc fgPlatformGetGLUTProcAddress( const char *procName ); + +static GLUTproc fghGetGLUTProcAddress( const char* procName ) +{ + /* optimization: quick initial check */ + if( strncmp( procName, "glut", 4 ) != 0 ) + return NULL; + +#define CHECK_NAME(x) if( strcmp( procName, #x ) == 0) return (GLUTproc)x; + CHECK_NAME(glutInit); + CHECK_NAME(glutInitDisplayMode); + CHECK_NAME(glutInitDisplayString); + CHECK_NAME(glutInitWindowPosition); + CHECK_NAME(glutInitWindowSize); + CHECK_NAME(glutMainLoop); + CHECK_NAME(glutExit); + CHECK_NAME(glutCreateWindow); + CHECK_NAME(glutCreateSubWindow); + CHECK_NAME(glutDestroyWindow); + CHECK_NAME(glutPostRedisplay); + CHECK_NAME(glutPostWindowRedisplay); + CHECK_NAME(glutSwapBuffers); + CHECK_NAME(glutGetWindow); + CHECK_NAME(glutSetWindow); + CHECK_NAME(glutSetWindowTitle); + CHECK_NAME(glutSetIconTitle); + CHECK_NAME(glutPositionWindow); + CHECK_NAME(glutReshapeWindow); + CHECK_NAME(glutPopWindow); + CHECK_NAME(glutPushWindow); + CHECK_NAME(glutIconifyWindow); + CHECK_NAME(glutShowWindow); + CHECK_NAME(glutHideWindow); + CHECK_NAME(glutFullScreen); + CHECK_NAME(glutSetCursor); + CHECK_NAME(glutWarpPointer); + CHECK_NAME(glutEstablishOverlay); + CHECK_NAME(glutRemoveOverlay); + CHECK_NAME(glutUseLayer); + CHECK_NAME(glutPostOverlayRedisplay); + CHECK_NAME(glutPostWindowOverlayRedisplay); + CHECK_NAME(glutShowOverlay); + CHECK_NAME(glutHideOverlay); + CHECK_NAME(glutCreateMenu); + CHECK_NAME(glutDestroyMenu); + CHECK_NAME(glutGetMenu); + CHECK_NAME(glutSetMenu); + CHECK_NAME(glutAddMenuEntry); + CHECK_NAME(glutAddSubMenu); + CHECK_NAME(glutChangeToMenuEntry); + CHECK_NAME(glutChangeToSubMenu); + CHECK_NAME(glutRemoveMenuItem); + CHECK_NAME(glutAttachMenu); + CHECK_NAME(glutDetachMenu); + CHECK_NAME(glutDisplayFunc); + CHECK_NAME(glutReshapeFunc); + CHECK_NAME(glutPositionFunc); + CHECK_NAME(glutKeyboardFunc); + CHECK_NAME(glutMouseFunc); + CHECK_NAME(glutMultiEntryFunc); + CHECK_NAME(glutMultiMotionFunc); + CHECK_NAME(glutMultiButtonFunc); + CHECK_NAME(glutMultiPassiveFunc); + CHECK_NAME(glutMotionFunc); + CHECK_NAME(glutPassiveMotionFunc); + CHECK_NAME(glutEntryFunc); + CHECK_NAME(glutVisibilityFunc); + CHECK_NAME(glutIdleFunc); + CHECK_NAME(glutTimerFunc); + CHECK_NAME(glutMenuStateFunc); + CHECK_NAME(glutSpecialFunc); + CHECK_NAME(glutSpaceballMotionFunc); + CHECK_NAME(glutSpaceballRotateFunc); + CHECK_NAME(glutSpaceballButtonFunc); + CHECK_NAME(glutButtonBoxFunc); + CHECK_NAME(glutDialsFunc); + CHECK_NAME(glutTabletMotionFunc); + CHECK_NAME(glutTabletButtonFunc); + CHECK_NAME(glutMenuStatusFunc); + CHECK_NAME(glutOverlayDisplayFunc); + CHECK_NAME(glutWindowStatusFunc); + CHECK_NAME(glutKeyboardUpFunc); + CHECK_NAME(glutSpecialUpFunc); + CHECK_NAME(glutSetColor); + CHECK_NAME(glutGetColor); + CHECK_NAME(glutCopyColormap); + CHECK_NAME(glutGet); + CHECK_NAME(glutDeviceGet); + CHECK_NAME(glutExtensionSupported); + CHECK_NAME(glutGetModifiers); + CHECK_NAME(glutLayerGet); + CHECK_NAME(glutBitmapCharacter); + CHECK_NAME(glutBitmapWidth); + CHECK_NAME(glutStrokeCharacter); + CHECK_NAME(glutStrokeWidth); + CHECK_NAME(glutStrokeWidthf); + CHECK_NAME(glutBitmapLength); + CHECK_NAME(glutStrokeLength); + CHECK_NAME(glutStrokeLengthf); + CHECK_NAME(glutWireSphere); + CHECK_NAME(glutSolidSphere); + CHECK_NAME(glutWireCone); + CHECK_NAME(glutSolidCone); + CHECK_NAME(glutWireTorus); + CHECK_NAME(glutSolidTorus); + CHECK_NAME(glutWireCylinder); + CHECK_NAME(glutSolidCylinder); + CHECK_NAME(glutWireTeapot); + CHECK_NAME(glutSolidTeapot); + CHECK_NAME(glutWireTeacup); + CHECK_NAME(glutSolidTeacup); + CHECK_NAME(glutWireTeaspoon); + CHECK_NAME(glutSolidTeaspoon); + CHECK_NAME(glutWireCube); + CHECK_NAME(glutSolidCube); + CHECK_NAME(glutWireDodecahedron); + CHECK_NAME(glutSolidDodecahedron); + CHECK_NAME(glutWireOctahedron); + CHECK_NAME(glutSolidOctahedron); + CHECK_NAME(glutWireTetrahedron); + CHECK_NAME(glutSolidTetrahedron); + CHECK_NAME(glutWireIcosahedron); + CHECK_NAME(glutSolidIcosahedron); + CHECK_NAME(glutWireRhombicDodecahedron); + CHECK_NAME(glutSolidRhombicDodecahedron); + CHECK_NAME(glutWireSierpinskiSponge); + CHECK_NAME(glutSolidSierpinskiSponge); + CHECK_NAME(glutVideoResizeGet); + CHECK_NAME(glutSetupVideoResizing); + CHECK_NAME(glutStopVideoResizing); + CHECK_NAME(glutVideoResize); + CHECK_NAME(glutVideoPan); + CHECK_NAME(glutReportErrors); + CHECK_NAME(glutIgnoreKeyRepeat); + CHECK_NAME(glutSetKeyRepeat); + + /* freeglut extensions */ + CHECK_NAME(glutMainLoopEvent); + CHECK_NAME(glutLeaveMainLoop); + CHECK_NAME(glutCloseFunc); + CHECK_NAME(glutWMCloseFunc); + CHECK_NAME(glutMenuDestroyFunc); + CHECK_NAME(glutFullScreenToggle); + CHECK_NAME(glutLeaveFullScreen); + CHECK_NAME(glutSetMenuFont); + CHECK_NAME(glutSetOption); + CHECK_NAME(glutGetModeValues); + CHECK_NAME(glutSetWindowData); + CHECK_NAME(glutGetWindowData); + CHECK_NAME(glutSetMenuData); + CHECK_NAME(glutGetMenuData); + CHECK_NAME(glutBitmapHeight); + CHECK_NAME(glutStrokeHeight); + CHECK_NAME(glutBitmapString); + CHECK_NAME(glutStrokeString); + CHECK_NAME(glutGetProcAddress); + CHECK_NAME(glutMouseWheelFunc); + CHECK_NAME(glutJoystickGetNumAxes); + CHECK_NAME(glutJoystickGetNumButtons); + CHECK_NAME(glutJoystickNotWorking); + CHECK_NAME(glutJoystickGetDeadBand); + CHECK_NAME(glutJoystickSetDeadBand); + CHECK_NAME(glutJoystickGetSaturation); + CHECK_NAME(glutJoystickSetSaturation); + CHECK_NAME(glutJoystickSetMinRange); + CHECK_NAME(glutJoystickSetMaxRange); + CHECK_NAME(glutJoystickSetCenter); + CHECK_NAME(glutJoystickGetMinRange); + CHECK_NAME(glutJoystickGetMaxRange); + CHECK_NAME(glutJoystickGetCenter); + CHECK_NAME(glutInitContextVersion); + CHECK_NAME(glutInitContextFlags); + CHECK_NAME(glutInitContextProfile); + CHECK_NAME(glutInitErrorFunc); + CHECK_NAME(glutInitWarningFunc); + CHECK_NAME(glutInitContextFunc); + CHECK_NAME(glutAppStatusFunc); + CHECK_NAME(glutSetVertexAttribCoord3); + CHECK_NAME(glutSetVertexAttribNormal); + CHECK_NAME(glutSetVertexAttribTexCoord2); + + /* freeglut user callback functions */ + CHECK_NAME(glutCreateMenuUcall); + CHECK_NAME(glutTimerFuncUcall); + CHECK_NAME(glutIdleFuncUcall); + CHECK_NAME(glutKeyboardFuncUcall); + CHECK_NAME(glutSpecialFuncUcall); + CHECK_NAME(glutReshapeFuncUcall); + CHECK_NAME(glutVisibilityFuncUcall); + CHECK_NAME(glutDisplayFuncUcall); + CHECK_NAME(glutMouseFuncUcall); + CHECK_NAME(glutMotionFuncUcall); + CHECK_NAME(glutPassiveMotionFuncUcall); + CHECK_NAME(glutEntryFuncUcall); + CHECK_NAME(glutKeyboardUpFuncUcall); + CHECK_NAME(glutSpecialUpFuncUcall); + CHECK_NAME(glutJoystickFuncUcall); + CHECK_NAME(glutMenuStatusFuncUcall); + CHECK_NAME(glutOverlayDisplayFuncUcall); + CHECK_NAME(glutWindowStatusFuncUcall); + CHECK_NAME(glutSpaceballMotionFuncUcall); + CHECK_NAME(glutSpaceballRotateFuncUcall); + CHECK_NAME(glutSpaceballButtonFuncUcall); + CHECK_NAME(glutButtonBoxFuncUcall); + CHECK_NAME(glutDialsFuncUcall); + CHECK_NAME(glutTabletMotionFuncUcall); + CHECK_NAME(glutTabletButtonFuncUcall); + CHECK_NAME(glutMouseWheelFuncUcall); + CHECK_NAME(glutPositionFuncUcall); + CHECK_NAME(glutCloseFuncUcall); + CHECK_NAME(glutWMCloseFuncUcall); + CHECK_NAME(glutMenuDestroyFuncUcall); + CHECK_NAME(glutMultiEntryFuncUcall); + CHECK_NAME(glutMultiButtonFuncUcall); + CHECK_NAME(glutMultiMotionFuncUcall); + CHECK_NAME(glutMultiPassiveFuncUcall); + CHECK_NAME(glutInitErrorFuncUcall); + CHECK_NAME(glutInitWarningFuncUcall); + CHECK_NAME(glutInitContextFuncUcall); + CHECK_NAME(glutAppStatusFuncUcall); +#undef CHECK_NAME + + return NULL; +} + + + +GLUTproc FGAPIENTRY +glutGetProcAddress( const char *procName ) +{ + GLUTproc p; + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGetProcAddress" ); + + /* Try GLUT functions first, then core GL functions */ + p = fghGetGLUTProcAddress( procName ); + + /* Some GLUT functions are platform-specific: */ + if ( !p ) + p = fgPlatformGetGLUTProcAddress( procName ); + + return ( p != NULL ) ? p : fgPlatformGetProcAddress( procName ); +} diff --git a/src/fg_font.c b/src/fg_font.c new file mode 100644 index 0000000..f104d28 --- /dev/null +++ b/src/fg_font.c @@ -0,0 +1,478 @@ +/* + * fg_font.c + * + * Bitmap and stroke fonts displaying. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Thu Dec 16 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" + +/* + * TODO BEFORE THE STABLE RELEASE: + * + * Test things out ... + */ + +/* -- IMPORT DECLARATIONS -------------------------------------------------- */ + +/* + * These are the font faces defined in fg_font_data.c file: + */ +extern SFG_Font fgFontFixed8x13; +extern SFG_Font fgFontFixed9x15; +extern SFG_Font fgFontHelvetica10; +extern SFG_Font fgFontHelvetica12; +extern SFG_Font fgFontHelvetica18; +extern SFG_Font fgFontTimesRoman10; +extern SFG_Font fgFontTimesRoman24; +extern SFG_StrokeFont fgStrokeRoman; +extern SFG_StrokeFont fgStrokeMonoRoman; + + +/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ + +/* + * Matches a font ID with a SFG_Font structure pointer. + * This was changed to match the GLUT header style. + */ +SFG_Font* fghFontByID( void* font ) +{ + if( font == GLUT_BITMAP_8_BY_13 ) + return &fgFontFixed8x13; + if( font == GLUT_BITMAP_9_BY_15 ) + return &fgFontFixed9x15; + if( font == GLUT_BITMAP_HELVETICA_10 ) + return &fgFontHelvetica10; + if( font == GLUT_BITMAP_HELVETICA_12 ) + return &fgFontHelvetica12; + if( font == GLUT_BITMAP_HELVETICA_18 ) + return &fgFontHelvetica18; + if( font == GLUT_BITMAP_TIMES_ROMAN_10 ) + return &fgFontTimesRoman10; + if( font == GLUT_BITMAP_TIMES_ROMAN_24 ) + return &fgFontTimesRoman24; + + return 0; +} + +/* + * Matches a font ID with a SFG_StrokeFont structure pointer. + * This was changed to match the GLUT header style. + */ +static SFG_StrokeFont* fghStrokeByID( void* font ) +{ + if( font == GLUT_STROKE_ROMAN ) + return &fgStrokeRoman; + if( font == GLUT_STROKE_MONO_ROMAN ) + return &fgStrokeMonoRoman; + + return 0; +} + + +/* -- INTERFACE FUNCTIONS -------------------------------------------------- */ + +/* + * Draw a bitmap character + */ +void FGAPIENTRY glutBitmapCharacter( void* fontID, int character ) +{ + const GLubyte* face; + SFG_Font* font; + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutBitmapCharacter" ); + font = fghFontByID( fontID ); + if (!font) + { + fgWarning("glutBitmapCharacter: bitmap font 0x%08x not found. Make sure you're not passing a stroke font.\n",fontID); + return; + } + freeglut_return_if_fail( ( character >= 1 )&&( character < 256 ) ); + + /* + * Find the character we want to draw (???) + */ + face = font->Characters[ character ]; + +#ifdef GL_VERSION_1_1 + glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT ); +#else + { + GLint swbytes, lsbfirst, rowlen, skiprows, skippix, align; + + glGetIntegerv(GL_UNPACK_SWAP_BYTES, &swbytes); + glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsbfirst); + glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowlen); + glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skiprows); + glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skippix); + glGetIntegerv(GL_UNPACK_ALIGNMENT, &align); +#endif + glPixelStorei( GL_UNPACK_SWAP_BYTES, GL_FALSE ); + glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE ); + glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 ); + glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 ); + glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 ); + glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); + glBitmap( + face[ 0 ], font->Height, /* The bitmap's width and height */ + font->xorig, font->yorig, /* The origin in the font glyph */ + ( float )( face[ 0 ] ), 0.0, /* The raster advance -- inc. x,y */ + ( face + 1 ) /* The packed bitmap data... */ + ); +#ifdef GL_VERSION_1_1 + glPopClientAttrib(); +#else + glPixelStorei(GL_UNPACK_SWAP_BYTES, swbytes); + glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst); + glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlen); + glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippix); + glPixelStorei(GL_UNPACK_ALIGNMENT, align); + } +#endif +} + +void FGAPIENTRY glutBitmapString( void* fontID, const unsigned char *string ) +{ + unsigned char c; + float x = 0.0f ; + SFG_Font* font; + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutBitmapString" ); + font = fghFontByID( fontID ); + if (!font) + { + fgWarning("glutBitmapString: bitmap font 0x%08x not found. Make sure you're not passing a stroke font.\n",fontID); + return; + } + if ( !string || ! *string ) + return; + +#ifdef GL_VERSION_1_1 + glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT ); +#else + { + GLint swbytes, lsbfirst, rowlen, skiprows, skippix, align; + + glGetIntegerv(GL_UNPACK_SWAP_BYTES, &swbytes); + glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsbfirst); + glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowlen); + glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skiprows); + glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skippix); + glGetIntegerv(GL_UNPACK_ALIGNMENT, &align); +#endif + glPixelStorei( GL_UNPACK_SWAP_BYTES, GL_FALSE ); + glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE ); + glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 ); + glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 ); + glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 ); + glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); + + /* + * Step through the string, drawing each character. + * A newline will simply translate the next character's insertion + * point back to the start of the line and down one line. + */ + while( ( c = *string++) ) + if( c == '\n' ) + { + glBitmap ( 0, 0, 0, 0, -x, (float) -font->Height, NULL ); + x = 0.0f; + } + else /* Not an EOL, draw the bitmap character */ + { + const GLubyte* face = font->Characters[ c ]; + + glBitmap( + face[ 0 ], font->Height, /* Bitmap's width and height */ + font->xorig, font->yorig, /* The origin in the font glyph */ + ( float )( face[ 0 ] ), 0.0, /* The raster advance; inc. x,y */ + ( face + 1 ) /* The packed bitmap data... */ + ); + + x += ( float )( face[ 0 ] ); + } + +#ifdef GL_VERSION_1_1 + glPopClientAttrib(); +#else + glPixelStorei(GL_UNPACK_SWAP_BYTES, swbytes); + glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst); + glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlen); + glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippix); + glPixelStorei(GL_UNPACK_ALIGNMENT, align); + } +#endif +} + +/* + * Returns the width in pixels of a font's character + */ +int FGAPIENTRY glutBitmapWidth( void* fontID, int character ) +{ + SFG_Font* font; + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutBitmapWidth" ); + freeglut_return_val_if_fail( character > 0 && character < 256, 0 ); + font = fghFontByID( fontID ); + if (!font) + { + fgWarning("glutBitmapWidth: bitmap font 0x%08x not found. Make sure you're not passing a stroke font.\n",fontID); + return 0; + } + return *( font->Characters[ character ] ); +} + +/* + * Return the width of a string drawn using a bitmap font + */ +int FGAPIENTRY glutBitmapLength( void* fontID, const unsigned char* string ) +{ + unsigned char c; + int length = 0, this_line_length = 0; + SFG_Font* font; + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutBitmapLength" ); + font = fghFontByID( fontID ); + if (!font) + { + fgWarning("glutBitmapLength: bitmap font 0x%08x not found. Make sure you're not passing a stroke font.\n",fontID); + return 0; + } + if ( !string || ! *string ) + return 0; + + while( ( c = *string++) ) + { + if( c != '\n' )/* Not an EOL, increment length of line */ + this_line_length += *( font->Characters[ c ]); + else /* EOL; reset the length of this line */ + { + if( length < this_line_length ) + length = this_line_length; + this_line_length = 0; + } + } + if ( length < this_line_length ) + length = this_line_length; + + return length; +} + +/* + * Returns the height of a bitmap font + */ +int FGAPIENTRY glutBitmapHeight( void* fontID ) +{ + SFG_Font* font; + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutBitmapHeight" ); + font = fghFontByID( fontID ); + if (!font) + { + fgWarning("glutBitmapHeight: bitmap font 0x%08x not found. Make sure you're not passing a stroke font.\n",fontID); + return 0; + } + return font->Height; +} + +/* + * Draw a stroke character + */ +void FGAPIENTRY glutStrokeCharacter( void* fontID, int character ) +{ + const SFG_StrokeChar *schar; + const SFG_StrokeStrip *strip; + int i, j; + SFG_StrokeFont* font; + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutStrokeCharacter" ); + font = fghStrokeByID( fontID ); + if (!font) + { + fgWarning("glutStrokeCharacter: stroke font 0x%08x not found. Make sure you're not passing a bitmap font.\n",fontID); + return; + } + freeglut_return_if_fail( character >= 0 ); + freeglut_return_if_fail( character < font->Quantity ); + + schar = font->Characters[ character ]; + freeglut_return_if_fail( schar ); + strip = schar->Strips; + + for( i = 0; i < schar->Number; i++, strip++ ) + { + glBegin( GL_LINE_STRIP ); + for( j = 0; j < strip->Number; j++ ) + glVertex2f( strip->Vertices[ j ].X, strip->Vertices[ j ].Y ); + glEnd( ); + + if (fgState.StrokeFontDrawJoinDots) + { + glBegin( GL_POINTS ); + for( j = 0; j < strip->Number; j++ ) + glVertex2f( strip->Vertices[ j ].X, strip->Vertices[ j ].Y ); + glEnd( ); + } + } + glTranslatef( schar->Right, 0.0, 0.0 ); +} + +void FGAPIENTRY glutStrokeString( void* fontID, const unsigned char *string ) +{ + unsigned char c; + int i, j; + float length = 0.0; + SFG_StrokeFont* font; + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutStrokeString" ); + font = fghStrokeByID( fontID ); + if (!font) + { + fgWarning("glutStrokeString: stroke font 0x%08x not found. Make sure you're not passing a bitmap font.\n",fontID); + return; + } + if ( !string || ! *string ) + return; + + /* + * Step through the string, drawing each character. + * A newline will simply translate the next character's insertion + * point back to the start of the line and down one line. + */ + while( ( c = *string++) ) + if( c < font->Quantity ) + { + if( c == '\n' ) + { + glTranslatef ( -length, -( float )( font->Height ), 0.0 ); + length = 0.0; + } + else /* Not an EOL, draw the bitmap character */ + { + const SFG_StrokeChar *schar = font->Characters[ c ]; + if( schar ) + { + const SFG_StrokeStrip *strip = schar->Strips; + + for( i = 0; i < schar->Number; i++, strip++ ) + { + glBegin( GL_LINE_STRIP ); + for( j = 0; j < strip->Number; j++ ) + glVertex2f( strip->Vertices[ j ].X, + strip->Vertices[ j ].Y); + + glEnd( ); + } + + length += schar->Right; + glTranslatef( schar->Right, 0.0, 0.0 ); + } + } + } +} + +/* + * Return the width in pixels of a stroke character + */ +GLfloat FGAPIENTRY glutStrokeWidthf( void* fontID, int character ) +{ + const SFG_StrokeChar *schar; + SFG_StrokeFont* font; + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutStrokeWidth" ); + font = fghStrokeByID( fontID ); + if (!font) + { + fgWarning("glutStrokeWidth: stroke font 0x%08x not found. Make sure you're not passing a bitmap font.\n",fontID); + return 0; + } + freeglut_return_val_if_fail( ( character >= 0 ) && + ( character < font->Quantity ), + 0 + ); + schar = font->Characters[ character ]; + freeglut_return_val_if_fail( schar, 0 ); + + return schar->Right; +} +int FGAPIENTRY glutStrokeWidth(void* fontID, int character) +{ + return ( int )( glutStrokeWidthf(fontID,character) + 0.5f ); +} + +/* + * Return the width of a string drawn using a stroke font + */ +GLfloat FGAPIENTRY glutStrokeLengthf( void* fontID, const unsigned char* string ) +{ + unsigned char c; + GLfloat length = 0.0; + GLfloat this_line_length = 0.0; + SFG_StrokeFont* font; + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutStrokeLength" ); + font = fghStrokeByID( fontID ); + if (!font) + { + fgWarning("glutStrokeLength: stroke font 0x%08x not found. Make sure you're not passing a bitmap font.\n",fontID); + return 0; + } + if ( !string || ! *string ) + return 0; + + while( ( c = *string++) ) + if( c < font->Quantity ) + { + if( c == '\n' ) /* EOL; reset the length of this line */ + { + if( length < this_line_length ) + length = this_line_length; + this_line_length = 0.0; + } + else /* Not an EOL, increment the length of this line */ + { + const SFG_StrokeChar *schar = font->Characters[ c ]; + if( schar ) + this_line_length += schar->Right; + } + } + if( length < this_line_length ) + length = this_line_length; + return length; +} +int FGAPIENTRY glutStrokeLength( void* fontID, const unsigned char* string ) +{ + return( int )( glutStrokeLengthf(fontID,string) + 0.5f ); +} + +/* + * Returns the height of a stroke font + */ +GLfloat FGAPIENTRY glutStrokeHeight( void* fontID ) +{ + SFG_StrokeFont* font; + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutStrokeHeight" ); + font = fghStrokeByID( fontID ); + if (!font) + { + fgWarning("glutStrokeHeight: stroke font 0x%08x not found. Make sure you're not passing a bitmap font.\n",fontID); + return 0.f; + } + return font->Height; +} + +/*** END OF FILE ***/ diff --git a/src/fg_font_data.c b/src/fg_font_data.c new file mode 100644 index 0000000..2f35496 --- /dev/null +++ b/src/fg_font_data.c @@ -0,0 +1,2043 @@ +/* + \file og_font_data.c + \brief Bitmapped font data for OpenGLUT fonts. +*/ + +/* + * This file has been automatically generated by the + * genfonts utility. + * + * The legal status of this file is a bit vague. The font glyphs + * themselves come from XFree86 v4.3.0 (as of this writing), and as + * part of the X server may be subject to the XFree86 copyrights. + * The original freeglut fonts were extracted by a utility written + * by Pawel W. Olszta (see below) and the generated fonts contained + * his copyright exclusively. Steve Baker asserts that Pawel + * assigned intellectual property rights to Steve Baker. Steve + * Baker also asserts that fonts cannot be copyrighted. He has + * neither stripped the copyright from the freeglut fonts nor + * formally retitled anything in his name. Since that time, the + * OpenGLUT project has branched from freeglut, and has made + * necessary modifications to Pawel's ``genfonts'' utility. + * To that extent, OpenGLUT may have some title to this file. + * What is fairly clear is that the font data is licensed under + * the XFree86 license (which is variously termed ``XFree'' and + * ``MIT'' by the freeglut project). It is believed that all + * title holders wish this file to be as useful as possible, and + * that either the ``XFree'' or ``MIT'' license works. + * + * Portions copyright (c) 2004, the OpenGLUT project contributors. + * OpenGLUT branched from freeglut in February, 2004. + * + * Copyright (c) 1999-2000 by Pawel W. Olszta + * Written by Pawel W. Olszta, + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Sotware. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" + +/* + * The following bitmapped fonts are defined in this file: + * + * 1. fgFontFixed8x13 + * -misc-fixed-medium-r-normal--13-120-75-75-C-80-iso8859-1 + * 2. fgFontFixed9x15 + * -misc-fixed-medium-r-normal--15-140-75-75-C-90-iso8859-1 + * 3. fgFontHelvetica10 + * -adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1 + * 4. fgFontHelvetica12 + * -adobe-helvetica-medium-r-normal--12-120-75-75-p-67-iso8859-1 + * 5. fgFontHelvetica18 + * -adobe-helvetica-medium-r-normal--18-180-75-75-p-98-iso8859-1 + * 6. fgFontTimesRoman10 + * -adobe-times-medium-r-normal--10-100-75-75-p-54-iso8859-1 + * 7. fgFontTimesRoman24 + * -adobe-times-medium-r-normal--24-240-75-75-p-124-iso8859-1 + */ + +static const GLubyte Fixed8x13_Character_000[] = { 8, 0, 0, 0,170, 0,130, 0,130, 0,130, 0,170, 0, 0}; +static const GLubyte Fixed8x13_Character_001[] = { 8, 0, 0, 0, 0, 16, 56,124,254,124, 56, 16, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_002[] = { 8, 0,170, 85,170, 85,170, 85,170, 85,170, 85,170, 85,170}; +static const GLubyte Fixed8x13_Character_003[] = { 8, 0, 0, 0, 4, 4, 4, 4,174,160,224,160,160, 0, 0}; +static const GLubyte Fixed8x13_Character_004[] = { 8, 0, 0, 0, 8, 8, 12, 8,142,128,192,128,224, 0, 0}; +static const GLubyte Fixed8x13_Character_005[] = { 8, 0, 0, 0, 10, 10, 12, 10,108,128,128,128, 96, 0, 0}; +static const GLubyte Fixed8x13_Character_006[] = { 8, 0, 0, 0, 8, 8, 12, 8,238,128,128,128,128, 0, 0}; +static const GLubyte Fixed8x13_Character_007[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 24, 36, 36, 24, 0, 0}; +static const GLubyte Fixed8x13_Character_008[] = { 8, 0, 0, 0, 0,124, 0, 16, 16,124, 16, 16, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_009[] = { 8, 0, 0, 0, 14, 8, 8, 8,168,160,160,160,192, 0, 0}; +static const GLubyte Fixed8x13_Character_010[] = { 8, 0, 0, 0, 4, 4, 4, 4, 46, 80, 80,136,136, 0, 0}; +static const GLubyte Fixed8x13_Character_011[] = { 8, 0, 0, 0, 0, 0, 0, 0,240, 16, 16, 16, 16, 16, 16}; +static const GLubyte Fixed8x13_Character_012[] = { 8, 0, 16, 16, 16, 16, 16, 16,240, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_013[] = { 8, 0, 16, 16, 16, 16, 16, 16, 31, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_014[] = { 8, 0, 0, 0, 0, 0, 0, 0, 31, 16, 16, 16, 16, 16, 16}; +static const GLubyte Fixed8x13_Character_015[] = { 8, 0, 16, 16, 16, 16, 16, 16,255, 16, 16, 16, 16, 16, 16}; +static const GLubyte Fixed8x13_Character_016[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255}; +static const GLubyte Fixed8x13_Character_017[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_018[] = { 8, 0, 0, 0, 0, 0, 0, 0,255, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_019[] = { 8, 0, 0, 0, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_020[] = { 8, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_021[] = { 8, 0, 16, 16, 16, 16, 16, 16, 31, 16, 16, 16, 16, 16, 16}; +static const GLubyte Fixed8x13_Character_022[] = { 8, 0, 16, 16, 16, 16, 16, 16,240, 16, 16, 16, 16, 16, 16}; +static const GLubyte Fixed8x13_Character_023[] = { 8, 0, 0, 0, 0, 0, 0, 0,255, 16, 16, 16, 16, 16, 16}; +static const GLubyte Fixed8x13_Character_024[] = { 8, 0, 16, 16, 16, 16, 16, 16,255, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_025[] = { 8, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; +static const GLubyte Fixed8x13_Character_026[] = { 8, 0, 0, 0,254, 0, 14, 48,192, 48, 14, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_027[] = { 8, 0, 0, 0,254, 0,224, 24, 6, 24,224, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_028[] = { 8, 0, 0, 0, 68, 68, 68, 68, 68,254, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_029[] = { 8, 0, 0, 0, 32, 32,126, 16, 8,126, 4, 4, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_030[] = { 8, 0, 0, 0,220, 98, 32, 32, 32,112, 32, 34, 28, 0, 0}; +static const GLubyte Fixed8x13_Character_031[] = { 8, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_032[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_033[] = { 8, 0, 0, 0, 16, 0, 16, 16, 16, 16, 16, 16, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_034[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 36, 36, 0, 0}; +static const GLubyte Fixed8x13_Character_035[] = { 8, 0, 0, 0, 0, 36, 36,126, 36,126, 36, 36, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_036[] = { 8, 0, 0, 0, 16,120, 20, 20, 56, 80, 80, 60, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_037[] = { 8, 0, 0, 0, 68, 42, 36, 16, 8, 8, 36, 82, 34, 0, 0}; +static const GLubyte Fixed8x13_Character_038[] = { 8, 0, 0, 0, 58, 68, 74, 48, 72, 72, 48, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_039[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 48, 56, 0, 0}; +static const GLubyte Fixed8x13_Character_040[] = { 8, 0, 0, 0, 4, 8, 8, 16, 16, 16, 8, 8, 4, 0, 0}; +static const GLubyte Fixed8x13_Character_041[] = { 8, 0, 0, 0, 32, 16, 16, 8, 8, 8, 16, 16, 32, 0, 0}; +static const GLubyte Fixed8x13_Character_042[] = { 8, 0, 0, 0, 0, 0, 36, 24,126, 24, 36, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_043[] = { 8, 0, 0, 0, 0, 0, 16, 16,124, 16, 16, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_044[] = { 8, 0, 0, 64, 48, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_045[] = { 8, 0, 0, 0, 0, 0, 0, 0,126, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_046[] = { 8, 0, 0, 16, 56, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_047[] = { 8, 0, 0, 0,128,128, 64, 32, 16, 8, 4, 2, 2, 0, 0}; +static const GLubyte Fixed8x13_Character_048[] = { 8, 0, 0, 0, 24, 36, 66, 66, 66, 66, 66, 36, 24, 0, 0}; +static const GLubyte Fixed8x13_Character_049[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 16, 80, 48, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_050[] = { 8, 0, 0, 0,126, 64, 32, 24, 4, 2, 66, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_051[] = { 8, 0, 0, 0, 60, 66, 2, 2, 28, 8, 4, 2,126, 0, 0}; +static const GLubyte Fixed8x13_Character_052[] = { 8, 0, 0, 0, 4, 4,126, 68, 68, 36, 20, 12, 4, 0, 0}; +static const GLubyte Fixed8x13_Character_053[] = { 8, 0, 0, 0, 60, 66, 2, 2, 98, 92, 64, 64,126, 0, 0}; +static const GLubyte Fixed8x13_Character_054[] = { 8, 0, 0, 0, 60, 66, 66, 98, 92, 64, 64, 32, 28, 0, 0}; +static const GLubyte Fixed8x13_Character_055[] = { 8, 0, 0, 0, 32, 32, 16, 16, 8, 8, 4, 2,126, 0, 0}; +static const GLubyte Fixed8x13_Character_056[] = { 8, 0, 0, 0, 60, 66, 66, 66, 60, 66, 66, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_057[] = { 8, 0, 0, 0, 56, 4, 2, 2, 58, 70, 66, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_058[] = { 8, 0, 0, 16, 56, 16, 0, 0, 16, 56, 16, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_059[] = { 8, 0, 0, 64, 48, 56, 0, 0, 16, 56, 16, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_060[] = { 8, 0, 0, 0, 2, 4, 8, 16, 32, 16, 8, 4, 2, 0, 0}; +static const GLubyte Fixed8x13_Character_061[] = { 8, 0, 0, 0, 0, 0,126, 0, 0,126, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_062[] = { 8, 0, 0, 0, 64, 32, 16, 8, 4, 8, 16, 32, 64, 0, 0}; +static const GLubyte Fixed8x13_Character_063[] = { 8, 0, 0, 0, 8, 0, 8, 8, 4, 2, 66, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_064[] = { 8, 0, 0, 0, 60, 64, 74, 86, 82, 78, 66, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_065[] = { 8, 0, 0, 0, 66, 66, 66,126, 66, 66, 66, 36, 24, 0, 0}; +static const GLubyte Fixed8x13_Character_066[] = { 8, 0, 0, 0,252, 66, 66, 66,124, 66, 66, 66,252, 0, 0}; +static const GLubyte Fixed8x13_Character_067[] = { 8, 0, 0, 0, 60, 66, 64, 64, 64, 64, 64, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_068[] = { 8, 0, 0, 0,252, 66, 66, 66, 66, 66, 66, 66,252, 0, 0}; +static const GLubyte Fixed8x13_Character_069[] = { 8, 0, 0, 0,126, 64, 64, 64,120, 64, 64, 64,126, 0, 0}; +static const GLubyte Fixed8x13_Character_070[] = { 8, 0, 0, 0, 64, 64, 64, 64,120, 64, 64, 64,126, 0, 0}; +static const GLubyte Fixed8x13_Character_071[] = { 8, 0, 0, 0, 58, 70, 66, 78, 64, 64, 64, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_072[] = { 8, 0, 0, 0, 66, 66, 66, 66,126, 66, 66, 66, 66, 0, 0}; +static const GLubyte Fixed8x13_Character_073[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 16, 16, 16,124, 0, 0}; +static const GLubyte Fixed8x13_Character_074[] = { 8, 0, 0, 0, 56, 68, 4, 4, 4, 4, 4, 4, 31, 0, 0}; +static const GLubyte Fixed8x13_Character_075[] = { 8, 0, 0, 0, 66, 68, 72, 80, 96, 80, 72, 68, 66, 0, 0}; +static const GLubyte Fixed8x13_Character_076[] = { 8, 0, 0, 0,126, 64, 64, 64, 64, 64, 64, 64, 64, 0, 0}; +static const GLubyte Fixed8x13_Character_077[] = { 8, 0, 0, 0,130,130,130,146,146,170,198,130,130, 0, 0}; +static const GLubyte Fixed8x13_Character_078[] = { 8, 0, 0, 0, 66, 66, 66, 70, 74, 82, 98, 66, 66, 0, 0}; +static const GLubyte Fixed8x13_Character_079[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_080[] = { 8, 0, 0, 0, 64, 64, 64, 64,124, 66, 66, 66,124, 0, 0}; +static const GLubyte Fixed8x13_Character_081[] = { 8, 0, 0, 2, 60, 74, 82, 66, 66, 66, 66, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_082[] = { 8, 0, 0, 0, 66, 68, 72, 80,124, 66, 66, 66,124, 0, 0}; +static const GLubyte Fixed8x13_Character_083[] = { 8, 0, 0, 0, 60, 66, 2, 2, 60, 64, 64, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_084[] = { 8, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16,254, 0, 0}; +static const GLubyte Fixed8x13_Character_085[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 66, 0, 0}; +static const GLubyte Fixed8x13_Character_086[] = { 8, 0, 0, 0, 16, 40, 40, 40, 68, 68, 68,130,130, 0, 0}; +static const GLubyte Fixed8x13_Character_087[] = { 8, 0, 0, 0, 68,170,146,146,146,130,130,130,130, 0, 0}; +static const GLubyte Fixed8x13_Character_088[] = { 8, 0, 0, 0,130,130, 68, 40, 16, 40, 68,130,130, 0, 0}; +static const GLubyte Fixed8x13_Character_089[] = { 8, 0, 0, 0, 16, 16, 16, 16, 16, 40, 68,130,130, 0, 0}; +static const GLubyte Fixed8x13_Character_090[] = { 8, 0, 0, 0,126, 64, 64, 32, 16, 8, 4, 2,126, 0, 0}; +static const GLubyte Fixed8x13_Character_091[] = { 8, 0, 0, 0, 60, 32, 32, 32, 32, 32, 32, 32, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_092[] = { 8, 0, 0, 0, 2, 2, 4, 8, 16, 32, 64,128,128, 0, 0}; +static const GLubyte Fixed8x13_Character_093[] = { 8, 0, 0, 0,120, 8, 8, 8, 8, 8, 8, 8,120, 0, 0}; +static const GLubyte Fixed8x13_Character_094[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 40, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_095[] = { 8, 0, 0,254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_096[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 24, 56, 0, 0}; +static const GLubyte Fixed8x13_Character_097[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2, 60, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_098[] = { 8, 0, 0, 0, 92, 98, 66, 66, 98, 92, 64, 64, 64, 0, 0}; +static const GLubyte Fixed8x13_Character_099[] = { 8, 0, 0, 0, 60, 66, 64, 64, 66, 60, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_100[] = { 8, 0, 0, 0, 58, 70, 66, 66, 70, 58, 2, 2, 2, 0, 0}; +static const GLubyte Fixed8x13_Character_101[] = { 8, 0, 0, 0, 60, 66, 64,126, 66, 60, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_102[] = { 8, 0, 0, 0, 32, 32, 32, 32,124, 32, 32, 34, 28, 0, 0}; +static const GLubyte Fixed8x13_Character_103[] = { 8, 0, 60, 66, 60, 64, 56, 68, 68, 58, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_104[] = { 8, 0, 0, 0, 66, 66, 66, 66, 98, 92, 64, 64, 64, 0, 0}; +static const GLubyte Fixed8x13_Character_105[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 48, 0, 16, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_106[] = { 8, 0, 56, 68, 68, 4, 4, 4, 4, 12, 0, 4, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_107[] = { 8, 0, 0, 0, 66, 68, 72,112, 72, 68, 64, 64, 64, 0, 0}; +static const GLubyte Fixed8x13_Character_108[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 16, 16, 16, 48, 0, 0}; +static const GLubyte Fixed8x13_Character_109[] = { 8, 0, 0, 0,130,146,146,146,146,236, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_110[] = { 8, 0, 0, 0, 66, 66, 66, 66, 98, 92, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_111[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 60, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_112[] = { 8, 0, 64, 64, 64, 92, 98, 66, 98, 92, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_113[] = { 8, 0, 2, 2, 2, 58, 70, 66, 70, 58, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_114[] = { 8, 0, 0, 0, 32, 32, 32, 32, 34, 92, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_115[] = { 8, 0, 0, 0, 60, 66, 12, 48, 66, 60, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_116[] = { 8, 0, 0, 0, 28, 34, 32, 32, 32,124, 32, 32, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_117[] = { 8, 0, 0, 0, 58, 68, 68, 68, 68, 68, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_118[] = { 8, 0, 0, 0, 16, 40, 40, 68, 68, 68, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_119[] = { 8, 0, 0, 0, 68,170,146,146,130,130, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_120[] = { 8, 0, 0, 0, 66, 36, 24, 24, 36, 66, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_121[] = { 8, 0, 60, 66, 2, 58, 70, 66, 66, 66, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_122[] = { 8, 0, 0, 0,126, 32, 16, 8, 4,126, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_123[] = { 8, 0, 0, 0, 14, 16, 16, 8, 48, 8, 16, 16, 14, 0, 0}; +static const GLubyte Fixed8x13_Character_124[] = { 8, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_125[] = { 8, 0, 0, 0,112, 8, 8, 16, 12, 16, 8, 8,112, 0, 0}; +static const GLubyte Fixed8x13_Character_126[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 84, 36, 0, 0}; +/* +static const GLubyte Fixed8x13_Character_127[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_128[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_129[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_130[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_131[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_132[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_133[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_134[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_135[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_136[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_137[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_138[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_139[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_140[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_141[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_142[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_143[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_144[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_145[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_146[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_147[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_148[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_149[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_150[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_151[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_152[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_153[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_154[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_155[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_156[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_157[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_158[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_159[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +*/ +static const GLubyte Fixed8x13_Character_160[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_161[] = { 8, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 0, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_162[] = { 8, 0, 0, 0, 0, 16, 56, 84, 80, 80, 84, 56, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_163[] = { 8, 0, 0, 0,220, 98, 32, 32, 32,112, 32, 34, 28, 0, 0}; +static const GLubyte Fixed8x13_Character_164[] = { 8, 0, 0, 0, 0, 66, 60, 36, 36, 60, 66, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_165[] = { 8, 0, 0, 0, 16, 16,124, 16,124, 40, 68,130,130, 0, 0}; +static const GLubyte Fixed8x13_Character_166[] = { 8, 0, 0, 0, 16, 16, 16, 16, 0, 16, 16, 16, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_167[] = { 8, 0, 0, 0, 24, 36, 4, 24, 36, 36, 24, 32, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_168[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,108, 0, 0}; +static const GLubyte Fixed8x13_Character_169[] = { 8, 0, 0, 0, 0, 56, 68,146,170,162,170,146, 68, 56, 0}; +static const GLubyte Fixed8x13_Character_170[] = { 8, 0, 0, 0, 0, 0,124, 0, 60, 68, 60, 4, 56, 0, 0}; +static const GLubyte Fixed8x13_Character_171[] = { 8, 0, 0, 0, 0, 18, 36, 72,144, 72, 36, 18, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_172[] = { 8, 0, 0, 0, 0, 2, 2, 2,126, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_173[] = { 8, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_174[] = { 8, 0, 0, 0, 0, 56, 68,170,178,170,170,146, 68, 56, 0}; +static const GLubyte Fixed8x13_Character_175[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 0, 0}; +static const GLubyte Fixed8x13_Character_176[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 24, 36, 36, 24, 0, 0}; +static const GLubyte Fixed8x13_Character_177[] = { 8, 0, 0, 0, 0,124, 0, 16, 16,124, 16, 16, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_178[] = { 8, 0, 0, 0, 0, 0, 0, 0,120, 64, 48, 8, 72, 48, 0}; +static const GLubyte Fixed8x13_Character_179[] = { 8, 0, 0, 0, 0, 0, 0, 0, 48, 72, 8, 16, 72, 48, 0}; +static const GLubyte Fixed8x13_Character_180[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_181[] = { 8, 0, 0, 64, 90,102, 66, 66, 66, 66, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_182[] = { 8, 0, 0, 0, 20, 20, 20, 20, 52,116,116,116, 62, 0, 0}; +static const GLubyte Fixed8x13_Character_183[] = { 8, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_184[] = { 8, 0, 24, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_185[] = { 8, 0, 0, 0, 0, 0, 0, 0,112, 32, 32, 32, 96, 32, 0}; +static const GLubyte Fixed8x13_Character_186[] = { 8, 0, 0, 0, 0, 0, 0,120, 0, 48, 72, 72, 48, 0, 0}; +static const GLubyte Fixed8x13_Character_187[] = { 8, 0, 0, 0, 0,144, 72, 36, 18, 36, 72,144, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_188[] = { 8, 0, 0, 0, 6, 26, 18, 10,230, 66, 64, 64,192, 64, 0}; +static const GLubyte Fixed8x13_Character_189[] = { 8, 0, 0, 0, 30, 16, 12, 2,242, 76, 64, 64,192, 64, 0}; +static const GLubyte Fixed8x13_Character_190[] = { 8, 0, 0, 0, 6, 26, 18, 10,102,146, 16, 32,144, 96, 0}; +static const GLubyte Fixed8x13_Character_191[] = { 8, 0, 0, 0, 60, 66, 66, 64, 32, 16, 16, 0, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_192[] = { 8, 0, 0, 0, 66, 66,126, 66, 66, 36, 24, 0, 8, 16, 0}; +static const GLubyte Fixed8x13_Character_193[] = { 8, 0, 0, 0, 66, 66,126, 66, 66, 36, 24, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_194[] = { 8, 0, 0, 0, 66, 66,126, 66, 66, 36, 24, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_195[] = { 8, 0, 0, 0, 66, 66,126, 66, 66, 36, 24, 0, 76, 50, 0}; +static const GLubyte Fixed8x13_Character_196[] = { 8, 0, 0, 0, 66, 66,126, 66, 66, 36, 24, 0, 36, 36, 0}; +static const GLubyte Fixed8x13_Character_197[] = { 8, 0, 0, 0, 66, 66,126, 66, 66, 36, 24, 24, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_198[] = { 8, 0, 0, 0,158,144,144,240,156,144,144,144,110, 0, 0}; +static const GLubyte Fixed8x13_Character_199[] = { 8, 0, 16, 8, 60, 66, 64, 64, 64, 64, 64, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_200[] = { 8, 0, 0, 0,126, 64, 64,120, 64, 64,126, 0, 8, 16, 0}; +static const GLubyte Fixed8x13_Character_201[] = { 8, 0, 0, 0,126, 64, 64,120, 64, 64,126, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_202[] = { 8, 0, 0, 0,126, 64, 64,120, 64, 64,126, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_203[] = { 8, 0, 0, 0,126, 64, 64,120, 64, 64,126, 0, 36, 36, 0}; +static const GLubyte Fixed8x13_Character_204[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 16,124, 0, 16, 32, 0}; +static const GLubyte Fixed8x13_Character_205[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 16,124, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_206[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 16,124, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_207[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 16,124, 0, 40, 40, 0}; +static const GLubyte Fixed8x13_Character_208[] = { 8, 0, 0, 0,120, 68, 66, 66,226, 66, 66, 68,120, 0, 0}; +static const GLubyte Fixed8x13_Character_209[] = { 8, 0, 0, 0,130,134,138,146,162,194,130, 0,152,100, 0}; +static const GLubyte Fixed8x13_Character_210[] = { 8, 0, 0, 0,124,130,130,130,130,130,124, 0, 16, 32, 0}; +static const GLubyte Fixed8x13_Character_211[] = { 8, 0, 0, 0,124,130,130,130,130,130,124, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_212[] = { 8, 0, 0, 0,124,130,130,130,130,130,124, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_213[] = { 8, 0, 0, 0,124,130,130,130,130,130,124, 0,152,100, 0}; +static const GLubyte Fixed8x13_Character_214[] = { 8, 0, 0, 0,124,130,130,130,130,130,124, 0, 40, 40, 0}; +static const GLubyte Fixed8x13_Character_215[] = { 8, 0, 0, 0, 0, 66, 36, 24, 24, 36, 66, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_216[] = { 8, 0, 0, 64, 60, 98, 82, 82, 82, 74, 74, 70, 60, 2, 0}; +static const GLubyte Fixed8x13_Character_217[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 0, 8, 16, 0}; +static const GLubyte Fixed8x13_Character_218[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_219[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_220[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 0, 36, 36, 0}; +static const GLubyte Fixed8x13_Character_221[] = { 8, 0, 0, 0, 16, 16, 16, 16, 40, 68, 68, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_222[] = { 8, 0, 0, 0, 64, 64, 64,124, 66, 66, 66,124, 64, 0, 0}; +static const GLubyte Fixed8x13_Character_223[] = { 8, 0, 0, 0, 92, 66, 66, 76, 80, 72, 68, 68, 56, 0, 0}; +static const GLubyte Fixed8x13_Character_224[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2, 60, 0, 0, 8, 16, 0}; +static const GLubyte Fixed8x13_Character_225[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2, 60, 0, 0, 8, 4, 0}; +static const GLubyte Fixed8x13_Character_226[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2, 60, 0, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_227[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2, 60, 0, 0, 76, 50, 0}; +static const GLubyte Fixed8x13_Character_228[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2, 60, 0, 0, 36, 36, 0}; +static const GLubyte Fixed8x13_Character_229[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2, 60, 0, 24, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_230[] = { 8, 0, 0, 0,108,146,144,124, 18,108, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_231[] = { 8, 0, 16, 8, 60, 66, 64, 64, 66, 60, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_232[] = { 8, 0, 0, 0, 60, 66, 64,126, 66, 60, 0, 0, 8, 16, 0}; +static const GLubyte Fixed8x13_Character_233[] = { 8, 0, 0, 0, 60, 66, 64,126, 66, 60, 0, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_234[] = { 8, 0, 0, 0, 60, 66, 64,126, 66, 60, 0, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_235[] = { 8, 0, 0, 0, 60, 66, 64,126, 66, 60, 0, 0, 36, 36, 0}; +static const GLubyte Fixed8x13_Character_236[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 48, 0, 0, 16, 32, 0}; +static const GLubyte Fixed8x13_Character_237[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 48, 0, 0, 32, 16, 0}; +static const GLubyte Fixed8x13_Character_238[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 48, 0, 0, 72, 48, 0}; +static const GLubyte Fixed8x13_Character_239[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 48, 0, 0, 40, 40, 0}; +static const GLubyte Fixed8x13_Character_240[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 60, 4, 40, 24, 36, 0}; +static const GLubyte Fixed8x13_Character_241[] = { 8, 0, 0, 0, 66, 66, 66, 66, 98, 92, 0, 0, 76, 50, 0}; +static const GLubyte Fixed8x13_Character_242[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 60, 0, 0, 16, 32, 0}; +static const GLubyte Fixed8x13_Character_243[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 60, 0, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_244[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 60, 0, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_245[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 60, 0, 0, 76, 50, 0}; +static const GLubyte Fixed8x13_Character_246[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 60, 0, 0, 36, 36, 0}; +static const GLubyte Fixed8x13_Character_247[] = { 8, 0, 0, 0, 0, 16, 16, 0,124, 0, 16, 16, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_248[] = { 8, 0, 0, 64, 60, 98, 82, 74, 70, 60, 2, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_249[] = { 8, 0, 0, 0, 58, 68, 68, 68, 68, 68, 0, 0, 16, 32, 0}; +static const GLubyte Fixed8x13_Character_250[] = { 8, 0, 0, 0, 58, 68, 68, 68, 68, 68, 0, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_251[] = { 8, 0, 0, 0, 58, 68, 68, 68, 68, 68, 0, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_252[] = { 8, 0, 0, 0, 58, 68, 68, 68, 68, 68, 0, 0, 40, 40, 0}; +static const GLubyte Fixed8x13_Character_253[] = { 8, 0, 60, 66, 2, 58, 70, 66, 66, 66, 0, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_254[] = { 8, 0, 64, 64, 92, 98, 66, 66, 98, 92, 64, 64, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_255[] = { 8, 0, 60, 66, 2, 58, 70, 66, 66, 66, 0, 0, 36, 36, 0}; + +/* The font characters mapping: */ +static const GLubyte* Fixed8x13_Character_Map[] = {Fixed8x13_Character_000,Fixed8x13_Character_001,Fixed8x13_Character_002,Fixed8x13_Character_003,Fixed8x13_Character_004,Fixed8x13_Character_005,Fixed8x13_Character_006,Fixed8x13_Character_007,Fixed8x13_Character_008,Fixed8x13_Character_009,Fixed8x13_Character_010,Fixed8x13_Character_011,Fixed8x13_Character_012,Fixed8x13_Character_013,Fixed8x13_Character_014,Fixed8x13_Character_015, + Fixed8x13_Character_016,Fixed8x13_Character_017,Fixed8x13_Character_018,Fixed8x13_Character_019,Fixed8x13_Character_020,Fixed8x13_Character_021,Fixed8x13_Character_022,Fixed8x13_Character_023,Fixed8x13_Character_024,Fixed8x13_Character_025,Fixed8x13_Character_026,Fixed8x13_Character_027,Fixed8x13_Character_028,Fixed8x13_Character_029,Fixed8x13_Character_030,Fixed8x13_Character_031, + Fixed8x13_Character_032,Fixed8x13_Character_033,Fixed8x13_Character_034,Fixed8x13_Character_035,Fixed8x13_Character_036,Fixed8x13_Character_037,Fixed8x13_Character_038,Fixed8x13_Character_039,Fixed8x13_Character_040,Fixed8x13_Character_041,Fixed8x13_Character_042,Fixed8x13_Character_043,Fixed8x13_Character_044,Fixed8x13_Character_045,Fixed8x13_Character_046,Fixed8x13_Character_047, + Fixed8x13_Character_048,Fixed8x13_Character_049,Fixed8x13_Character_050,Fixed8x13_Character_051,Fixed8x13_Character_052,Fixed8x13_Character_053,Fixed8x13_Character_054,Fixed8x13_Character_055,Fixed8x13_Character_056,Fixed8x13_Character_057,Fixed8x13_Character_058,Fixed8x13_Character_059,Fixed8x13_Character_060,Fixed8x13_Character_061,Fixed8x13_Character_062,Fixed8x13_Character_063, + Fixed8x13_Character_064,Fixed8x13_Character_065,Fixed8x13_Character_066,Fixed8x13_Character_067,Fixed8x13_Character_068,Fixed8x13_Character_069,Fixed8x13_Character_070,Fixed8x13_Character_071,Fixed8x13_Character_072,Fixed8x13_Character_073,Fixed8x13_Character_074,Fixed8x13_Character_075,Fixed8x13_Character_076,Fixed8x13_Character_077,Fixed8x13_Character_078,Fixed8x13_Character_079, + Fixed8x13_Character_080,Fixed8x13_Character_081,Fixed8x13_Character_082,Fixed8x13_Character_083,Fixed8x13_Character_084,Fixed8x13_Character_085,Fixed8x13_Character_086,Fixed8x13_Character_087,Fixed8x13_Character_088,Fixed8x13_Character_089,Fixed8x13_Character_090,Fixed8x13_Character_091,Fixed8x13_Character_092,Fixed8x13_Character_093,Fixed8x13_Character_094,Fixed8x13_Character_095, + Fixed8x13_Character_096,Fixed8x13_Character_097,Fixed8x13_Character_098,Fixed8x13_Character_099,Fixed8x13_Character_100,Fixed8x13_Character_101,Fixed8x13_Character_102,Fixed8x13_Character_103,Fixed8x13_Character_104,Fixed8x13_Character_105,Fixed8x13_Character_106,Fixed8x13_Character_107,Fixed8x13_Character_108,Fixed8x13_Character_109,Fixed8x13_Character_110,Fixed8x13_Character_111, + Fixed8x13_Character_112,Fixed8x13_Character_113,Fixed8x13_Character_114,Fixed8x13_Character_115,Fixed8x13_Character_116,Fixed8x13_Character_117,Fixed8x13_Character_118,Fixed8x13_Character_119,Fixed8x13_Character_120,Fixed8x13_Character_121,Fixed8x13_Character_122,Fixed8x13_Character_123,Fixed8x13_Character_124,Fixed8x13_Character_125,Fixed8x13_Character_126,Fixed8x13_Character_032, + Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032, + Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032, + Fixed8x13_Character_160,Fixed8x13_Character_161,Fixed8x13_Character_162,Fixed8x13_Character_163,Fixed8x13_Character_164,Fixed8x13_Character_165,Fixed8x13_Character_166,Fixed8x13_Character_167,Fixed8x13_Character_168,Fixed8x13_Character_169,Fixed8x13_Character_170,Fixed8x13_Character_171,Fixed8x13_Character_172,Fixed8x13_Character_173,Fixed8x13_Character_174,Fixed8x13_Character_175, + Fixed8x13_Character_176,Fixed8x13_Character_177,Fixed8x13_Character_178,Fixed8x13_Character_179,Fixed8x13_Character_180,Fixed8x13_Character_181,Fixed8x13_Character_182,Fixed8x13_Character_183,Fixed8x13_Character_184,Fixed8x13_Character_185,Fixed8x13_Character_186,Fixed8x13_Character_187,Fixed8x13_Character_188,Fixed8x13_Character_189,Fixed8x13_Character_190,Fixed8x13_Character_191, + Fixed8x13_Character_192,Fixed8x13_Character_193,Fixed8x13_Character_194,Fixed8x13_Character_195,Fixed8x13_Character_196,Fixed8x13_Character_197,Fixed8x13_Character_198,Fixed8x13_Character_199,Fixed8x13_Character_200,Fixed8x13_Character_201,Fixed8x13_Character_202,Fixed8x13_Character_203,Fixed8x13_Character_204,Fixed8x13_Character_205,Fixed8x13_Character_206,Fixed8x13_Character_207, + Fixed8x13_Character_208,Fixed8x13_Character_209,Fixed8x13_Character_210,Fixed8x13_Character_211,Fixed8x13_Character_212,Fixed8x13_Character_213,Fixed8x13_Character_214,Fixed8x13_Character_215,Fixed8x13_Character_216,Fixed8x13_Character_217,Fixed8x13_Character_218,Fixed8x13_Character_219,Fixed8x13_Character_220,Fixed8x13_Character_221,Fixed8x13_Character_222,Fixed8x13_Character_223, + Fixed8x13_Character_224,Fixed8x13_Character_225,Fixed8x13_Character_226,Fixed8x13_Character_227,Fixed8x13_Character_228,Fixed8x13_Character_229,Fixed8x13_Character_230,Fixed8x13_Character_231,Fixed8x13_Character_232,Fixed8x13_Character_233,Fixed8x13_Character_234,Fixed8x13_Character_235,Fixed8x13_Character_236,Fixed8x13_Character_237,Fixed8x13_Character_238,Fixed8x13_Character_239, + Fixed8x13_Character_240,Fixed8x13_Character_241,Fixed8x13_Character_242,Fixed8x13_Character_243,Fixed8x13_Character_244,Fixed8x13_Character_245,Fixed8x13_Character_246,Fixed8x13_Character_247,Fixed8x13_Character_248,Fixed8x13_Character_249,Fixed8x13_Character_250,Fixed8x13_Character_251,Fixed8x13_Character_252,Fixed8x13_Character_253,Fixed8x13_Character_254,Fixed8x13_Character_255,NULL}; + +/* The font structure: */ +SFG_Font fgFontFixed8x13 = { "-misc-fixed-medium-r-normal--13-120-75-75-C-80-iso8859-1", 256, 14, Fixed8x13_Character_Map, 0, 3 }; + +static const GLubyte Fixed9x15_Character_000[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_001[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 28, 0, 62, 0,127, 0,255,128,127, 0, 62, 0, 28, 0, 8, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_002[] = { 9, 0, 0,170,128, 85, 0,170,128, 85, 0,170,128, 85, 0,170,128, 85, 0,170,128, 85, 0,170,128, 85, 0,170,128, 85, 0,170,128}; +static const GLubyte Fixed9x15_Character_003[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 4, 0, 4, 0, 31, 0, 0, 0, 72, 0, 72, 0,120, 0, 72, 0, 72, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_004[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 8, 0, 8, 0, 14, 0, 72, 0, 79, 0, 64, 0,112, 0, 64, 0,120, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_005[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 9, 0, 14, 0, 9, 0, 14, 0, 0, 0, 56, 0, 64, 0, 64, 0, 64, 0, 56, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_006[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 8, 0, 14, 0, 8, 0, 15, 0, 0, 0,120, 0, 64, 0, 64, 0, 64, 0, 64, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_007[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 18, 0, 18, 0, 12, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_008[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 0, 0, 0, 8, 0, 8, 0, 8, 0,127, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_009[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 68, 0, 76, 0, 84, 0,100, 0, 68, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_010[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 4, 0, 4, 0, 31, 0, 0, 0, 16, 0, 40, 0, 40, 0, 68, 0, 68, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_011[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0}; +static const GLubyte Fixed9x15_Character_012[] = { 9, 0, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0,248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_013[] = { 9, 0, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 15,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_014[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,128, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0}; +static const GLubyte Fixed9x15_Character_015[] = { 9, 0, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0,255,128, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0}; +static const GLubyte Fixed9x15_Character_016[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,128}; +static const GLubyte Fixed9x15_Character_017[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,128, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_018[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_019[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_020[] = { 9, 0, 0,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_021[] = { 9, 0, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 15,128, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0}; +static const GLubyte Fixed9x15_Character_022[] = { 9, 0, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0,248, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0}; +static const GLubyte Fixed9x15_Character_023[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,128, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0}; +static const GLubyte Fixed9x15_Character_024[] = { 9, 0, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_025[] = { 9, 0, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0}; +static const GLubyte Fixed9x15_Character_026[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 0, 0, 0, 3, 0, 28, 0, 96, 0, 28, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_027[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 0, 0, 0, 96, 0, 28, 0, 3, 0, 28, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_028[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 34, 0, 34, 0, 34, 0, 34, 0, 34, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_029[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 16, 0,127, 0, 8, 0,127, 0, 4, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_030[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, 81, 0, 48, 0, 16, 0, 16, 0,124, 0, 16, 0, 16, 0, 17, 0, 14, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_031[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_032[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_033[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 8, 0, 0, 0, 0, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_034[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 18, 0, 18, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_035[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 36, 0,126, 0, 36, 0, 36, 0,126, 0, 36, 0, 36, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_036[] = { 9, 0, 0, 0, 0, 0, 0, 8, 0, 62, 0, 73, 0, 9, 0, 9, 0, 10, 0, 28, 0, 40, 0, 72, 0, 73, 0, 62, 0, 8, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_037[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 66, 0, 37, 0, 37, 0, 18, 0, 8, 0, 8, 0, 36, 0, 82, 0, 82, 0, 33, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_038[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 74, 0, 68, 0, 74, 0, 49, 0, 48, 0, 72, 0, 72, 0, 72, 0, 48, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_039[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 8, 0, 4, 0, 6, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_040[] = { 9, 0, 0, 0, 0, 0, 0, 4, 0, 8, 0, 8, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 8, 0, 8, 0, 4, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_041[] = { 9, 0, 0, 0, 0, 0, 0, 16, 0, 8, 0, 8, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 8, 0, 8, 0, 16, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_042[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 73, 0, 42, 0, 28, 0, 42, 0, 73, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_043[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 8, 0, 8, 0,127, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_044[] = { 9, 0, 0, 8, 0, 4, 0, 4, 0, 12, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_045[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_046[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_047[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 32, 0, 32, 0, 16, 0, 8, 0, 8, 0, 4, 0, 2, 0, 2, 0, 1, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_048[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 34, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 34, 0, 28, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_049[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,127, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 72, 0, 40, 0, 24, 0, 8, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_050[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,127, 0, 64, 0, 32, 0, 16, 0, 8, 0, 4, 0, 2, 0, 65, 0, 65, 0, 62, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_051[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 1, 0, 1, 0, 1, 0, 14, 0, 4, 0, 2, 0, 1, 0,127, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_052[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 0,127, 0, 66, 0, 34, 0, 18, 0, 10, 0, 6, 0, 2, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_053[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 1, 0, 1, 0, 1, 0, 97, 0, 94, 0, 64, 0, 64, 0,127, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_054[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 65, 0, 65, 0, 97, 0, 94, 0, 64, 0, 64, 0, 32, 0, 30, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_055[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 32, 0, 16, 0, 16, 0, 8, 0, 4, 0, 2, 0, 1, 0, 1, 0,127, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_056[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 34, 0, 65, 0, 65, 0, 34, 0, 28, 0, 34, 0, 65, 0, 34, 0, 28, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_057[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 2, 0, 1, 0, 1, 0, 61, 0, 67, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_058[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 12, 0, 0, 0, 0, 0, 0, 0, 12, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_059[] = { 9, 0, 0, 8, 0, 4, 0, 4, 0, 12, 0, 12, 0, 0, 0, 0, 0, 0, 0, 12, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_060[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 0, 8, 0, 16, 0, 32, 0, 32, 0, 16, 0, 8, 0, 4, 0, 2, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_061[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 0, 0, 0, 0, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_062[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 16, 0, 8, 0, 4, 0, 2, 0, 2, 0, 4, 0, 8, 0, 16, 0, 32, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_063[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 8, 0, 4, 0, 2, 0, 1, 0, 65, 0, 65, 0, 62, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_064[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 64, 0, 64, 0, 77, 0, 83, 0, 81, 0, 79, 0, 65, 0, 65, 0, 62, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_065[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 65, 0, 65, 0,127, 0, 65, 0, 65, 0, 65, 0, 34, 0, 20, 0, 8, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_066[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,126, 0, 33, 0, 33, 0, 33, 0, 33, 0,126, 0, 33, 0, 33, 0, 33, 0,126, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_067[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 65, 0, 62, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_068[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,126, 0, 33, 0, 33, 0, 33, 0, 33, 0, 33, 0, 33, 0, 33, 0, 33, 0,126, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_069[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,127, 0, 32, 0, 32, 0, 32, 0, 32, 0, 60, 0, 32, 0, 32, 0, 32, 0,127, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_070[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 60, 0, 32, 0, 32, 0, 32, 0,127, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_071[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 65, 0, 65, 0, 71, 0, 64, 0, 64, 0, 64, 0, 65, 0, 62, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_072[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0,127, 0, 65, 0, 65, 0, 65, 0, 65, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_073[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 62, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_074[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 66, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 15,128, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_075[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 66, 0, 68, 0, 72, 0, 80, 0,112, 0, 72, 0, 68, 0, 66, 0, 65, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_076[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,127, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_077[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 65, 0, 65, 0, 73, 0, 73, 0, 85, 0, 85, 0, 99, 0, 65, 0, 65, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_078[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 65, 0, 65, 0, 67, 0, 69, 0, 73, 0, 81, 0, 97, 0, 65, 0, 65, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_079[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_080[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0,126, 0, 65, 0, 65, 0, 65, 0,126, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_081[] = { 9, 0, 0, 0, 0, 3, 0, 4, 0, 62, 0, 73, 0, 81, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_082[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 65, 0, 66, 0, 68, 0, 72, 0,126, 0, 65, 0, 65, 0, 65, 0,126, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_083[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 65, 0, 1, 0, 6, 0, 56, 0, 64, 0, 65, 0, 65, 0, 62, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_084[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0,127, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_085[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_086[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 20, 0, 20, 0, 20, 0, 34, 0, 34, 0, 34, 0, 65, 0, 65, 0, 65, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_087[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 85, 0, 73, 0, 73, 0, 73, 0, 73, 0, 65, 0, 65, 0, 65, 0, 65, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_088[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 65, 0, 34, 0, 20, 0, 8, 0, 8, 0, 20, 0, 34, 0, 65, 0, 65, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_089[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 20, 0, 34, 0, 65, 0, 65, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_090[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,127, 0, 64, 0, 64, 0, 32, 0, 16, 0, 8, 0, 4, 0, 2, 0, 1, 0,127, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_091[] = { 9, 0, 0, 0, 0, 0, 0, 30, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 30, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_092[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 2, 0, 4, 0, 8, 0, 8, 0, 16, 0, 32, 0, 32, 0, 64, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_093[] = { 9, 0, 0, 0, 0, 0, 0, 60, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 60, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_094[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 34, 0, 20, 0, 8, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_095[] = { 9, 0, 0, 0, 0, 0, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_096[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 8, 0, 16, 0, 48, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_097[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 67, 0, 65, 0, 63, 0, 1, 0, 1, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_098[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 94, 0, 97, 0, 65, 0, 65, 0, 65, 0, 97, 0, 94, 0, 64, 0, 64, 0, 64, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_099[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 64, 0, 64, 0, 64, 0, 65, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_100[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 67, 0, 65, 0, 65, 0, 65, 0, 67, 0, 61, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_101[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 64, 0, 64, 0,127, 0, 65, 0, 65, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_102[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 16, 0, 16, 0, 16, 0,124, 0, 16, 0, 16, 0, 17, 0, 17, 0, 14, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_103[] = { 9, 0, 0, 62, 0, 65, 0, 65, 0, 62, 0, 64, 0, 60, 0, 66, 0, 66, 0, 66, 0, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_104[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 97, 0, 94, 0, 64, 0, 64, 0, 64, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_105[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 56, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_106[] = { 9, 0, 0, 60, 0, 66, 0, 66, 0, 66, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 14, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_107[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 70, 0, 88, 0, 96, 0, 88, 0, 70, 0, 65, 0, 64, 0, 64, 0, 64, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_108[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 56, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_109[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 73, 0, 73, 0, 73, 0, 73, 0, 73, 0,118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_110[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 97, 0, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_111[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_112[] = { 9, 0, 0, 64, 0, 64, 0, 64, 0, 94, 0, 97, 0, 65, 0, 65, 0, 65, 0, 97, 0, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_113[] = { 9, 0, 0, 1, 0, 1, 0, 1, 0, 61, 0, 67, 0, 65, 0, 65, 0, 65, 0, 67, 0, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_114[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 32, 0, 32, 0, 32, 0, 33, 0, 49, 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_115[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 1, 0, 62, 0, 64, 0, 65, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_116[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 17, 0, 16, 0, 16, 0, 16, 0, 16, 0,126, 0, 16, 0, 16, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_117[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_118[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 20, 0, 20, 0, 34, 0, 34, 0, 65, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_119[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 85, 0, 73, 0, 73, 0, 73, 0, 65, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_120[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 34, 0, 20, 0, 8, 0, 20, 0, 34, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_121[] = { 9, 0, 0, 60, 0, 66, 0, 2, 0, 58, 0, 70, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_122[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,127, 0, 32, 0, 16, 0, 8, 0, 4, 0, 2, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_123[] = { 9, 0, 0, 0, 0, 0, 0, 7, 0, 8, 0, 8, 0, 8, 0, 4, 0, 24, 0, 24, 0, 4, 0, 8, 0, 8, 0, 8, 0, 7, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_124[] = { 9, 0, 0, 0, 0, 0, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_125[] = { 9, 0, 0, 0, 0, 0, 0,112, 0, 8, 0, 8, 0, 8, 0, 16, 0, 12, 0, 12, 0, 16, 0, 8, 0, 8, 0, 8, 0,112, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_126[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 0, 73, 0, 49, 0, 0, 0, 0, 0}; +/* +static const GLubyte Fixed9x15_Character_127[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_128[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_129[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_130[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_131[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_132[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_133[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_134[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_135[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_136[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_137[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_138[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_139[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_140[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_141[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_142[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_143[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_144[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_145[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_146[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_147[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_148[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_149[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_150[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_151[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_152[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_153[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_154[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_155[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_156[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_157[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_158[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_159[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0, 65, 0, 64, 0, 1, 0,109, 0, 0, 0, 0, 0}; +*/ +static const GLubyte Fixed9x15_Character_160[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_161[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0, 8, 0, 8, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_162[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 60, 0, 82, 0, 80, 0, 72, 0, 74, 0, 60, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_163[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, 81, 0, 48, 0, 16, 0, 16, 0,124, 0, 16, 0, 16, 0, 17, 0, 14, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_164[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 62, 0, 34, 0, 34, 0, 62, 0, 65, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_165[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 8, 0, 8, 0, 62, 0, 8, 0, 62, 0, 20, 0, 34, 0, 65, 0, 65, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_166[] = { 9, 0, 0, 0, 0, 0, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_167[] = { 9, 0, 0, 0, 0, 0, 0, 24, 0, 36, 0, 4, 0, 24, 0, 36, 0, 36, 0, 36, 0, 24, 0, 32, 0, 36, 0, 24, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_168[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 34, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_169[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 66, 0,153, 0,165, 0,161, 0,165, 0,153, 0, 66, 0, 60, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_170[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,124, 0, 0, 0, 60, 0, 72, 0, 56, 0, 72, 0, 48, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_171[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 18, 0, 36, 0, 72, 0, 72, 0, 36, 0, 18, 0, 9, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_172[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 0,126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_173[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_174[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 66, 0,165, 0,169, 0,185, 0,165, 0,185, 0, 66, 0, 60, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_175[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_176[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 18, 0, 18, 0, 12, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_177[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 0, 0, 0, 8, 0, 8, 0, 8, 0,127, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_178[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120, 0, 64, 0, 48, 0, 8, 0, 72, 0, 48, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_179[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 72, 0, 8, 0, 16, 0, 72, 0, 48, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_180[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 8, 0, 4, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_181[] = { 9, 0, 0, 0, 0, 64, 0, 64, 0, 93, 0, 99, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_182[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 61, 0, 69, 0, 69, 0, 69, 0, 63, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_183[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_184[] = { 9, 0, 0, 24, 0, 36, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_185[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,112, 0, 32, 0, 32, 0, 32, 0, 96, 0, 32, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_186[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,124, 0, 0, 0, 56, 0, 68, 0, 68, 0, 56, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_187[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 36, 0, 18, 0, 9, 0, 9, 0, 18, 0, 36, 0, 72, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_188[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 13, 0, 9, 0, 5, 0,115, 0, 33, 0, 32, 0, 32, 0, 96, 0, 32, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_189[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 8, 0, 6, 0, 1, 0,121, 0, 38, 0, 32, 0, 32, 0, 96, 0, 32, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_190[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 13, 0, 9, 0, 5, 0, 51, 0, 73, 0, 8, 0, 16, 0, 72, 0, 48, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_191[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 65, 0, 64, 0, 32, 0, 16, 0, 8, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_192[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 65, 0, 65, 0,127, 0, 65, 0, 65, 0, 34, 0, 28, 0, 0, 0, 8, 0, 16, 0, 32, 0}; +static const GLubyte Fixed9x15_Character_193[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 65, 0, 65, 0,127, 0, 65, 0, 65, 0, 34, 0, 28, 0, 0, 0, 8, 0, 4, 0, 2, 0}; +static const GLubyte Fixed9x15_Character_194[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 65, 0, 65, 0,127, 0, 65, 0, 65, 0, 34, 0, 28, 0, 0, 0, 34, 0, 20, 0, 8, 0}; +static const GLubyte Fixed9x15_Character_195[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 65, 0, 65, 0,127, 0, 65, 0, 65, 0, 34, 0, 28, 0, 0, 0, 78, 0, 49, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_196[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 65, 0, 65, 0,127, 0, 65, 0, 65, 0, 34, 0, 28, 0, 0, 0, 34, 0, 34, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_197[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 65, 0, 65, 0,127, 0, 65, 0, 65, 0, 34, 0, 20, 0, 28, 0, 34, 0, 28, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_198[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 79, 0, 72, 0, 72, 0, 72, 0,126, 0, 72, 0, 72, 0, 72, 0, 72, 0, 55, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_199[] = { 9, 0, 0, 24, 0, 36, 0, 12, 0, 62, 0, 65, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 65, 0, 62, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_200[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,127, 0, 32, 0, 32, 0, 32, 0, 60, 0, 32, 0, 32, 0,127, 0, 0, 0, 8, 0, 16, 0, 32, 0}; +static const GLubyte Fixed9x15_Character_201[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,127, 0, 32, 0, 32, 0, 32, 0, 60, 0, 32, 0, 32, 0,127, 0, 0, 0, 8, 0, 4, 0, 2, 0}; +static const GLubyte Fixed9x15_Character_202[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,127, 0, 32, 0, 32, 0, 32, 0, 60, 0, 32, 0, 32, 0,127, 0, 0, 0, 34, 0, 20, 0, 8, 0}; +static const GLubyte Fixed9x15_Character_203[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,127, 0, 32, 0, 32, 0, 32, 0, 60, 0, 32, 0, 32, 0,127, 0, 0, 0, 34, 0, 34, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_204[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 62, 0, 0, 0, 8, 0, 16, 0, 32, 0}; +static const GLubyte Fixed9x15_Character_205[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 62, 0, 0, 0, 8, 0, 4, 0, 2, 0}; +static const GLubyte Fixed9x15_Character_206[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 62, 0, 0, 0, 34, 0, 20, 0, 8, 0}; +static const GLubyte Fixed9x15_Character_207[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 62, 0, 0, 0, 34, 0, 34, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_208[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,124, 0, 33, 0, 33, 0, 33, 0, 33, 0,225, 0, 33, 0, 33, 0, 33, 0,124, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_209[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 67, 0, 69, 0, 73, 0, 73, 0, 81, 0, 97, 0, 65, 0, 0, 0, 78, 0, 49, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_210[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 8, 0, 16, 0, 32, 0}; +static const GLubyte Fixed9x15_Character_211[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 8, 0, 4, 0, 2, 0}; +static const GLubyte Fixed9x15_Character_212[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 34, 0, 20, 0, 8, 0}; +static const GLubyte Fixed9x15_Character_213[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 78, 0, 49, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_214[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 34, 0, 34, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_215[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 34, 0, 20, 0, 8, 0, 20, 0, 34, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_216[] = { 9, 0, 0, 0, 0, 0, 0, 64, 0, 62, 0, 97, 0, 81, 0, 81, 0, 73, 0, 73, 0, 69, 0, 69, 0, 67, 0, 62, 0, 1, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_217[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 0, 0, 8, 0, 16, 0, 32, 0}; +static const GLubyte Fixed9x15_Character_218[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 0, 0, 8, 0, 4, 0, 2, 0}; +static const GLubyte Fixed9x15_Character_219[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 0, 0, 34, 0, 20, 0, 8, 0}; +static const GLubyte Fixed9x15_Character_220[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 0, 0, 34, 0, 34, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_221[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 8, 0, 8, 0, 8, 0, 20, 0, 34, 0, 65, 0, 65, 0, 0, 0, 8, 0, 4, 0, 2, 0}; +static const GLubyte Fixed9x15_Character_222[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 64, 0, 64, 0,126, 0, 65, 0, 65, 0, 65, 0,126, 0, 64, 0, 64, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_223[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 34, 0, 34, 0, 34, 0, 36, 0,104, 0, 36, 0, 34, 0, 34, 0, 28, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_224[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 67, 0, 65, 0, 63, 0, 1, 0, 1, 0, 62, 0, 0, 0, 4, 0, 8, 0, 16, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_225[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 67, 0, 65, 0, 63, 0, 1, 0, 1, 0, 62, 0, 0, 0, 8, 0, 4, 0, 2, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_226[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 67, 0, 65, 0, 63, 0, 1, 0, 1, 0, 62, 0, 0, 0, 34, 0, 20, 0, 8, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_227[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 67, 0, 65, 0, 63, 0, 1, 0, 1, 0, 62, 0, 0, 0, 38, 0, 25, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_228[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 67, 0, 65, 0, 63, 0, 1, 0, 1, 0, 62, 0, 0, 0, 34, 0, 34, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_229[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 67, 0, 65, 0, 63, 0, 1, 0, 1, 0, 62, 0, 0, 0, 12, 0, 18, 0, 12, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_230[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, 73, 0, 72, 0, 62, 0, 9, 0, 73, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_231[] = { 9, 0, 0, 24, 0, 36, 0, 12, 0, 62, 0, 65, 0, 64, 0, 64, 0, 64, 0, 65, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_232[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 64, 0, 64, 0,127, 0, 65, 0, 65, 0, 62, 0, 0, 0, 8, 0, 16, 0, 32, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_233[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 64, 0, 64, 0,127, 0, 65, 0, 65, 0, 62, 0, 0, 0, 8, 0, 4, 0, 2, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_234[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 64, 0, 64, 0,127, 0, 65, 0, 65, 0, 62, 0, 0, 0, 34, 0, 20, 0, 8, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_235[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 64, 0, 64, 0,127, 0, 65, 0, 65, 0, 62, 0, 0, 0, 34, 0, 34, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_236[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 56, 0, 0, 0, 8, 0, 16, 0, 32, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_237[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 56, 0, 0, 0, 16, 0, 8, 0, 4, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_238[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 56, 0, 0, 0, 68, 0, 40, 0, 16, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_239[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 56, 0, 0, 0, 36, 0, 36, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_240[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 4, 0, 40, 0, 24, 0, 36, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_241[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 97, 0, 94, 0, 0, 0, 78, 0, 49, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_242[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 8, 0, 16, 0, 32, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_243[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 8, 0, 4, 0, 2, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_244[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 34, 0, 20, 0, 8, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_245[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 78, 0, 49, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_246[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 62, 0, 0, 0, 34, 0, 34, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_247[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 28, 0, 8, 0, 0, 0,127, 0, 0, 0, 8, 0, 28, 0, 8, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_248[] = { 9, 0, 0, 0, 0, 0, 0, 64, 0, 62, 0, 81, 0, 81, 0, 73, 0, 69, 0, 69, 0, 62, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_249[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 0, 0, 8, 0, 16, 0, 32, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_250[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 0, 0, 8, 0, 4, 0, 2, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_251[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 0, 0, 34, 0, 20, 0, 8, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_252[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 0, 0, 36, 0, 36, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_253[] = { 9, 0, 0, 60, 0, 66, 0, 2, 0, 58, 0, 70, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 0, 0, 16, 0, 8, 0, 4, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_254[] = { 9, 0, 0, 64, 0, 64, 0, 64, 0, 94, 0, 97, 0, 65, 0, 65, 0, 97, 0, 94, 0, 64, 0, 64, 0, 64, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_255[] = { 9, 0, 0, 60, 0, 66, 0, 2, 0, 58, 0, 70, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 0, 0, 36, 0, 36, 0, 0, 0, 0, 0}; + +/* The font characters mapping: */ +static const GLubyte* Fixed9x15_Character_Map[] = {Fixed9x15_Character_000,Fixed9x15_Character_001,Fixed9x15_Character_002,Fixed9x15_Character_003,Fixed9x15_Character_004,Fixed9x15_Character_005,Fixed9x15_Character_006,Fixed9x15_Character_007,Fixed9x15_Character_008,Fixed9x15_Character_009,Fixed9x15_Character_010,Fixed9x15_Character_011,Fixed9x15_Character_012,Fixed9x15_Character_013,Fixed9x15_Character_014,Fixed9x15_Character_015, + Fixed9x15_Character_016,Fixed9x15_Character_017,Fixed9x15_Character_018,Fixed9x15_Character_019,Fixed9x15_Character_020,Fixed9x15_Character_021,Fixed9x15_Character_022,Fixed9x15_Character_023,Fixed9x15_Character_024,Fixed9x15_Character_025,Fixed9x15_Character_026,Fixed9x15_Character_027,Fixed9x15_Character_028,Fixed9x15_Character_029,Fixed9x15_Character_030,Fixed9x15_Character_031, + Fixed9x15_Character_032,Fixed9x15_Character_033,Fixed9x15_Character_034,Fixed9x15_Character_035,Fixed9x15_Character_036,Fixed9x15_Character_037,Fixed9x15_Character_038,Fixed9x15_Character_039,Fixed9x15_Character_040,Fixed9x15_Character_041,Fixed9x15_Character_042,Fixed9x15_Character_043,Fixed9x15_Character_044,Fixed9x15_Character_045,Fixed9x15_Character_046,Fixed9x15_Character_047, + Fixed9x15_Character_048,Fixed9x15_Character_049,Fixed9x15_Character_050,Fixed9x15_Character_051,Fixed9x15_Character_052,Fixed9x15_Character_053,Fixed9x15_Character_054,Fixed9x15_Character_055,Fixed9x15_Character_056,Fixed9x15_Character_057,Fixed9x15_Character_058,Fixed9x15_Character_059,Fixed9x15_Character_060,Fixed9x15_Character_061,Fixed9x15_Character_062,Fixed9x15_Character_063, + Fixed9x15_Character_064,Fixed9x15_Character_065,Fixed9x15_Character_066,Fixed9x15_Character_067,Fixed9x15_Character_068,Fixed9x15_Character_069,Fixed9x15_Character_070,Fixed9x15_Character_071,Fixed9x15_Character_072,Fixed9x15_Character_073,Fixed9x15_Character_074,Fixed9x15_Character_075,Fixed9x15_Character_076,Fixed9x15_Character_077,Fixed9x15_Character_078,Fixed9x15_Character_079, + Fixed9x15_Character_080,Fixed9x15_Character_081,Fixed9x15_Character_082,Fixed9x15_Character_083,Fixed9x15_Character_084,Fixed9x15_Character_085,Fixed9x15_Character_086,Fixed9x15_Character_087,Fixed9x15_Character_088,Fixed9x15_Character_089,Fixed9x15_Character_090,Fixed9x15_Character_091,Fixed9x15_Character_092,Fixed9x15_Character_093,Fixed9x15_Character_094,Fixed9x15_Character_095, + Fixed9x15_Character_096,Fixed9x15_Character_097,Fixed9x15_Character_098,Fixed9x15_Character_099,Fixed9x15_Character_100,Fixed9x15_Character_101,Fixed9x15_Character_102,Fixed9x15_Character_103,Fixed9x15_Character_104,Fixed9x15_Character_105,Fixed9x15_Character_106,Fixed9x15_Character_107,Fixed9x15_Character_108,Fixed9x15_Character_109,Fixed9x15_Character_110,Fixed9x15_Character_111, + Fixed9x15_Character_112,Fixed9x15_Character_113,Fixed9x15_Character_114,Fixed9x15_Character_115,Fixed9x15_Character_116,Fixed9x15_Character_117,Fixed9x15_Character_118,Fixed9x15_Character_119,Fixed9x15_Character_120,Fixed9x15_Character_121,Fixed9x15_Character_122,Fixed9x15_Character_123,Fixed9x15_Character_124,Fixed9x15_Character_125,Fixed9x15_Character_126,Fixed9x15_Character_032, + Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032, + Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032,Fixed9x15_Character_032, + Fixed9x15_Character_160,Fixed9x15_Character_161,Fixed9x15_Character_162,Fixed9x15_Character_163,Fixed9x15_Character_164,Fixed9x15_Character_165,Fixed9x15_Character_166,Fixed9x15_Character_167,Fixed9x15_Character_168,Fixed9x15_Character_169,Fixed9x15_Character_170,Fixed9x15_Character_171,Fixed9x15_Character_172,Fixed9x15_Character_173,Fixed9x15_Character_174,Fixed9x15_Character_175, + Fixed9x15_Character_176,Fixed9x15_Character_177,Fixed9x15_Character_178,Fixed9x15_Character_179,Fixed9x15_Character_180,Fixed9x15_Character_181,Fixed9x15_Character_182,Fixed9x15_Character_183,Fixed9x15_Character_184,Fixed9x15_Character_185,Fixed9x15_Character_186,Fixed9x15_Character_187,Fixed9x15_Character_188,Fixed9x15_Character_189,Fixed9x15_Character_190,Fixed9x15_Character_191, + Fixed9x15_Character_192,Fixed9x15_Character_193,Fixed9x15_Character_194,Fixed9x15_Character_195,Fixed9x15_Character_196,Fixed9x15_Character_197,Fixed9x15_Character_198,Fixed9x15_Character_199,Fixed9x15_Character_200,Fixed9x15_Character_201,Fixed9x15_Character_202,Fixed9x15_Character_203,Fixed9x15_Character_204,Fixed9x15_Character_205,Fixed9x15_Character_206,Fixed9x15_Character_207, + Fixed9x15_Character_208,Fixed9x15_Character_209,Fixed9x15_Character_210,Fixed9x15_Character_211,Fixed9x15_Character_212,Fixed9x15_Character_213,Fixed9x15_Character_214,Fixed9x15_Character_215,Fixed9x15_Character_216,Fixed9x15_Character_217,Fixed9x15_Character_218,Fixed9x15_Character_219,Fixed9x15_Character_220,Fixed9x15_Character_221,Fixed9x15_Character_222,Fixed9x15_Character_223, + Fixed9x15_Character_224,Fixed9x15_Character_225,Fixed9x15_Character_226,Fixed9x15_Character_227,Fixed9x15_Character_228,Fixed9x15_Character_229,Fixed9x15_Character_230,Fixed9x15_Character_231,Fixed9x15_Character_232,Fixed9x15_Character_233,Fixed9x15_Character_234,Fixed9x15_Character_235,Fixed9x15_Character_236,Fixed9x15_Character_237,Fixed9x15_Character_238,Fixed9x15_Character_239, + Fixed9x15_Character_240,Fixed9x15_Character_241,Fixed9x15_Character_242,Fixed9x15_Character_243,Fixed9x15_Character_244,Fixed9x15_Character_245,Fixed9x15_Character_246,Fixed9x15_Character_247,Fixed9x15_Character_248,Fixed9x15_Character_249,Fixed9x15_Character_250,Fixed9x15_Character_251,Fixed9x15_Character_252,Fixed9x15_Character_253,Fixed9x15_Character_254,Fixed9x15_Character_255,NULL}; + +/* The font structure: */ +SFG_Font fgFontFixed9x15 = { "-misc-fixed-medium-r-normal--15-140-75-75-C-90-iso8859-1", 256, 16, Fixed9x15_Character_Map, 0, 4 }; + +/* +static const GLubyte Helvetica10_Character_000[] = { 8, 0, 0, 0, 84, 0, 68, 0, 68, 0, 84, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_001[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_002[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_003[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_004[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_005[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_006[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_007[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_008[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_009[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_010[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_011[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_012[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_013[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_014[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_015[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_016[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_017[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_018[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_019[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_020[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_021[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_022[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_023[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_024[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_025[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_026[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_027[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_028[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_029[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_030[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_031[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +*/ +static const GLubyte Helvetica10_Character_032[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_033[] = { 3, 0, 0, 0, 64, 0, 64, 64, 64, 64, 64, 64, 0, 0, 0}; +static const GLubyte Helvetica10_Character_034[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 80, 0, 0, 0}; +static const GLubyte Helvetica10_Character_035[] = { 6, 0, 0, 0, 80, 80,248, 40,124, 40, 40, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_036[] = { 6, 0, 0, 32,112,168, 40,112,160,168,112, 32, 0, 0, 0}; +static const GLubyte Helvetica10_Character_037[] = { 9, 0, 0, 0, 0, 0, 0, 38, 0, 41, 0, 22, 0, 16, 0, 8, 0,104, 0,148, 0,100, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_038[] = { 8, 0, 0, 0, 50, 76, 76, 82, 48, 40, 40, 16, 0, 0, 0}; +static const GLubyte Helvetica10_Character_039[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0, 64, 32, 32, 0, 0, 0}; +static const GLubyte Helvetica10_Character_040[] = { 4, 0, 32, 64, 64,128,128,128,128, 64, 64, 32, 0, 0, 0}; +static const GLubyte Helvetica10_Character_041[] = { 4, 0, 64, 32, 32, 16, 16, 16, 16, 32, 32, 64, 0, 0, 0}; +static const GLubyte Helvetica10_Character_042[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0,160, 64,160, 0, 0, 0}; +static const GLubyte Helvetica10_Character_043[] = { 6, 0, 0, 0, 0, 32, 32,248, 32, 32, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_044[] = { 3, 0,128, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_045[] = { 7, 0, 0, 0, 0, 0, 0,124, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_046[] = { 3, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_047[] = { 3, 0, 0, 0,128,128, 64, 64, 64, 64, 32, 32, 0, 0, 0}; +static const GLubyte Helvetica10_Character_048[] = { 6, 0, 0, 0,112,136,136,136,136,136,136,112, 0, 0, 0}; +static const GLubyte Helvetica10_Character_049[] = { 6, 0, 0, 0, 32, 32, 32, 32, 32, 32, 96, 32, 0, 0, 0}; +static const GLubyte Helvetica10_Character_050[] = { 6, 0, 0, 0,248,128, 64, 48, 8, 8,136,112, 0, 0, 0}; +static const GLubyte Helvetica10_Character_051[] = { 6, 0, 0, 0,112,136, 8, 8, 48, 8,136,112, 0, 0, 0}; +static const GLubyte Helvetica10_Character_052[] = { 6, 0, 0, 0, 16, 16,248,144, 80, 80, 48, 16, 0, 0, 0}; +static const GLubyte Helvetica10_Character_053[] = { 6, 0, 0, 0,112,136, 8, 8,240,128,128,248, 0, 0, 0}; +static const GLubyte Helvetica10_Character_054[] = { 6, 0, 0, 0,112,136,136,200,176,128,136,112, 0, 0, 0}; +static const GLubyte Helvetica10_Character_055[] = { 6, 0, 0, 0, 64, 64, 32, 32, 16, 16, 8,248, 0, 0, 0}; +static const GLubyte Helvetica10_Character_056[] = { 6, 0, 0, 0,112,136,136,136,112,136,136,112, 0, 0, 0}; +static const GLubyte Helvetica10_Character_057[] = { 6, 0, 0, 0,112,136, 8,104,152,136,136,112, 0, 0, 0}; +static const GLubyte Helvetica10_Character_058[] = { 3, 0, 0, 0, 64, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_059[] = { 3, 0,128, 64, 64, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_060[] = { 6, 0, 0, 0, 0, 16, 32, 64, 32, 16, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_061[] = { 5, 0, 0, 0, 0, 0,240, 0,240, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_062[] = { 6, 0, 0, 0, 0, 64, 32, 16, 32, 64, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_063[] = { 6, 0, 0, 0, 32, 0, 32, 32, 16, 8, 72, 48, 0, 0, 0}; +static const GLubyte Helvetica10_Character_064[] = { 11, 0, 0, 62, 0, 64, 0,155, 0,164,128,164,128,162, 64,146, 64, 77, 64, 32,128, 31, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_065[] = { 7, 0, 0, 0,130,130,124, 68, 40, 40, 16, 16, 0, 0, 0}; +static const GLubyte Helvetica10_Character_066[] = { 7, 0, 0, 0,120, 68, 68, 68,120, 68, 68,120, 0, 0, 0}; +static const GLubyte Helvetica10_Character_067[] = { 8, 0, 0, 0, 60, 66, 64, 64, 64, 64, 66, 60, 0, 0, 0}; +static const GLubyte Helvetica10_Character_068[] = { 8, 0, 0, 0,120, 68, 66, 66, 66, 66, 68,120, 0, 0, 0}; +static const GLubyte Helvetica10_Character_069[] = { 7, 0, 0, 0,124, 64, 64, 64,124, 64, 64,124, 0, 0, 0}; +static const GLubyte Helvetica10_Character_070[] = { 6, 0, 0, 0, 64, 64, 64, 64,120, 64, 64,124, 0, 0, 0}; +static const GLubyte Helvetica10_Character_071[] = { 8, 0, 0, 0, 58, 70, 66, 70, 64, 64, 66, 60, 0, 0, 0}; +static const GLubyte Helvetica10_Character_072[] = { 8, 0, 0, 0, 66, 66, 66, 66,126, 66, 66, 66, 0, 0, 0}; +static const GLubyte Helvetica10_Character_073[] = { 3, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 64, 0, 0, 0}; +static const GLubyte Helvetica10_Character_074[] = { 5, 0, 0, 0, 96,144, 16, 16, 16, 16, 16, 16, 0, 0, 0}; +static const GLubyte Helvetica10_Character_075[] = { 7, 0, 0, 0, 68, 68, 72, 72,112, 80, 72, 68, 0, 0, 0}; +static const GLubyte Helvetica10_Character_076[] = { 6, 0, 0, 0,120, 64, 64, 64, 64, 64, 64, 64, 0, 0, 0}; +static const GLubyte Helvetica10_Character_077[] = { 9, 0, 0, 0, 0, 0, 0, 73, 0, 73, 0, 73, 0, 85, 0, 85, 0, 99, 0, 99, 0, 65, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_078[] = { 8, 0, 0, 0, 70, 70, 74, 74, 82, 82, 98, 98, 0, 0, 0}; +static const GLubyte Helvetica10_Character_079[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 60, 0, 0, 0}; +static const GLubyte Helvetica10_Character_080[] = { 7, 0, 0, 0, 64, 64, 64, 64,120, 68, 68,120, 0, 0, 0}; +static const GLubyte Helvetica10_Character_081[] = { 8, 0, 0, 1, 62, 70, 74, 66, 66, 66, 66, 60, 0, 0, 0}; +static const GLubyte Helvetica10_Character_082[] = { 7, 0, 0, 0, 68, 68, 68, 68,120, 68, 68,120, 0, 0, 0}; +static const GLubyte Helvetica10_Character_083[] = { 7, 0, 0, 0, 56, 68, 68, 4, 56, 64, 68, 56, 0, 0, 0}; +static const GLubyte Helvetica10_Character_084[] = { 5, 0, 0, 0, 32, 32, 32, 32, 32, 32, 32,248, 0, 0, 0}; +static const GLubyte Helvetica10_Character_085[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 0, 0, 0}; +static const GLubyte Helvetica10_Character_086[] = { 7, 0, 0, 0, 16, 40, 40, 68, 68, 68,130,130, 0, 0, 0}; +static const GLubyte Helvetica10_Character_087[] = { 9, 0, 0, 0, 0, 0, 0, 34, 0, 34, 0, 34, 0, 85, 0, 73, 0, 73, 0,136,128,136,128, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_088[] = { 7, 0, 0, 0, 68, 68, 40, 40, 16, 40, 68, 68, 0, 0, 0}; +static const GLubyte Helvetica10_Character_089[] = { 7, 0, 0, 0, 16, 16, 16, 40, 40, 68, 68,130, 0, 0, 0}; +static const GLubyte Helvetica10_Character_090[] = { 7, 0, 0, 0,124, 64, 32, 16, 16, 8, 4,124, 0, 0, 0}; +static const GLubyte Helvetica10_Character_091[] = { 3, 0, 96, 64, 64, 64, 64, 64, 64, 64, 64, 96, 0, 0, 0}; +static const GLubyte Helvetica10_Character_092[] = { 3, 0, 0, 0, 32, 32, 64, 64, 64, 64,128,128, 0, 0, 0}; +static const GLubyte Helvetica10_Character_093[] = { 3, 0,192, 64, 64, 64, 64, 64, 64, 64, 64,192, 0, 0, 0}; +static const GLubyte Helvetica10_Character_094[] = { 6, 0, 0, 0, 0, 0, 0,136, 80, 80, 32, 32, 0, 0, 0}; +static const GLubyte Helvetica10_Character_095[] = { 6, 0,252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_096[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0, 63, 64, 32, 0, 0, 0}; +static const GLubyte Helvetica10_Character_097[] = { 5, 0, 0, 0,104,144,144,112, 16,224, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_098[] = { 6, 0, 0, 0,176,200,136,136,200,176,128,128, 0, 0, 0}; +static const GLubyte Helvetica10_Character_099[] = { 5, 0, 0, 0, 96,144,128,128,144, 96, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_100[] = { 6, 0, 0, 0,104,152,136,136,152,104, 8, 8, 0, 0, 0}; +static const GLubyte Helvetica10_Character_101[] = { 5, 0, 0, 0, 96,144,128,240,144, 96, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_102[] = { 4, 0, 0, 0, 64, 64, 64, 64, 64,224, 64, 48, 0, 0, 0}; +static const GLubyte Helvetica10_Character_103[] = { 6, 0,112, 8,104,152,136,136,152,104, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_104[] = { 6, 0, 0, 0,136,136,136,136,200,176,128,128, 0, 0, 0}; +static const GLubyte Helvetica10_Character_105[] = { 2, 0, 0, 0,128,128,128,128,128,128, 0,128, 0, 0, 0}; +static const GLubyte Helvetica10_Character_106[] = { 2, 0, 0,128,128,128,128,128,128,128, 0,128, 0, 0, 0}; +static const GLubyte Helvetica10_Character_107[] = { 5, 0, 0, 0,144,144,160,192,160,144,128,128, 0, 0, 0}; +static const GLubyte Helvetica10_Character_108[] = { 2, 0, 0, 0,128,128,128,128,128,128,128,128, 0, 0, 0}; +static const GLubyte Helvetica10_Character_109[] = { 8, 0, 0, 0,146,146,146,146,146,236, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_110[] = { 6, 0, 0, 0,136,136,136,136,200,176, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_111[] = { 6, 0, 0, 0,112,136,136,136,136,112, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_112[] = { 6, 0,128,128,176,200,136,136,200,176, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_113[] = { 6, 0, 8, 8,104,152,136,136,152,104, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_114[] = { 4, 0, 0, 0,128,128,128,128,192,160, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_115[] = { 5, 0, 0, 0, 96,144, 16, 96,144, 96, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_116[] = { 4, 0, 0, 0, 96, 64, 64, 64, 64,224, 64, 64, 0, 0, 0}; +static const GLubyte Helvetica10_Character_117[] = { 5, 0, 0, 0,112,144,144,144,144,144, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_118[] = { 6, 0, 0, 0, 32, 32, 80, 80,136,136, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_119[] = { 8, 0, 0, 0, 40, 40, 84, 84,146,146, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_120[] = { 6, 0, 0, 0,136,136, 80, 32, 80,136, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_121[] = { 5, 0,128, 64, 64, 96,160,160,144,144, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_122[] = { 5, 0, 0, 0,240,128, 64, 32, 16,240, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_123[] = { 3, 0, 32, 64, 64, 64, 64,128, 64, 64, 64, 32, 0, 0, 0}; +static const GLubyte Helvetica10_Character_124[] = { 3, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 0, 0}; +static const GLubyte Helvetica10_Character_125[] = { 3, 0,128, 64, 64, 64, 64, 32, 64, 64, 64,128, 0, 0, 0}; +static const GLubyte Helvetica10_Character_126[] = { 7, 0, 0, 0, 0, 0, 0,152,100, 0, 0, 0, 0, 0, 0}; +/* +static const GLubyte Helvetica10_Character_127[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_128[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_129[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_130[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_131[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_132[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_133[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_134[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_135[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_136[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_137[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_138[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_139[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_140[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_141[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_142[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_143[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_144[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_145[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_146[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_147[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_148[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_149[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_150[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_151[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_152[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_153[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_154[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_155[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_156[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_157[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_158[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_159[] = { 13, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +*/ +static const GLubyte Helvetica10_Character_160[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_161[] = { 3, 0, 64, 64, 64, 64, 64, 64, 0, 64, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_162[] = { 6, 0, 0, 64,112,168,160,160,168,112, 16, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_163[] = { 6, 0, 0, 0,176, 72, 64, 64,224, 64, 72, 48, 0, 0, 0}; +static const GLubyte Helvetica10_Character_164[] = { 5, 0, 0, 0, 0,144, 96,144,144, 96,144, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_165[] = { 6, 0, 0, 0, 32,248, 32,248, 80, 80,136,136, 0, 0, 0}; +static const GLubyte Helvetica10_Character_166[] = { 3, 0, 64, 64, 64, 64, 0, 0, 64, 64, 64, 64, 0, 0, 0}; +static const GLubyte Helvetica10_Character_167[] = { 6, 0,112,136, 24,112,200,152,112,192,136,112, 0, 0, 0}; +static const GLubyte Helvetica10_Character_168[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 0, 0, 0}; +static const GLubyte Helvetica10_Character_169[] = { 9, 0, 0, 0, 0, 0, 0, 28, 0, 34, 0, 77, 0, 81, 0, 77, 0, 34, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_170[] = { 4, 0, 0, 0, 0, 0, 0,224, 0,160, 32,224, 0, 0, 0}; +static const GLubyte Helvetica10_Character_171[] = { 6, 0, 0, 0, 40, 80,160, 80, 40, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_172[] = { 7, 0, 0, 0, 0, 0, 4, 4,124, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_173[] = { 4, 0, 0, 0, 0, 0, 0,224, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_174[] = { 9, 0, 0, 0, 0, 0, 0, 28, 0, 34, 0, 85, 0, 89, 0, 93, 0, 34, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_175[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,224, 0, 0, 0}; +static const GLubyte Helvetica10_Character_176[] = { 4, 0, 0, 0, 0, 0, 0, 96,144,144, 96, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_177[] = { 6, 0, 0, 0,248, 0, 32, 32,248, 32, 32, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_178[] = { 3, 0, 0, 0, 0, 0, 0,224, 64,160, 96, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_179[] = { 3, 0, 0, 0, 0, 0, 0,192, 32, 64,224, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_180[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 64, 0, 0, 0}; +static const GLubyte Helvetica10_Character_181[] = { 5, 0,128,128,240,144,144,144,144,144, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_182[] = { 6, 0, 40, 40, 40, 40, 40,104,232,232,232,124, 0, 0, 0}; +static const GLubyte Helvetica10_Character_183[] = { 3, 0, 0, 0, 0, 0, 0,192, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_184[] = { 3, 0,192, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_185[] = { 3, 0, 0, 0, 0, 0, 0, 64, 64,192, 64, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_186[] = { 4, 0, 0, 0, 0, 0, 0,224, 0,224,160,224, 0, 0, 0}; +static const GLubyte Helvetica10_Character_187[] = { 6, 0, 0, 0,160, 80, 40, 80,160, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_188[] = { 9, 0, 0, 0, 0, 0, 0, 33, 0, 23,128, 19, 0, 9, 0, 72, 0, 68, 0,196, 0, 66, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_189[] = { 9, 0, 0, 0, 0, 0, 0, 39, 0, 18, 0, 21, 0, 11, 0, 72, 0, 68, 0,196, 0, 66, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_190[] = { 9, 0, 0, 0, 0, 0, 0, 33, 0, 23,128, 19, 0, 9, 0,200, 0, 36, 0, 68, 0,226, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_191[] = { 6, 0, 48, 72, 64, 32, 16, 16, 0, 16, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_192[] = { 7, 0, 0, 0,130,130,124, 68, 40, 40, 16, 16, 0, 16, 32}; +static const GLubyte Helvetica10_Character_193[] = { 7, 0, 0, 0,130,130,124, 68, 40, 40, 16, 16, 0, 16, 8}; +static const GLubyte Helvetica10_Character_194[] = { 7, 0, 0, 0,130,130,124, 68, 40, 40, 16, 16, 0, 40, 16}; +static const GLubyte Helvetica10_Character_195[] = { 7, 0, 0, 0,130,130,124, 68, 40, 40, 16, 16, 0, 40, 20}; +static const GLubyte Helvetica10_Character_196[] = { 7, 0, 0, 0,130,130,124, 68, 40, 40, 16, 16, 0, 40, 0}; +static const GLubyte Helvetica10_Character_197[] = { 7, 0, 0, 0,130,130,124, 68, 40, 40, 16, 16, 16, 40, 16}; +static const GLubyte Helvetica10_Character_198[] = { 10, 0, 0, 0, 0, 0, 0,143,128,136, 0,120, 0, 72, 0, 47,128, 40, 0, 24, 0, 31,128, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_199[] = { 8, 0, 24, 8, 60, 66, 64, 64, 64, 64, 66, 60, 0, 0, 0}; +static const GLubyte Helvetica10_Character_200[] = { 7, 0, 0, 0,124, 64, 64, 64,124, 64, 64,124, 0, 16, 32}; +static const GLubyte Helvetica10_Character_201[] = { 7, 0, 0, 0,124, 64, 64, 64,124, 64, 64,124, 0, 16, 8}; +static const GLubyte Helvetica10_Character_202[] = { 7, 0, 0, 0,124, 64, 64,124, 64, 64, 64,124, 0, 40, 16}; +static const GLubyte Helvetica10_Character_203[] = { 7, 0, 0, 0,124, 64, 64, 64,124, 64, 64,124, 0, 40, 0}; +static const GLubyte Helvetica10_Character_204[] = { 3, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 64, 0, 64,128}; +static const GLubyte Helvetica10_Character_205[] = { 3, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 64, 0, 64, 32}; +static const GLubyte Helvetica10_Character_206[] = { 3, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 64, 0,160, 64}; +static const GLubyte Helvetica10_Character_207[] = { 3, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 64, 0,160, 0}; +static const GLubyte Helvetica10_Character_208[] = { 8, 0, 0, 0,120, 68, 66, 66,242, 66, 68,120, 0, 0, 0}; +static const GLubyte Helvetica10_Character_209[] = { 8, 0, 0, 0, 70, 70, 74, 74, 82, 82, 98, 98, 0, 40, 20}; +static const GLubyte Helvetica10_Character_210[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 60, 0, 8, 16}; +static const GLubyte Helvetica10_Character_211[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 60, 0, 8, 4}; +static const GLubyte Helvetica10_Character_212[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 60, 0, 20, 8}; +static const GLubyte Helvetica10_Character_213[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 60, 0, 40, 20}; +static const GLubyte Helvetica10_Character_214[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 60, 0, 36, 0}; +static const GLubyte Helvetica10_Character_215[] = { 6, 0, 0, 0, 0,136, 80, 32, 80,136, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_216[] = { 8, 0, 0, 64, 60, 98, 82, 82, 74, 74, 70, 60, 2, 0, 0}; +static const GLubyte Helvetica10_Character_217[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 0, 8, 16}; +static const GLubyte Helvetica10_Character_218[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 0, 16, 8}; +static const GLubyte Helvetica10_Character_219[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 0, 20, 8}; +static const GLubyte Helvetica10_Character_220[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 0, 36, 0}; +static const GLubyte Helvetica10_Character_221[] = { 7, 0, 0, 0, 16, 16, 16, 40, 40, 68, 68,130, 0, 16, 8}; +static const GLubyte Helvetica10_Character_222[] = { 7, 0, 0, 0, 64, 64,120, 68, 68,120, 64, 64, 0, 0, 0}; +static const GLubyte Helvetica10_Character_223[] = { 5, 0, 0, 0,160,144,144,144,160,144,144, 96, 0, 0, 0}; +static const GLubyte Helvetica10_Character_224[] = { 5, 0, 0, 0,104,144,144,112, 16,224, 0, 32, 64, 0, 0}; +static const GLubyte Helvetica10_Character_225[] = { 5, 0, 0, 0,104,144,144,112, 16,224, 0, 32, 16, 0, 0}; +static const GLubyte Helvetica10_Character_226[] = { 5, 0, 0, 0,104,144,144,112, 16,224, 0, 80, 32, 0, 0}; +static const GLubyte Helvetica10_Character_227[] = { 5, 0, 0, 0,104,144,144,112, 16,224, 0,160, 80, 0, 0}; +static const GLubyte Helvetica10_Character_228[] = { 5, 0, 0, 0,104,144,144,112, 16,224, 0, 80, 0, 0, 0}; +static const GLubyte Helvetica10_Character_229[] = { 5, 0, 0, 0,104,144,144,112, 16,224, 32, 80, 32, 0, 0}; +static const GLubyte Helvetica10_Character_230[] = { 8, 0, 0, 0,108,146,144,126, 18,236, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_231[] = { 5, 0, 96, 32, 96,144,128,128,144, 96, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_232[] = { 5, 0, 0, 0, 96,144,128,240,144, 96, 0, 32, 64, 0, 0}; +static const GLubyte Helvetica10_Character_233[] = { 5, 0, 0, 0, 96,144,128,240,144, 96, 0, 64, 32, 0, 0}; +static const GLubyte Helvetica10_Character_234[] = { 5, 0, 0, 0, 96,144,128,240,144, 96, 0, 80, 32, 0, 0}; +static const GLubyte Helvetica10_Character_235[] = { 5, 0, 0, 0, 96,144,128,240,144, 96, 0, 80, 0, 0, 0}; +static const GLubyte Helvetica10_Character_236[] = { 2, 0, 0, 0,128,128,128,128,128,128, 0,128, 0, 0, 0}; +static const GLubyte Helvetica10_Character_237[] = { 2, 0, 0, 0,128,128,128,128,128,128, 0,128, 64, 0, 0}; +static const GLubyte Helvetica10_Character_238[] = { 2, 0, 0, 0,128,128,128,128,128,128, 0, 64,128, 0, 0}; +static const GLubyte Helvetica10_Character_239[] = { 2, 0, 0, 0, 64, 64, 64, 64, 64, 64, 0,160, 0, 0, 0}; +static const GLubyte Helvetica10_Character_240[] = { 6, 0, 0, 0,112,136,136,136,136,120,144, 96, 80, 0, 0}; +static const GLubyte Helvetica10_Character_241[] = { 5, 0, 0, 0,144,144,144,144,144,224, 0,160, 80, 0, 0}; +static const GLubyte Helvetica10_Character_242[] = { 6, 0, 0, 0,112,136,136,136,136,112, 0, 32, 64, 0, 0}; +static const GLubyte Helvetica10_Character_243[] = { 6, 0, 0, 0,112,136,136,136,136,112, 0, 32, 16, 0, 0}; +static const GLubyte Helvetica10_Character_244[] = { 6, 0, 0, 0,112,136,136,136,136,112, 0, 80, 32, 0, 0}; +static const GLubyte Helvetica10_Character_245[] = { 6, 0, 0, 0,112,136,136,136,136,112, 0, 80, 40, 0, 0}; +static const GLubyte Helvetica10_Character_246[] = { 6, 0, 0, 0,112,136,136,136,136,112, 0, 80, 0, 0, 0}; +static const GLubyte Helvetica10_Character_247[] = { 6, 0, 0, 0, 0, 32, 0,248, 0, 32, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_248[] = { 6, 0, 0, 0,112,136,200,168,152,116, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica10_Character_249[] = { 5, 0, 0, 0,112,144,144,144,144,144, 0, 32, 64, 0, 0}; +static const GLubyte Helvetica10_Character_250[] = { 5, 0, 0, 0,112,144,144,144,144,144, 0, 64, 32, 0, 0}; +static const GLubyte Helvetica10_Character_251[] = { 5, 0, 0, 0,112,144,144,144,144,144, 0, 80, 32, 0, 0}; +static const GLubyte Helvetica10_Character_252[] = { 5, 0, 0, 0,112,144,144,144,144,144, 0, 80, 0, 0, 0}; +static const GLubyte Helvetica10_Character_253[] = { 5, 0,128, 64, 64, 96,160,160,144,144, 0, 32, 16, 0, 0}; +static const GLubyte Helvetica10_Character_254[] = { 6, 0,128,128,176,200,136,136,200,176,128,128, 0, 0, 0}; +static const GLubyte Helvetica10_Character_255[] = { 5, 0,128, 64, 64, 96,160,160,144,144, 0, 80, 0, 0, 0}; + +/* The font characters mapping: */ +static const GLubyte* Helvetica10_Character_Map[] = {Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032, + Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032, + Helvetica10_Character_032,Helvetica10_Character_033,Helvetica10_Character_034,Helvetica10_Character_035,Helvetica10_Character_036,Helvetica10_Character_037,Helvetica10_Character_038,Helvetica10_Character_039,Helvetica10_Character_040,Helvetica10_Character_041,Helvetica10_Character_042,Helvetica10_Character_043,Helvetica10_Character_044,Helvetica10_Character_045,Helvetica10_Character_046,Helvetica10_Character_047, + Helvetica10_Character_048,Helvetica10_Character_049,Helvetica10_Character_050,Helvetica10_Character_051,Helvetica10_Character_052,Helvetica10_Character_053,Helvetica10_Character_054,Helvetica10_Character_055,Helvetica10_Character_056,Helvetica10_Character_057,Helvetica10_Character_058,Helvetica10_Character_059,Helvetica10_Character_060,Helvetica10_Character_061,Helvetica10_Character_062,Helvetica10_Character_063, + Helvetica10_Character_064,Helvetica10_Character_065,Helvetica10_Character_066,Helvetica10_Character_067,Helvetica10_Character_068,Helvetica10_Character_069,Helvetica10_Character_070,Helvetica10_Character_071,Helvetica10_Character_072,Helvetica10_Character_073,Helvetica10_Character_074,Helvetica10_Character_075,Helvetica10_Character_076,Helvetica10_Character_077,Helvetica10_Character_078,Helvetica10_Character_079, + Helvetica10_Character_080,Helvetica10_Character_081,Helvetica10_Character_082,Helvetica10_Character_083,Helvetica10_Character_084,Helvetica10_Character_085,Helvetica10_Character_086,Helvetica10_Character_087,Helvetica10_Character_088,Helvetica10_Character_089,Helvetica10_Character_090,Helvetica10_Character_091,Helvetica10_Character_092,Helvetica10_Character_093,Helvetica10_Character_094,Helvetica10_Character_095, + Helvetica10_Character_096,Helvetica10_Character_097,Helvetica10_Character_098,Helvetica10_Character_099,Helvetica10_Character_100,Helvetica10_Character_101,Helvetica10_Character_102,Helvetica10_Character_103,Helvetica10_Character_104,Helvetica10_Character_105,Helvetica10_Character_106,Helvetica10_Character_107,Helvetica10_Character_108,Helvetica10_Character_109,Helvetica10_Character_110,Helvetica10_Character_111, + Helvetica10_Character_112,Helvetica10_Character_113,Helvetica10_Character_114,Helvetica10_Character_115,Helvetica10_Character_116,Helvetica10_Character_117,Helvetica10_Character_118,Helvetica10_Character_119,Helvetica10_Character_120,Helvetica10_Character_121,Helvetica10_Character_122,Helvetica10_Character_123,Helvetica10_Character_124,Helvetica10_Character_125,Helvetica10_Character_126,Helvetica10_Character_032, + Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032, + Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032,Helvetica10_Character_032, + Helvetica10_Character_160,Helvetica10_Character_161,Helvetica10_Character_162,Helvetica10_Character_163,Helvetica10_Character_164,Helvetica10_Character_165,Helvetica10_Character_166,Helvetica10_Character_167,Helvetica10_Character_168,Helvetica10_Character_169,Helvetica10_Character_170,Helvetica10_Character_171,Helvetica10_Character_172,Helvetica10_Character_173,Helvetica10_Character_174,Helvetica10_Character_175, + Helvetica10_Character_176,Helvetica10_Character_177,Helvetica10_Character_178,Helvetica10_Character_179,Helvetica10_Character_180,Helvetica10_Character_181,Helvetica10_Character_182,Helvetica10_Character_183,Helvetica10_Character_184,Helvetica10_Character_185,Helvetica10_Character_186,Helvetica10_Character_187,Helvetica10_Character_188,Helvetica10_Character_189,Helvetica10_Character_190,Helvetica10_Character_191, + Helvetica10_Character_192,Helvetica10_Character_193,Helvetica10_Character_194,Helvetica10_Character_195,Helvetica10_Character_196,Helvetica10_Character_197,Helvetica10_Character_198,Helvetica10_Character_199,Helvetica10_Character_200,Helvetica10_Character_201,Helvetica10_Character_202,Helvetica10_Character_203,Helvetica10_Character_204,Helvetica10_Character_205,Helvetica10_Character_206,Helvetica10_Character_207, + Helvetica10_Character_208,Helvetica10_Character_209,Helvetica10_Character_210,Helvetica10_Character_211,Helvetica10_Character_212,Helvetica10_Character_213,Helvetica10_Character_214,Helvetica10_Character_215,Helvetica10_Character_216,Helvetica10_Character_217,Helvetica10_Character_218,Helvetica10_Character_219,Helvetica10_Character_220,Helvetica10_Character_221,Helvetica10_Character_222,Helvetica10_Character_223, + Helvetica10_Character_224,Helvetica10_Character_225,Helvetica10_Character_226,Helvetica10_Character_227,Helvetica10_Character_228,Helvetica10_Character_229,Helvetica10_Character_230,Helvetica10_Character_231,Helvetica10_Character_232,Helvetica10_Character_233,Helvetica10_Character_234,Helvetica10_Character_235,Helvetica10_Character_236,Helvetica10_Character_237,Helvetica10_Character_238,Helvetica10_Character_239, + Helvetica10_Character_240,Helvetica10_Character_241,Helvetica10_Character_242,Helvetica10_Character_243,Helvetica10_Character_244,Helvetica10_Character_245,Helvetica10_Character_246,Helvetica10_Character_247,Helvetica10_Character_248,Helvetica10_Character_249,Helvetica10_Character_250,Helvetica10_Character_251,Helvetica10_Character_252,Helvetica10_Character_253,Helvetica10_Character_254,Helvetica10_Character_255,NULL}; + +/* The font structure: */ +SFG_Font fgFontHelvetica10 = { "-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1", 256, 14, Helvetica10_Character_Map, 0, 3 }; + +/* +static const GLubyte Helvetica12_Character_000[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_001[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_002[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_003[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_004[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_005[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_006[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_007[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_008[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_009[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_010[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_011[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_012[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_013[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_014[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_015[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_016[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_017[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_018[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_019[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_020[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_021[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_022[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_023[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_024[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_025[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_026[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_027[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_028[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_029[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_030[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_031[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +*/ +static const GLubyte Helvetica12_Character_032[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_033[] = { 3, 0, 0, 0, 0, 64, 0, 64, 64, 64, 64, 64, 64, 64, 0, 0, 0}; +static const GLubyte Helvetica12_Character_034[] = { 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 80, 80, 0, 0, 0}; +static const GLubyte Helvetica12_Character_035[] = { 7, 0, 0, 0, 0, 80, 80, 80,252, 40,252, 40, 40, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_036[] = { 7, 0, 0, 0, 16, 56, 84, 84, 20, 56, 80, 84, 56, 16, 0, 0, 0}; +static const GLubyte Helvetica12_Character_037[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 17,128, 10, 64, 10, 64, 9,128, 4, 0, 52, 0, 74, 0, 74, 0, 49, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_038[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 70, 0, 66, 0, 69, 0, 40, 0, 24, 0, 36, 0, 36, 0, 24, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_039[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 32, 96, 0, 0, 0}; +static const GLubyte Helvetica12_Character_040[] = { 4, 0, 16, 32, 32, 64, 64, 64, 64, 64, 64, 32, 32, 16, 0, 0, 0}; +static const GLubyte Helvetica12_Character_041[] = { 4, 0,128, 64, 64, 32, 32, 32, 32, 32, 32, 64, 64,128, 0, 0, 0}; +static const GLubyte Helvetica12_Character_042[] = { 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 32, 80, 0, 0, 0}; +static const GLubyte Helvetica12_Character_043[] = { 7, 0, 0, 0, 0, 0, 16, 16,124, 16, 16, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_044[] = { 4, 0, 0, 64, 32, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_045[] = { 8, 0, 0, 0, 0, 0, 0, 0,124, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_046[] = { 3, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_047[] = { 4, 0, 0, 0, 0,128,128, 64, 64, 64, 32, 32, 16, 16, 0, 0, 0}; +static const GLubyte Helvetica12_Character_048[] = { 7, 0, 0, 0, 0, 56, 68, 68, 68, 68, 68, 68, 68, 56, 0, 0, 0}; +static const GLubyte Helvetica12_Character_049[] = { 7, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16,112, 16, 0, 0, 0}; +static const GLubyte Helvetica12_Character_050[] = { 7, 0, 0, 0, 0,124, 64, 64, 32, 16, 8, 4, 68, 56, 0, 0, 0}; +static const GLubyte Helvetica12_Character_051[] = { 7, 0, 0, 0, 0, 56, 68, 68, 4, 4, 24, 4, 68, 56, 0, 0, 0}; +static const GLubyte Helvetica12_Character_052[] = { 7, 0, 0, 0, 0, 8, 8,252,136, 72, 40, 40, 24, 8, 0, 0, 0}; +static const GLubyte Helvetica12_Character_053[] = { 7, 0, 0, 0, 0, 56, 68, 68, 4, 4,120, 64, 64,124, 0, 0, 0}; +static const GLubyte Helvetica12_Character_054[] = { 7, 0, 0, 0, 0, 56, 68, 68, 68,100, 88, 64, 68, 56, 0, 0, 0}; +static const GLubyte Helvetica12_Character_055[] = { 7, 0, 0, 0, 0, 32, 32, 16, 16, 16, 8, 8, 4,124, 0, 0, 0}; +static const GLubyte Helvetica12_Character_056[] = { 7, 0, 0, 0, 0, 56, 68, 68, 68, 68, 56, 68, 68, 56, 0, 0, 0}; +static const GLubyte Helvetica12_Character_057[] = { 7, 0, 0, 0, 0, 56, 68, 4, 4, 60, 68, 68, 68, 56, 0, 0, 0}; +static const GLubyte Helvetica12_Character_058[] = { 3, 0, 0, 0, 0, 64, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_059[] = { 3, 0, 0,128, 64, 64, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_060[] = { 7, 0, 0, 0, 0, 0, 12, 48,192, 48, 12, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_061[] = { 7, 0, 0, 0, 0, 0, 0,124, 0,124, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_062[] = { 7, 0, 0, 0, 0, 0, 96, 24, 6, 24, 96, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_063[] = { 7, 0, 0, 0, 0, 16, 0, 16, 16, 8, 8, 68, 68, 56, 0, 0, 0}; +static const GLubyte Helvetica12_Character_064[] = { 12, 0, 0, 0, 0, 0, 0, 31, 0, 32, 0, 77,128, 83, 64, 81, 32, 81, 32, 73, 32, 38,160, 48, 64, 15,128, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_065[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 65, 0, 65, 0, 62, 0, 34, 0, 34, 0, 20, 0, 20, 0, 8, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_066[] = { 8, 0, 0, 0, 0,124, 66, 66, 66,124, 66, 66, 66,124, 0, 0, 0}; +static const GLubyte Helvetica12_Character_067[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 33, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 33, 0, 30, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_068[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,124, 0, 66, 0, 65, 0, 65, 0, 65, 0, 65, 0, 65, 0, 66, 0,124, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_069[] = { 8, 0, 0, 0, 0,126, 64, 64, 64,126, 64, 64, 64,126, 0, 0, 0}; +static const GLubyte Helvetica12_Character_070[] = { 8, 0, 0, 0, 0, 64, 64, 64, 64,124, 64, 64, 64,126, 0, 0, 0}; +static const GLubyte Helvetica12_Character_071[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 35, 0, 65, 0, 65, 0, 71, 0, 64, 0, 64, 0, 33, 0, 30, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_072[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 65, 0, 65, 0, 65, 0,127, 0, 65, 0, 65, 0, 65, 0, 65, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_073[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 0, 0}; +static const GLubyte Helvetica12_Character_074[] = { 7, 0, 0, 0, 0, 56, 68, 68, 4, 4, 4, 4, 4, 4, 0, 0, 0}; +static const GLubyte Helvetica12_Character_075[] = { 8, 0, 0, 0, 0, 65, 66, 68, 72,112, 80, 72, 68, 66, 0, 0, 0}; +static const GLubyte Helvetica12_Character_076[] = { 7, 0, 0, 0, 0,124, 64, 64, 64, 64, 64, 64, 64, 64, 0, 0, 0}; +static const GLubyte Helvetica12_Character_077[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 68, 64, 68, 64, 74, 64, 74, 64, 81, 64, 81, 64, 96,192, 96,192, 64, 64, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_078[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 67, 0, 69, 0, 69, 0, 73, 0, 81, 0, 81, 0, 97, 0, 65, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_079[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 33, 0, 64,128, 64,128, 64,128, 64,128, 64,128, 33, 0, 30, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_080[] = { 8, 0, 0, 0, 0, 64, 64, 64, 64,124, 66, 66, 66,124, 0, 0, 0}; +static const GLubyte Helvetica12_Character_081[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 30,128, 33, 0, 66,128, 68,128, 64,128, 64,128, 64,128, 33, 0, 30, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_082[] = { 8, 0, 0, 0, 0, 66, 66, 66, 68,124, 66, 66, 66,124, 0, 0, 0}; +static const GLubyte Helvetica12_Character_083[] = { 8, 0, 0, 0, 0, 60, 66, 66, 2, 12, 48, 64, 66, 60, 0, 0, 0}; +static const GLubyte Helvetica12_Character_084[] = { 7, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16,254, 0, 0, 0}; +static const GLubyte Helvetica12_Character_085[] = { 8, 0, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 66, 0, 0, 0}; +static const GLubyte Helvetica12_Character_086[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 8, 0, 20, 0, 20, 0, 34, 0, 34, 0, 34, 0, 65, 0, 65, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_087[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 17, 0, 42,128, 42,128, 36,128, 68, 64, 68, 64, 68, 64, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_088[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 34, 0, 34, 0, 20, 0, 8, 0, 20, 0, 34, 0, 34, 0, 65, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_089[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 8, 0, 8, 0, 8, 0, 20, 0, 34, 0, 34, 0, 65, 0, 65, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_090[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,127, 0, 64, 0, 32, 0, 16, 0, 8, 0, 4, 0, 2, 0, 1, 0,127, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_091[] = { 3, 0, 96, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 96, 0, 0, 0}; +static const GLubyte Helvetica12_Character_092[] = { 4, 0, 0, 0, 0, 16, 16, 32, 32, 32, 64, 64,128,128, 0, 0, 0}; +static const GLubyte Helvetica12_Character_093[] = { 3, 0,192, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,192, 0, 0, 0}; +static const GLubyte Helvetica12_Character_094[] = { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,136, 80, 32, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_095[] = { 7, 0, 0,254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_096[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,128, 64, 0, 0, 0}; +static const GLubyte Helvetica12_Character_097[] = { 7, 0, 0, 0, 0, 58, 68, 68, 60, 4, 68, 56, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_098[] = { 7, 0, 0, 0, 0, 88,100, 68, 68, 68,100, 88, 64, 64, 0, 0, 0}; +static const GLubyte Helvetica12_Character_099[] = { 7, 0, 0, 0, 0, 56, 68, 64, 64, 64, 68, 56, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_100[] = { 7, 0, 0, 0, 0, 52, 76, 68, 68, 68, 76, 52, 4, 4, 0, 0, 0}; +static const GLubyte Helvetica12_Character_101[] = { 7, 0, 0, 0, 0, 56, 68, 64,124, 68, 68, 56, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_102[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64, 64, 64,224, 64, 48, 0, 0, 0}; +static const GLubyte Helvetica12_Character_103[] = { 7, 0, 56, 68, 4, 52, 76, 68, 68, 68, 76, 52, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_104[] = { 7, 0, 0, 0, 0, 68, 68, 68, 68, 68,100, 88, 64, 64, 0, 0, 0}; +static const GLubyte Helvetica12_Character_105[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 0, 64, 0, 0, 0}; +static const GLubyte Helvetica12_Character_106[] = { 3, 0,128, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 64, 0, 0, 0}; +static const GLubyte Helvetica12_Character_107[] = { 6, 0, 0, 0, 0, 68, 72, 80, 96, 96, 80, 72, 64, 64, 0, 0, 0}; +static const GLubyte Helvetica12_Character_108[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 0, 0}; +static const GLubyte Helvetica12_Character_109[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 73, 0, 73, 0, 73, 0, 73, 0,109, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_110[] = { 7, 0, 0, 0, 0, 68, 68, 68, 68, 68,100, 88, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_111[] = { 7, 0, 0, 0, 0, 56, 68, 68, 68, 68, 68, 56, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_112[] = { 7, 0, 64, 64, 64, 88,100, 68, 68, 68,100, 88, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_113[] = { 7, 0, 4, 4, 4, 52, 76, 68, 68, 68, 76, 52, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_114[] = { 4, 0, 0, 0, 0, 64, 64, 64, 64, 64, 96, 80, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_115[] = { 6, 0, 0, 0, 0, 48, 72, 8, 48, 64, 72, 48, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_116[] = { 3, 0, 0, 0, 0, 96, 64, 64, 64, 64, 64,224, 64, 64, 0, 0, 0}; +static const GLubyte Helvetica12_Character_117[] = { 7, 0, 0, 0, 0, 52, 76, 68, 68, 68, 68, 68, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_118[] = { 7, 0, 0, 0, 0, 16, 16, 40, 40, 68, 68, 68, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_119[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 34, 0, 85, 0, 73, 0, 73, 0,136,128,136,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_120[] = { 6, 0, 0, 0, 0,132,132, 72, 48, 48, 72,132, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_121[] = { 7, 0, 64, 32, 16, 16, 40, 40, 72, 68, 68, 68, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_122[] = { 6, 0, 0, 0, 0,120, 64, 32, 32, 16, 8,120, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_123[] = { 4, 0, 48, 64, 64, 64, 64, 64,128, 64, 64, 64, 64, 48, 0, 0, 0}; +static const GLubyte Helvetica12_Character_124[] = { 3, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 0, 0}; +static const GLubyte Helvetica12_Character_125[] = { 4, 0,192, 32, 32, 32, 32, 32, 16, 32, 32, 32, 32,192, 0, 0, 0}; +static const GLubyte Helvetica12_Character_126[] = { 7, 0, 0, 0, 0, 0, 0, 0,152,100, 0, 0, 0, 0, 0, 0, 0}; +/* +static const GLubyte Helvetica12_Character_127[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_128[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_129[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_130[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_131[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_132[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_133[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_134[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_135[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_136[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_137[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_138[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_139[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_140[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_141[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_142[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_143[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_144[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_145[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_146[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_147[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_148[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_149[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_150[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_151[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_152[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_153[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_154[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_155[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_156[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_157[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_158[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_159[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0}; +*/ +static const GLubyte Helvetica12_Character_160[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_161[] = { 3, 0, 64, 64, 64, 64, 64, 64, 64, 64, 0, 64, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_162[] = { 7, 0, 0, 0, 32, 56,100, 80, 80, 80, 84, 56, 8, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_163[] = { 7, 0, 0, 0, 0, 88, 36, 16, 16,120, 32, 32, 36, 24, 0, 0, 0}; +static const GLubyte Helvetica12_Character_164[] = { 7, 0, 0, 0, 0, 0,132,120, 72, 72,120,132, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_165[] = { 7, 0, 0, 0, 0, 16, 16,124, 16,124, 16, 40, 68, 68, 0, 0, 0}; +static const GLubyte Helvetica12_Character_166[] = { 3, 0, 0, 64, 64, 64, 64, 0, 0, 0, 64, 64, 64, 64, 0, 0, 0}; +static const GLubyte Helvetica12_Character_167[] = { 6, 0,112,136, 8, 48, 72,136,136,144, 96,128,136,112, 0, 0, 0}; +static const GLubyte Helvetica12_Character_168[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 0, 0, 0}; +static const GLubyte Helvetica12_Character_169[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 32,128, 78, 64, 81, 64, 80, 64, 81, 64, 78, 64, 32,128, 31, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_170[] = { 5, 0, 0, 0, 0, 0, 0, 0, 0,112, 0, 80, 16,112, 0, 0, 0}; +static const GLubyte Helvetica12_Character_171[] = { 7, 0, 0, 0, 0, 0, 20, 40, 80, 40, 20, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_172[] = { 8, 0, 0, 0, 0, 0, 0, 2, 2, 2,126, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_173[] = { 5, 0, 0, 0, 0, 0, 0, 0,240, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_174[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 32,128, 74, 64, 74, 64, 76, 64, 74, 64, 78, 64, 32,128, 31, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_175[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 0, 0, 0}; +static const GLubyte Helvetica12_Character_176[] = { 5, 0, 0, 0, 0, 0, 0, 0, 0, 96,144,144, 96, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_177[] = { 7, 0, 0, 0, 0,124, 0, 16, 16,124, 16, 16, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_178[] = { 4, 0, 0, 0, 0, 0, 0, 0,240, 64, 32,144, 96, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_179[] = { 4, 0, 0, 0, 0, 0, 0, 0,192, 32, 64, 32,224, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_180[] = { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 64, 0, 0}; +static const GLubyte Helvetica12_Character_181[] = { 7, 0, 64, 64, 64,116, 76, 68, 68, 68, 68, 68, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_182[] = { 7, 0, 40, 40, 40, 40, 40, 40,104,232,232,232,104, 60, 0, 0, 0}; +static const GLubyte Helvetica12_Character_183[] = { 3, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_184[] = { 3, 0,192, 32, 32, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_185[] = { 4, 0, 0, 0, 0, 0, 0, 0, 32, 32, 32, 96, 32, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_186[] = { 5, 0, 0, 0, 0, 0, 0, 0, 0,112, 0,112, 80,112, 0, 0, 0}; +static const GLubyte Helvetica12_Character_187[] = { 7, 0, 0, 0, 0, 0, 80, 40, 20, 40, 80, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_188[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 39,128, 21, 0, 19, 0, 73, 0, 68, 0, 68, 0,194, 0, 65, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_189[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 71,128, 34, 0, 17, 0, 20,128, 75, 0, 72, 0, 68, 0,194, 0, 65, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_190[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 23,128, 21, 0, 11, 0,201, 0, 36, 0, 68, 0, 34, 0,225, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_191[] = { 7, 0, 56, 68, 68, 32, 32, 16, 16, 0, 16, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_192[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 65, 0, 65, 0, 62, 0, 34, 0, 34, 0, 20, 0, 8, 0, 8, 0, 0, 0, 8, 0, 16, 0}; +static const GLubyte Helvetica12_Character_193[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 65, 0, 65, 0, 62, 0, 34, 0, 34, 0, 20, 0, 8, 0, 8, 0, 0, 0, 8, 0, 4, 0}; +static const GLubyte Helvetica12_Character_194[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 65, 0, 65, 0, 62, 0, 34, 0, 34, 0, 20, 0, 8, 0, 8, 0, 0, 0, 20, 0, 8, 0}; +static const GLubyte Helvetica12_Character_195[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 65, 0, 65, 0, 62, 0, 34, 0, 34, 0, 20, 0, 8, 0, 8, 0, 0, 0, 20, 0, 10, 0}; +static const GLubyte Helvetica12_Character_196[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 65, 0, 65, 0, 62, 0, 34, 0, 34, 0, 20, 0, 8, 0, 8, 0, 0, 0, 20, 0, 0, 0}; +static const GLubyte Helvetica12_Character_197[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 65, 0, 65, 0, 62, 0, 34, 0, 34, 0, 20, 0, 8, 0, 8, 0, 8, 0, 20, 0, 8, 0}; +static const GLubyte Helvetica12_Character_198[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 71,192, 68, 0, 68, 0, 60, 0, 39,192, 36, 0, 20, 0, 20, 0, 15,192, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_199[] = { 9, 0, 0, 24, 0, 4, 0, 4, 0, 30, 0, 33, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 33, 0, 30, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_200[] = { 8, 0, 0, 0, 0,126, 64, 64, 64,126, 64, 64, 64,126, 0, 8, 16}; +static const GLubyte Helvetica12_Character_201[] = { 8, 0, 0, 0, 0,126, 64, 64, 64,126, 64, 64, 64,126, 0, 8, 4}; +static const GLubyte Helvetica12_Character_202[] = { 8, 0, 0, 0, 0,126, 64, 64, 64,126, 64, 64, 64,126, 0, 20, 8}; +static const GLubyte Helvetica12_Character_203[] = { 8, 0, 0, 0, 0,126, 64, 64, 64,126, 64, 64, 64,126, 0, 20, 0}; +static const GLubyte Helvetica12_Character_204[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 64,128}; +static const GLubyte Helvetica12_Character_205[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 64, 32}; +static const GLubyte Helvetica12_Character_206[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0,160, 64}; +static const GLubyte Helvetica12_Character_207[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0,160, 0}; +static const GLubyte Helvetica12_Character_208[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,124, 0, 66, 0, 65, 0, 65, 0,241, 0, 65, 0, 65, 0, 66, 0,124, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_209[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 67, 0, 69, 0, 69, 0, 73, 0, 81, 0, 81, 0, 97, 0, 65, 0, 0, 0, 20, 0, 10, 0}; +static const GLubyte Helvetica12_Character_210[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 33, 0, 64,128, 64,128, 64,128, 64,128, 64,128, 33, 0, 30, 0, 0, 0, 4, 0, 8, 0}; +static const GLubyte Helvetica12_Character_211[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 33, 0, 64,128, 64,128, 64,128, 64,128, 64,128, 33, 0, 30, 0, 0, 0, 4, 0, 2, 0}; +static const GLubyte Helvetica12_Character_212[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 33, 0, 64,128, 64,128, 64,128, 64,128, 64,128, 33, 0, 30, 0, 0, 0, 10, 0, 4, 0}; +static const GLubyte Helvetica12_Character_213[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 33, 0, 64,128, 64,128, 64,128, 64,128, 64,128, 33, 0, 30, 0, 0, 0, 20, 0, 10, 0}; +static const GLubyte Helvetica12_Character_214[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 33, 0, 64,128, 64,128, 64,128, 64,128, 64,128, 33, 0, 30, 0, 0, 0, 18, 0, 0, 0}; +static const GLubyte Helvetica12_Character_215[] = { 7, 0, 0, 0, 0, 0, 68, 40, 16, 40, 68, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_216[] = { 10, 0, 0, 0, 0, 0, 0,128, 0, 94, 0, 33, 0, 80,128, 72,128, 68,128, 68,128, 66,128, 33, 0, 30,128, 0, 64, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_217[] = { 8, 0, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 66, 0, 8, 16}; +static const GLubyte Helvetica12_Character_218[] = { 8, 0, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 66, 0, 8, 4}; +static const GLubyte Helvetica12_Character_219[] = { 8, 0, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 66, 0, 20, 8}; +static const GLubyte Helvetica12_Character_220[] = { 8, 0, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 66, 0, 36, 0}; +static const GLubyte Helvetica12_Character_221[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 8, 0, 8, 0, 8, 0, 20, 0, 34, 0, 34, 0, 65, 0, 65, 0, 0, 0, 8, 0, 4, 0}; +static const GLubyte Helvetica12_Character_222[] = { 8, 0, 0, 0, 0, 64, 64,124, 66, 66, 66,124, 64, 64, 0, 0, 0}; +static const GLubyte Helvetica12_Character_223[] = { 7, 0, 0, 0, 0, 88, 68, 68, 68, 88, 68, 68, 68, 56, 0, 0, 0}; +static const GLubyte Helvetica12_Character_224[] = { 7, 0, 0, 0, 0, 58, 68, 68, 60, 4, 68, 56, 0, 8, 16, 0, 0}; +static const GLubyte Helvetica12_Character_225[] = { 7, 0, 0, 0, 0, 58, 68, 68, 60, 4, 68, 56, 0, 16, 8, 0, 0}; +static const GLubyte Helvetica12_Character_226[] = { 7, 0, 0, 0, 0, 58, 68, 68, 60, 4, 68, 56, 0, 40, 16, 0, 0}; +static const GLubyte Helvetica12_Character_227[] = { 7, 0, 0, 0, 0, 58, 68, 68, 60, 4, 68, 56, 0, 40, 20, 0, 0}; +static const GLubyte Helvetica12_Character_228[] = { 7, 0, 0, 0, 0, 58, 68, 68, 60, 4, 68, 56, 0, 40, 0, 0, 0}; +static const GLubyte Helvetica12_Character_229[] = { 7, 0, 0, 0, 0, 58, 68, 68, 60, 4, 68, 56, 24, 36, 24, 0, 0}; +static const GLubyte Helvetica12_Character_230[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 59,128, 68, 64, 68, 0, 63,192, 4, 64, 68, 64, 59,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_231[] = { 7, 0, 48, 8, 16, 56, 68, 64, 64, 64, 68, 56, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_232[] = { 7, 0, 0, 0, 0, 56, 68, 64,124, 68, 68, 56, 0, 16, 32, 0, 0}; +static const GLubyte Helvetica12_Character_233[] = { 7, 0, 0, 0, 0, 56, 68, 64,124, 68, 68, 56, 0, 16, 8, 0, 0}; +static const GLubyte Helvetica12_Character_234[] = { 7, 0, 0, 0, 0, 56, 68, 64,124, 68, 68, 56, 0, 40, 16, 0, 0}; +static const GLubyte Helvetica12_Character_235[] = { 7, 0, 0, 0, 0, 56, 68, 64,124, 68, 68, 56, 0, 40, 0, 0, 0}; +static const GLubyte Helvetica12_Character_236[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 0, 64,128, 0, 0}; +static const GLubyte Helvetica12_Character_237[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 0, 64, 32, 0, 0}; +static const GLubyte Helvetica12_Character_238[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 0,160, 64, 0, 0}; +static const GLubyte Helvetica12_Character_239[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 0,160, 0, 0, 0}; +static const GLubyte Helvetica12_Character_240[] = { 7, 0, 0, 0, 0, 56, 68, 68, 68, 68, 60, 4, 40, 24, 52, 0, 0}; +static const GLubyte Helvetica12_Character_241[] = { 7, 0, 0, 0, 0, 68, 68, 68, 68, 68,100, 88, 0, 40, 20, 0, 0}; +static const GLubyte Helvetica12_Character_242[] = { 7, 0, 0, 0, 0, 56, 68, 68, 68, 68, 68, 56, 0, 16, 32, 0, 0}; +static const GLubyte Helvetica12_Character_243[] = { 7, 0, 0, 0, 0, 56, 68, 68, 68, 68, 68, 56, 0, 16, 8, 0, 0}; +static const GLubyte Helvetica12_Character_244[] = { 7, 0, 0, 0, 0, 56, 68, 68, 68, 68, 68, 56, 0, 40, 16, 0, 0}; +static const GLubyte Helvetica12_Character_245[] = { 7, 0, 0, 0, 0, 56, 68, 68, 68, 68, 68, 56, 0, 40, 20, 0, 0}; +static const GLubyte Helvetica12_Character_246[] = { 7, 0, 0, 0, 0, 56, 68, 68, 68, 68, 68, 56, 0, 40, 0, 0, 0}; +static const GLubyte Helvetica12_Character_247[] = { 7, 0, 0, 0, 0, 0, 16, 0,124, 0, 16, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_248[] = { 7, 0, 0, 0, 0,184, 68,100, 84, 76, 68, 58, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica12_Character_249[] = { 7, 0, 0, 0, 0, 52, 76, 68, 68, 68, 68, 68, 0, 16, 32, 0, 0}; +static const GLubyte Helvetica12_Character_250[] = { 7, 0, 0, 0, 0, 52, 76, 68, 68, 68, 68, 68, 0, 16, 8, 0, 0}; +static const GLubyte Helvetica12_Character_251[] = { 7, 0, 0, 0, 0, 52, 76, 68, 68, 68, 68, 68, 0, 40, 16, 0, 0}; +static const GLubyte Helvetica12_Character_252[] = { 7, 0, 0, 0, 0, 52, 76, 68, 68, 68, 68, 68, 0, 40, 0, 0, 0}; +static const GLubyte Helvetica12_Character_253[] = { 7, 0, 64, 32, 16, 16, 40, 40, 72, 68, 68, 68, 0, 16, 8, 0, 0}; +static const GLubyte Helvetica12_Character_254[] = { 7, 0, 64, 64, 64, 88,100, 68, 68, 68,100, 88, 64, 64, 0, 0, 0}; +static const GLubyte Helvetica12_Character_255[] = { 7, 0, 96, 16, 16, 16, 24, 40, 40, 36, 68, 68, 0, 40, 0, 0, 0}; + +/* The font characters mapping: */ +static const GLubyte* Helvetica12_Character_Map[] = {Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032, + Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032, + Helvetica12_Character_032,Helvetica12_Character_033,Helvetica12_Character_034,Helvetica12_Character_035,Helvetica12_Character_036,Helvetica12_Character_037,Helvetica12_Character_038,Helvetica12_Character_039,Helvetica12_Character_040,Helvetica12_Character_041,Helvetica12_Character_042,Helvetica12_Character_043,Helvetica12_Character_044,Helvetica12_Character_045,Helvetica12_Character_046,Helvetica12_Character_047, + Helvetica12_Character_048,Helvetica12_Character_049,Helvetica12_Character_050,Helvetica12_Character_051,Helvetica12_Character_052,Helvetica12_Character_053,Helvetica12_Character_054,Helvetica12_Character_055,Helvetica12_Character_056,Helvetica12_Character_057,Helvetica12_Character_058,Helvetica12_Character_059,Helvetica12_Character_060,Helvetica12_Character_061,Helvetica12_Character_062,Helvetica12_Character_063, + Helvetica12_Character_064,Helvetica12_Character_065,Helvetica12_Character_066,Helvetica12_Character_067,Helvetica12_Character_068,Helvetica12_Character_069,Helvetica12_Character_070,Helvetica12_Character_071,Helvetica12_Character_072,Helvetica12_Character_073,Helvetica12_Character_074,Helvetica12_Character_075,Helvetica12_Character_076,Helvetica12_Character_077,Helvetica12_Character_078,Helvetica12_Character_079, + Helvetica12_Character_080,Helvetica12_Character_081,Helvetica12_Character_082,Helvetica12_Character_083,Helvetica12_Character_084,Helvetica12_Character_085,Helvetica12_Character_086,Helvetica12_Character_087,Helvetica12_Character_088,Helvetica12_Character_089,Helvetica12_Character_090,Helvetica12_Character_091,Helvetica12_Character_092,Helvetica12_Character_093,Helvetica12_Character_094,Helvetica12_Character_095, + Helvetica12_Character_096,Helvetica12_Character_097,Helvetica12_Character_098,Helvetica12_Character_099,Helvetica12_Character_100,Helvetica12_Character_101,Helvetica12_Character_102,Helvetica12_Character_103,Helvetica12_Character_104,Helvetica12_Character_105,Helvetica12_Character_106,Helvetica12_Character_107,Helvetica12_Character_108,Helvetica12_Character_109,Helvetica12_Character_110,Helvetica12_Character_111, + Helvetica12_Character_112,Helvetica12_Character_113,Helvetica12_Character_114,Helvetica12_Character_115,Helvetica12_Character_116,Helvetica12_Character_117,Helvetica12_Character_118,Helvetica12_Character_119,Helvetica12_Character_120,Helvetica12_Character_121,Helvetica12_Character_122,Helvetica12_Character_123,Helvetica12_Character_124,Helvetica12_Character_125,Helvetica12_Character_126,Helvetica12_Character_032, + Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032, + Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032,Helvetica12_Character_032, + Helvetica12_Character_160,Helvetica12_Character_161,Helvetica12_Character_162,Helvetica12_Character_163,Helvetica12_Character_164,Helvetica12_Character_165,Helvetica12_Character_166,Helvetica12_Character_167,Helvetica12_Character_168,Helvetica12_Character_169,Helvetica12_Character_170,Helvetica12_Character_171,Helvetica12_Character_172,Helvetica12_Character_173,Helvetica12_Character_174,Helvetica12_Character_175, + Helvetica12_Character_176,Helvetica12_Character_177,Helvetica12_Character_178,Helvetica12_Character_179,Helvetica12_Character_180,Helvetica12_Character_181,Helvetica12_Character_182,Helvetica12_Character_183,Helvetica12_Character_184,Helvetica12_Character_185,Helvetica12_Character_186,Helvetica12_Character_187,Helvetica12_Character_188,Helvetica12_Character_189,Helvetica12_Character_190,Helvetica12_Character_191, + Helvetica12_Character_192,Helvetica12_Character_193,Helvetica12_Character_194,Helvetica12_Character_195,Helvetica12_Character_196,Helvetica12_Character_197,Helvetica12_Character_198,Helvetica12_Character_199,Helvetica12_Character_200,Helvetica12_Character_201,Helvetica12_Character_202,Helvetica12_Character_203,Helvetica12_Character_204,Helvetica12_Character_205,Helvetica12_Character_206,Helvetica12_Character_207, + Helvetica12_Character_208,Helvetica12_Character_209,Helvetica12_Character_210,Helvetica12_Character_211,Helvetica12_Character_212,Helvetica12_Character_213,Helvetica12_Character_214,Helvetica12_Character_215,Helvetica12_Character_216,Helvetica12_Character_217,Helvetica12_Character_218,Helvetica12_Character_219,Helvetica12_Character_220,Helvetica12_Character_221,Helvetica12_Character_222,Helvetica12_Character_223, + Helvetica12_Character_224,Helvetica12_Character_225,Helvetica12_Character_226,Helvetica12_Character_227,Helvetica12_Character_228,Helvetica12_Character_229,Helvetica12_Character_230,Helvetica12_Character_231,Helvetica12_Character_232,Helvetica12_Character_233,Helvetica12_Character_234,Helvetica12_Character_235,Helvetica12_Character_236,Helvetica12_Character_237,Helvetica12_Character_238,Helvetica12_Character_239, + Helvetica12_Character_240,Helvetica12_Character_241,Helvetica12_Character_242,Helvetica12_Character_243,Helvetica12_Character_244,Helvetica12_Character_245,Helvetica12_Character_246,Helvetica12_Character_247,Helvetica12_Character_248,Helvetica12_Character_249,Helvetica12_Character_250,Helvetica12_Character_251,Helvetica12_Character_252,Helvetica12_Character_253,Helvetica12_Character_254,Helvetica12_Character_255,NULL}; + +/* The font structure: */ +SFG_Font fgFontHelvetica12 = { "-adobe-helvetica-medium-r-normal--12-120-75-75-p-67-iso8859-1", 256, 16, Helvetica12_Character_Map, 0, 4 }; + +/* +static const GLubyte Helvetica18_Character_000[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 64, 16, 0, 0, 64, 16, 0, 0, 64, 16, 0, 0, 64, 16, 0, 0, 64, 16, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_001[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_002[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_003[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_004[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_005[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_006[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_007[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_008[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_009[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_010[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_011[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_012[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_013[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_014[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_015[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_016[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_017[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_018[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_019[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_020[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_021[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_022[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_023[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_024[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_025[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_026[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_027[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_028[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_029[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_030[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_031[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +*/ +static const GLubyte Helvetica18_Character_032[] = { 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_033[] = { 6, 0, 0, 0, 0, 0, 48, 48, 0, 0, 32, 32, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_034[] = { 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,144,144,216,216,216, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_035[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 36, 0, 36, 0,255,128,255,128, 18, 0, 18, 0, 18, 0,127,192,127,192, 9, 0, 9, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_036[] = { 10, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 31, 0, 63,128,117,192,100,192, 4,192, 7,128, 31, 0, 60, 0,116, 0,100, 0,101,128, 63,128, 31, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_037[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 60, 12,126, 6,102, 6,102, 3,126, 3, 60, 1,128, 61,128,126,192,102,192,102, 96,126, 96, 60, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_038[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 56, 63,112,115,224, 97,192, 97,224, 99, 96,119, 96, 62, 0, 30, 0, 51, 0, 51, 0, 63, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_039[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 32, 32, 96, 96, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_040[] = { 6, 0, 8, 24, 48, 48, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 48, 48, 24, 8, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_041[] = { 6, 0, 64, 96, 48, 48, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 48, 48, 96, 64, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_042[] = { 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 56, 56,124, 16, 16, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_043[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 12, 0, 12, 0, 12, 0,127,128,127,128, 12, 0, 12, 0, 12, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_044[] = { 5, 0, 0, 64, 32, 32, 96, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_045[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,128,127,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_046[] = { 5, 0, 0, 0, 0, 0, 96, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_047[] = { 5, 0, 0, 0, 0, 0,192,192, 64, 64, 96, 96, 32, 32, 48, 48, 16, 16, 24, 24, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_048[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 63, 0, 51, 0, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 51, 0, 63, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_049[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 62, 0, 62, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_050[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,128,127,128, 96, 0,112, 0, 56, 0, 28, 0, 14, 0, 7, 0, 3,128, 1,128, 97,128,127, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_051[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 63, 0, 99,128, 97,128, 1,128, 3,128, 15, 0, 14, 0, 3, 0, 97,128, 97,128, 63, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_052[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,128, 1,128, 1,128,127,192,127,192, 97,128, 49,128, 25,128, 25,128, 13,128, 7,128, 3,128, 1,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_053[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0,127, 0, 99,128, 97,128, 1,128, 1,128, 99,128,127, 0,126, 0, 96, 0, 96, 0,127, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_054[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 63, 0,113,128, 97,128, 97,128, 97,128,127, 0,110, 0, 96, 0, 96, 0, 49,128, 63,128, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_055[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 48, 0, 24, 0, 24, 0, 24, 0, 12, 0, 12, 0, 6, 0, 6, 0, 3, 0, 1,128,127,128,127,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_056[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 63, 0,115,128, 97,128, 97,128, 51, 0, 63, 0, 51, 0, 97,128, 97,128,115,128, 63, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_057[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0,127, 0, 99, 0, 1,128, 1,128, 29,128, 63,128, 97,128, 97,128, 97,128, 99,128, 63, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_058[] = { 5, 0, 0, 0, 0, 0, 96, 96, 0, 0, 0, 0, 0, 0, 96, 96, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_059[] = { 5, 0, 0, 64, 32, 32, 96, 96, 0, 0, 0, 0, 0, 0, 96, 96, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_060[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,128, 7,128, 30, 0, 56, 0, 96, 0, 56, 0, 30, 0, 7,128, 1,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_061[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,128, 63,128, 0, 0, 0, 0, 63,128, 63,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_062[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0,120, 0, 30, 0, 7, 0, 1,128, 7, 0, 30, 0,120, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_063[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 24, 0, 0, 0, 0, 0, 24, 0, 24, 0, 24, 0, 28, 0, 14, 0, 7, 0, 99, 0, 99, 0,127, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_064[] = { 18, 0, 0, 0, 0, 0, 0, 3,240, 0, 15,248, 0, 28, 0, 0, 56, 0, 0, 51,184, 0,103,252, 0,102,102, 0,102, 51, 0,102, 51, 0,102, 49,128, 99, 25,128, 51,185,128, 49,217,128, 24, 3, 0, 14, 7, 0, 7,254, 0, 1,248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_065[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 48,192, 48, 96, 96, 96, 96,127,224, 63,192, 48,192, 48,192, 25,128, 25,128, 15, 0, 15, 0, 6, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_066[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,192,127,224, 96,112, 96, 48, 96, 48, 96,112,127,224,127,192, 96,192, 96, 96, 96, 96, 96,224,127,192,127,128, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_067[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,192, 31,240, 56, 56, 48, 24,112, 0, 96, 0, 96, 0, 96, 0, 96, 0,112, 0, 48, 24, 56, 56, 31,240, 7,192, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_068[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,128,127,192, 96,224, 96, 96, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 96, 96,224,127,192,127,128, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_069[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,192,127,192, 96, 0, 96, 0, 96, 0, 96, 0,127,128,127,128, 96, 0, 96, 0, 96, 0, 96, 0,127,192,127,192, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_070[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0,127,128,127,128, 96, 0, 96, 0, 96, 0, 96, 0,127,192,127,192, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_071[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,216, 31,248, 56, 56, 48, 24,112, 24, 96,248, 96,248, 96, 0, 96, 0,112, 24, 48, 24, 56, 56, 31,240, 7,192, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_072[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48,127,240,127,240, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_073[] = { 6, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_074[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 63, 0,115,128, 97,128, 97,128, 1,128, 1,128, 1,128, 1,128, 1,128, 1,128, 1,128, 1,128, 1,128, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_075[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 56, 96,112, 96,224, 97,192, 99,128,103, 0,126, 0,124, 0,110, 0,103, 0, 99,128, 97,192, 96,224, 96,112, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_076[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,128,127,128, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_077[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97,134, 97,134, 99,198, 98, 70,102,102,102,102,108, 54,108, 54,120, 30,120, 30,112, 14,112, 14, 96, 6, 96, 6, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_078[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 48, 96,112, 96,240, 96,240, 97,176, 99, 48, 99, 48,102, 48,102, 48,108, 48,120, 48,120, 48,112, 48, 96, 48, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_079[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,192, 31,240, 56, 56, 48, 24,112, 28, 96, 12, 96, 12, 96, 12, 96, 12,112, 28, 48, 24, 56, 56, 31,240, 7,192, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_080[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0,127,128,127,192, 96,224, 96, 96, 96, 96, 96,224,127,192,127,128, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_081[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 7,216, 31,240, 56,120, 48,216,112,220, 96, 12, 96, 12, 96, 12, 96, 12,112, 28, 48, 24, 56, 56, 31,240, 7,192, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_082[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 96, 96, 96, 96, 96, 96, 96, 96,192, 96,192,127,128,127,192, 96,224, 96, 96, 96, 96, 96,224,127,192,127,128, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_083[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31,128, 63,224,112,112, 96, 48, 0, 48, 0,112, 1,224, 15,128, 62, 0,112, 0, 96, 48,112,112, 63,224, 15,128, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_084[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0,127,224,127,224, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_085[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,128, 63,224, 48, 96, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_086[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 7,128, 7,128, 12,192, 12,192, 12,192, 24, 96, 24, 96, 24, 96, 48, 48, 48, 48, 48, 48, 96, 24, 96, 24, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_087[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 0, 12, 12, 0, 14, 28, 0, 26, 22, 0, 27, 54, 0, 27, 54, 0, 51, 51, 0, 51, 51, 0, 49, 35, 0, 49,227, 0, 97,225,128, 96,193,128, 96,193,128, 96,193,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_088[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 48,112,112, 48, 96, 56,224, 24,192, 13,128, 7, 0, 7, 0, 13,128, 24,192, 56,224, 48, 96,112,112, 96, 48, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_089[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 7,128, 12,192, 24, 96, 24, 96, 48, 48, 48, 48, 96, 24, 96, 24, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_090[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,224,127,224, 96, 0, 48, 0, 24, 0, 12, 0, 14, 0, 6, 0, 3, 0, 1,128, 0,192, 0, 96,127,224,127,224, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_091[] = { 5, 0,120,120, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,120,120, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_092[] = { 5, 0, 0, 0, 0, 0, 24, 24, 16, 16, 48, 48, 32, 32, 96, 96, 64, 64,192,192, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_093[] = { 5, 0,240,240, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,240,240, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_094[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 99, 0, 54, 0, 28, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_095[] = { 10, 0, 0,255,192,255,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_096[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 96, 64, 64, 32, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_097[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0,119, 0, 99, 0, 99, 0,115, 0, 63, 0, 7, 0, 99, 0,119, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_098[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,111, 0,127,128,113,128, 96,192, 96,192, 96,192, 96,192,113,128,127,128,111, 0, 96, 0, 96, 0, 96, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_099[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 63,128, 49,128, 96, 0, 96, 0, 96, 0, 96, 0, 49,128, 63,128, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_100[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30,192, 63,192, 49,192, 96,192, 96,192, 96,192, 96,192, 49,192, 63,192, 30,192, 0,192, 0,192, 0,192, 0,192, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_101[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 63,128,113,128, 96, 0, 96, 0,127,128, 97,128, 97,128, 63, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_102[] = { 6, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48,252,252, 48, 48, 60, 28, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_103[] = { 11, 0, 0, 14, 0, 63,128, 49,128, 0,192, 30,192, 63,192, 49,192, 96,192, 96,192, 96,192, 96,192, 48,192, 63,192, 30,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_104[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128,113,128,111,128,103, 0, 96, 0, 96, 0, 96, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_105[] = { 4, 0, 0, 0, 0, 0, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 0, 0, 96, 96, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_106[] = { 4, 0,192,224, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 0, 0, 96, 96, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_107[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99,128, 99, 0,103, 0,102, 0,108, 0,124, 0,120, 0,108, 0,102, 0, 99, 0, 96, 0, 96, 0, 96, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_108[] = { 4, 0, 0, 0, 0, 0, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_109[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 24, 99, 24, 99, 24, 99, 24, 99, 24, 99, 24, 99, 24,115,152,111,120,102, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_110[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128,113,128,111,128,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_111[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 63,128, 49,128, 96,192, 96,192, 96,192, 96,192, 49,128, 63,128, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_112[] = { 11, 0, 0, 96, 0, 96, 0, 96, 0, 96, 0,111, 0,127,128,113,128, 96,192, 96,192, 96,192, 96,192,113,128,127,128,111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_113[] = { 11, 0, 0, 0,192, 0,192, 0,192, 0,192, 30,192, 63,192, 49,192, 96,192, 96,192, 96,192, 96,192, 49,192, 63,192, 30,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_114[] = { 6, 0, 0, 0, 0, 0, 96, 96, 96, 96, 96, 96, 96,112,108,108, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_115[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0,126, 0, 99, 0, 3, 0, 31, 0,126, 0, 96, 0, 99, 0, 63, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_116[] = { 6, 0, 0, 0, 0, 0, 24, 56, 48, 48, 48, 48, 48, 48,252,252, 48, 48, 48, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_117[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57,128,125,128, 99,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_118[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 12, 0, 30, 0, 18, 0, 51, 0, 51, 0, 51, 0, 97,128, 97,128, 97,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_119[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12,192, 12,192, 28,224, 20,160, 52,176, 51, 48, 51, 48, 99, 24, 99, 24, 99, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_120[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97,128,115,128, 51, 0, 30, 0, 12, 0, 12, 0, 30, 0, 51, 0,115,128, 97,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_121[] = { 10, 0, 0, 56, 0, 56, 0, 12, 0, 12, 0, 12, 0, 12, 0, 30, 0, 18, 0, 51, 0, 51, 0, 51, 0, 97,128, 97,128, 97,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_122[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 0,127, 0, 96, 0, 48, 0, 24, 0, 12, 0, 6, 0, 3, 0,127, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_123[] = { 6, 0, 12, 24, 48, 48, 48, 48, 48, 48, 96,192, 96, 48, 48, 48, 48, 48, 24, 12, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_124[] = { 4, 0, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_125[] = { 6, 0,192, 96, 48, 48, 48, 48, 48, 48, 24, 12, 24, 48, 48, 48, 48, 48, 96,192, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_126[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,102, 0, 63, 0, 25,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +/* +static const GLubyte Helvetica18_Character_127[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_128[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_129[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_130[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_131[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_132[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_133[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_134[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_135[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_136[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_137[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_138[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_139[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_140[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_141[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_142[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_143[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_144[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_145[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_146[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_147[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_148[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_149[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_150[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_151[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_152[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_153[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_154[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_155[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_156[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_157[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_158[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_159[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 85, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +*/ +static const GLubyte Helvetica18_Character_160[] = { 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_161[] = { 6, 0, 48, 48, 48, 48, 48, 48, 48, 48, 16, 16, 0, 0, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_162[] = { 10, 0, 0, 0, 0, 0, 0, 8, 0, 8, 0, 31, 0, 63,128, 53,128,100, 0,100, 0,100, 0,100, 0, 53,128, 63,128, 31, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_163[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,223, 0,255,128, 96,128, 48, 0, 24, 0, 24, 0,126, 0, 48, 0, 96, 0, 97,128, 97,128, 63, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_164[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97,128,127,128, 51, 0, 51, 0, 51, 0,127,128, 97,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_165[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 12, 0, 12, 0, 12, 0,127,128, 12, 0,127,128, 30, 0, 51, 0, 51, 0, 51, 0, 97,128, 97,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_166[] = { 4, 0, 0, 96, 96, 96, 96, 96, 96, 0, 0, 0, 0, 96, 96, 96, 96, 96, 96, 96, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_167[] = { 10, 0, 0, 30, 0, 63, 0, 97,128, 97,128, 3,128, 7, 0, 31, 0, 57,128,113,128, 97,128, 99,128, 55, 0, 62, 0,120, 0, 97,128, 97,128, 63, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_168[] = { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216,216, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_169[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,192, 24, 48, 32, 8, 35,136, 68, 68, 72, 4, 72, 4, 72, 4, 68, 68, 35,136, 32, 8, 24, 48, 7,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_170[] = { 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,124, 0, 52,108, 36, 28,100, 56, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_171[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 27, 0, 54, 0,108, 0,108, 0, 54, 0, 27, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_172[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 0,192, 0,192,127,192,127,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_173[] = { 7, 0, 0, 0, 0, 0, 0, 0, 0, 0,124,124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_174[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,192, 24, 48, 32, 8, 36, 40, 68, 68, 68,132, 71,196, 68, 36, 68, 36, 39,200, 32, 8, 24, 48, 7,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_175[] = { 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_176[] = { 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,108, 68,108, 56, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_177[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,128,127,128, 0, 0, 12, 0, 12, 0, 12, 0,127,128,127,128, 12, 0, 12, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_178[] = { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248,248, 96, 48, 24,152,248,112, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_179[] = { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,112,248,152, 48, 48,152,248,112, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_180[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 96, 48, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_181[] = { 10, 0, 0, 96, 0, 96, 0, 96, 0, 96, 0,109,128,127,128,115,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_182[] = { 10, 0, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 25, 0, 57, 0,121, 0,121, 0,121, 0,121, 0, 57, 0, 31,128, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_183[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_184[] = { 5, 0,240,216, 24,112, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_185[] = { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48,112,112, 48, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_186[] = { 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,124, 0, 56,108, 68, 68,108, 56, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_187[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0,108, 0, 54, 0, 27, 0, 27, 0, 54, 0,108, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_188[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 12,252, 6,216, 6,120, 51, 56, 49, 24, 49,136, 48,192, 48,192,112, 96,112, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_189[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24,124, 24,124, 12, 48, 6, 24, 6, 12, 51, 76, 49,124, 49,184, 48,192, 48,192,112, 96,112, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_190[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 12,252, 6,216, 6,120,115, 56,249, 24,153,136, 48,192, 48,192,152, 96,248, 48,112, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_191[] = { 10, 0, 0, 62, 0,127, 0, 99, 0, 99, 0,112, 0, 56, 0, 28, 0, 12, 0, 12, 0, 12, 0, 0, 0, 0, 0, 12, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_192[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 48,192, 48, 96, 96, 96, 96,127,224, 63,192, 48,192, 48,192, 25,128, 25,128, 15, 0, 15, 0, 6, 0, 6, 0, 0, 0, 6, 0, 12, 0, 24, 0}; +static const GLubyte Helvetica18_Character_193[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 48,192, 48, 96, 96, 96, 96,127,224, 63,192, 48,192, 48,192, 25,128, 25,128, 15, 0, 15, 0, 6, 0, 6, 0, 0, 0, 6, 0, 3, 0, 1,128}; +static const GLubyte Helvetica18_Character_194[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 48,192, 48, 96, 96, 96, 96,127,224, 63,192, 48,192, 48,192, 25,128, 25,128, 15, 0, 15, 0, 6, 0, 6, 0, 0, 0, 25,128, 15, 0, 6, 0}; +static const GLubyte Helvetica18_Character_195[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 48,192, 48, 96, 96, 96, 96,127,224, 63,192, 48,192, 48,192, 25,128, 25,128, 15, 0, 15, 0, 6, 0, 6, 0, 0, 0, 19, 0, 22,128, 12,128}; +static const GLubyte Helvetica18_Character_196[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 48,192, 48, 96, 96, 96, 96,127,224, 63,192, 48,192, 48,192, 25,128, 25,128, 15, 0, 15, 0, 6, 0, 6, 0, 0, 0, 25,128, 25,128, 0, 0}; +static const GLubyte Helvetica18_Character_197[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 48,192, 48, 96, 96, 96, 96,127,224, 63,192, 48,192, 48,192, 25,128, 25,128, 15, 0, 15, 0, 6, 0, 6, 0, 15, 0, 25,128, 25,128, 15, 0}; +static const GLubyte Helvetica18_Character_198[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96,255,128, 96,255,128, 48,192, 0, 48,192, 0, 63,192, 0, 31,192, 0, 24,255, 0, 24,255, 0, 12,192, 0, 12,192, 0, 6,192, 0, 6,192, 0, 3,255,128, 3,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_199[] = { 14, 0, 0, 15, 0, 13,128, 1,128, 7, 0, 7,192, 31,240, 56, 56, 48, 24,112, 0, 96, 0, 96, 0, 96, 0, 96, 0,112, 0, 48, 24, 56, 56, 31,240, 7,192, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_200[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,192,127,192, 96, 0, 96, 0, 96, 0, 96, 0,127,128,127,128, 96, 0, 96, 0, 96, 0, 96, 0,127,192,127,192, 0, 0, 6, 0, 12, 0, 24, 0}; +static const GLubyte Helvetica18_Character_201[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,192,127,192, 96, 0, 96, 0, 96, 0, 96, 0,127,128,127,128, 96, 0, 96, 0, 96, 0, 96, 0,127,192,127,192, 0, 0, 6, 0, 3, 0, 1,128}; +static const GLubyte Helvetica18_Character_202[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,192,127,192, 96, 0, 96, 0, 96, 0, 96, 0,127,128,127,128, 96, 0, 96, 0, 96, 0, 96, 0,127,192,127,192, 0, 0, 25,128, 15, 0, 6, 0}; +static const GLubyte Helvetica18_Character_203[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,192,127,192, 96, 0, 96, 0, 96, 0, 96, 0,127,128,127,128, 96, 0, 96, 0, 96, 0, 96, 0,127,192,127,192, 0, 0, 25,128, 25,128, 0, 0}; +static const GLubyte Helvetica18_Character_204[] = { 6, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 96,192}; +static const GLubyte Helvetica18_Character_205[] = { 6, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 24, 12}; +static const GLubyte Helvetica18_Character_206[] = { 6, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0,204,120, 48}; +static const GLubyte Helvetica18_Character_207[] = { 6, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0,204,204, 0}; +static const GLubyte Helvetica18_Character_208[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,128,127,192, 96,224, 96, 96, 96, 48, 96, 48,252, 48,252, 48, 96, 48, 96, 48, 96, 96, 96,224,127,192,127,128, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_209[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 48, 96,112, 96,240, 96,240, 97,176, 99, 48, 99, 48,102, 48,102, 48,108, 48,108, 48,120, 48,112, 48,112, 48, 0, 0, 9,128, 11, 64, 6, 64}; +static const GLubyte Helvetica18_Character_210[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,192, 31,240, 56, 56, 48, 24,112, 28, 96, 12, 96, 12, 96, 12, 96, 12,112, 28, 48, 24, 56, 56, 31,240, 7,192, 0, 0, 1,128, 3, 0, 6, 0}; +static const GLubyte Helvetica18_Character_211[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,192, 31,240, 56, 56, 48, 24,112, 28, 96, 12, 96, 12, 96, 12, 96, 12,112, 28, 48, 24, 56, 56, 31,240, 7,192, 0, 0, 1,128, 0,192, 0, 96}; +static const GLubyte Helvetica18_Character_212[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,192, 31,240, 56, 56, 48, 24,112, 28, 96, 12, 96, 12, 96, 12, 96, 12,112, 28, 48, 24, 56, 56, 31,240, 7,192, 0, 0, 6, 96, 3,192, 1,128}; +static const GLubyte Helvetica18_Character_213[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,192, 31,240, 56, 56, 48, 24,112, 28, 96, 12, 96, 12, 96, 12, 96, 12,112, 28, 48, 24, 56, 56, 31,240, 7,192, 0, 0, 4,192, 5,160, 3, 32}; +static const GLubyte Helvetica18_Character_214[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,192, 31,240, 56, 56, 48, 24,112, 28, 96, 12, 96, 12, 96, 12, 96, 12,112, 28, 48, 24, 56, 56, 31,240, 7,192, 0, 0, 6,192, 6,192, 0, 0}; +static const GLubyte Helvetica18_Character_215[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,192, 97,128, 51, 0, 30, 0, 12, 0, 30, 0, 51, 0, 97,128,192,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_216[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,199,192,255,240,120, 56, 56, 24,108, 28,110, 12,103, 12, 99,140, 97,204,112,220, 48,120, 56, 56, 31,252, 7,204, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_217[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,128, 63,224, 48, 96, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 0, 0, 3, 0, 6, 0, 12, 0}; +static const GLubyte Helvetica18_Character_218[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,128, 63,224, 48, 96, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 0, 0, 6, 0, 3, 0, 1,128}; +static const GLubyte Helvetica18_Character_219[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,128, 63,224, 48, 96, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 0, 0, 12,192, 7,128, 3, 0}; +static const GLubyte Helvetica18_Character_220[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,128, 63,224, 48, 96, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 0, 0, 12,192, 12,192, 0, 0}; +static const GLubyte Helvetica18_Character_221[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 7,128, 12,192, 24, 96, 24, 96, 48, 48, 48, 48, 96, 24, 96, 24, 0, 0, 3, 0, 1,128, 0,192}; +static const GLubyte Helvetica18_Character_222[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 96, 0, 96, 0,127,128,127,192, 96,224, 96, 96, 96, 96, 96,224,127,192,127,128, 96, 0, 96, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_223[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,110, 0,111, 0, 99, 0, 99, 0, 99, 0, 99, 0,110, 0,110, 0, 99, 0, 99, 0, 99, 0, 99, 0, 62, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_224[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0,119, 0, 99, 0, 99, 0,115, 0, 63, 0, 7, 0, 99, 0,119, 0, 62, 0, 0, 0, 12, 0, 24, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_225[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0,119, 0, 99, 0, 99, 0,115, 0, 63, 0, 7, 0, 99, 0,119, 0, 62, 0, 0, 0, 24, 0, 12, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_226[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0,119, 0, 99, 0, 99, 0,115, 0, 63, 0, 7, 0, 99, 0,119, 0, 62, 0, 0, 0, 51, 0, 30, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_227[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0,119, 0, 99, 0, 99, 0,115, 0, 63, 0, 7, 0, 99, 0,119, 0, 62, 0, 0, 0, 38, 0, 45, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_228[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0,119, 0, 99, 0, 99, 0,115, 0, 63, 0, 7, 0, 99, 0,119, 0, 62, 0, 0, 0, 54, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_229[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0,119, 0, 99, 0, 99, 0,115, 0, 63, 0, 7, 0, 99, 0,119, 0, 62, 0, 28, 0, 54, 0, 54, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_230[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58,240,119,252, 99,140, 99, 0,115, 0, 63,252, 7, 12, 99, 12,119,248, 62,240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_231[] = { 10, 0, 0, 60, 0, 54, 0, 6, 0, 28, 0, 31, 0, 63,128, 49,128, 96, 0, 96, 0, 96, 0, 96, 0, 49,128, 63,128, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_232[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 63,128,113,128, 96, 0, 96, 0,127,128, 97,128, 97,128, 63, 0, 30, 0, 0, 0, 12, 0, 24, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_233[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 63,128,113,128, 96, 0, 96, 0,127,128, 97,128, 97,128, 63, 0, 30, 0, 0, 0, 12, 0, 6, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_234[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 63,128,113,128, 96, 0, 96, 0,127,128, 97,128, 97,128, 63, 0, 30, 0, 0, 0, 51, 0, 30, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_235[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 63,128,113,128, 96, 0, 96, 0,127,128, 97,128, 97,128, 63, 0, 30, 0, 0, 0, 27, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_236[] = { 4, 0, 0, 0, 0, 0, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 0, 48, 96,192, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_237[] = { 4, 0, 0, 0, 0, 0, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 0,192, 96, 48, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_238[] = { 4, 0, 0, 0, 0, 0, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 0,144,240, 96, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_239[] = { 4, 0, 0, 0, 0, 0, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 0,216,216, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_240[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 63,128, 49,128, 96,192, 96,192, 96,192, 96,192, 49,128, 63,128, 31, 0, 38, 0, 28, 0, 27, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_241[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128,113,128,111,128,103, 0, 0, 0, 38, 0, 45, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_242[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 63,128, 49,128, 96,192, 96,192, 96,192, 96,192, 49,128, 63,128, 31, 0, 0, 0, 6, 0, 12, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_243[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 63,128, 49,128, 96,192, 96,192, 96,192, 96,192, 49,128, 63,128, 31, 0, 0, 0, 12, 0, 6, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_244[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 63,128, 49,128, 96,192, 96,192, 96,192, 96,192, 49,128, 63,128, 31, 0, 0, 0, 25,128, 15, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_245[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 63,128, 49,128, 96,192, 96,192, 96,192, 96,192, 49,128, 63,128, 31, 0, 0, 0, 19, 0, 22,128, 12,128, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_246[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 63,128, 49,128, 96,192, 96,192, 96,192, 96,192, 49,128, 63,128, 31, 0, 0, 0, 27, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_247[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 12, 0, 0, 0,127,128,127,128, 0, 0, 12, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_248[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,206, 0,127,128, 49,128,120,192,108,192,102,192, 99,192, 49,128, 63,192, 14, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_249[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57,128,125,128, 99,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 0, 0, 6, 0, 12, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_250[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57,128,125,128, 99,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 0, 0, 12, 0, 6, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_251[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57,128,125,128, 99,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 0, 0, 51, 0, 30, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_252[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57,128,125,128, 99,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 97,128, 0, 0, 51, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_253[] = { 10, 0, 0, 56, 0, 56, 0, 12, 0, 12, 0, 12, 0, 12, 0, 30, 0, 18, 0, 51, 0, 51, 0, 51, 0, 97,128, 97,128, 97,128, 0, 0, 12, 0, 6, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_254[] = { 11, 0, 0, 96, 0, 96, 0, 96, 0, 96, 0,111, 0,127,128,113,128, 96,192, 96,192, 96,192, 96,192,113,128,127,128,111, 0, 96, 0, 96, 0, 96, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Helvetica18_Character_255[] = { 10, 0, 0, 56, 0, 56, 0, 12, 0, 12, 0, 12, 0, 12, 0, 30, 0, 18, 0, 51, 0, 51, 0, 51, 0, 97,128, 97,128, 97,128, 0, 0, 51, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +/* The font characters mapping: */ +static const GLubyte* Helvetica18_Character_Map[] = {Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032, + Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032, + Helvetica18_Character_032,Helvetica18_Character_033,Helvetica18_Character_034,Helvetica18_Character_035,Helvetica18_Character_036,Helvetica18_Character_037,Helvetica18_Character_038,Helvetica18_Character_039,Helvetica18_Character_040,Helvetica18_Character_041,Helvetica18_Character_042,Helvetica18_Character_043,Helvetica18_Character_044,Helvetica18_Character_045,Helvetica18_Character_046,Helvetica18_Character_047, + Helvetica18_Character_048,Helvetica18_Character_049,Helvetica18_Character_050,Helvetica18_Character_051,Helvetica18_Character_052,Helvetica18_Character_053,Helvetica18_Character_054,Helvetica18_Character_055,Helvetica18_Character_056,Helvetica18_Character_057,Helvetica18_Character_058,Helvetica18_Character_059,Helvetica18_Character_060,Helvetica18_Character_061,Helvetica18_Character_062,Helvetica18_Character_063, + Helvetica18_Character_064,Helvetica18_Character_065,Helvetica18_Character_066,Helvetica18_Character_067,Helvetica18_Character_068,Helvetica18_Character_069,Helvetica18_Character_070,Helvetica18_Character_071,Helvetica18_Character_072,Helvetica18_Character_073,Helvetica18_Character_074,Helvetica18_Character_075,Helvetica18_Character_076,Helvetica18_Character_077,Helvetica18_Character_078,Helvetica18_Character_079, + Helvetica18_Character_080,Helvetica18_Character_081,Helvetica18_Character_082,Helvetica18_Character_083,Helvetica18_Character_084,Helvetica18_Character_085,Helvetica18_Character_086,Helvetica18_Character_087,Helvetica18_Character_088,Helvetica18_Character_089,Helvetica18_Character_090,Helvetica18_Character_091,Helvetica18_Character_092,Helvetica18_Character_093,Helvetica18_Character_094,Helvetica18_Character_095, + Helvetica18_Character_096,Helvetica18_Character_097,Helvetica18_Character_098,Helvetica18_Character_099,Helvetica18_Character_100,Helvetica18_Character_101,Helvetica18_Character_102,Helvetica18_Character_103,Helvetica18_Character_104,Helvetica18_Character_105,Helvetica18_Character_106,Helvetica18_Character_107,Helvetica18_Character_108,Helvetica18_Character_109,Helvetica18_Character_110,Helvetica18_Character_111, + Helvetica18_Character_112,Helvetica18_Character_113,Helvetica18_Character_114,Helvetica18_Character_115,Helvetica18_Character_116,Helvetica18_Character_117,Helvetica18_Character_118,Helvetica18_Character_119,Helvetica18_Character_120,Helvetica18_Character_121,Helvetica18_Character_122,Helvetica18_Character_123,Helvetica18_Character_124,Helvetica18_Character_125,Helvetica18_Character_126,Helvetica18_Character_032, + Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032, + Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032,Helvetica18_Character_032, + Helvetica18_Character_160,Helvetica18_Character_161,Helvetica18_Character_162,Helvetica18_Character_163,Helvetica18_Character_164,Helvetica18_Character_165,Helvetica18_Character_166,Helvetica18_Character_167,Helvetica18_Character_168,Helvetica18_Character_169,Helvetica18_Character_170,Helvetica18_Character_171,Helvetica18_Character_172,Helvetica18_Character_173,Helvetica18_Character_174,Helvetica18_Character_175, + Helvetica18_Character_176,Helvetica18_Character_177,Helvetica18_Character_178,Helvetica18_Character_179,Helvetica18_Character_180,Helvetica18_Character_181,Helvetica18_Character_182,Helvetica18_Character_183,Helvetica18_Character_184,Helvetica18_Character_185,Helvetica18_Character_186,Helvetica18_Character_187,Helvetica18_Character_188,Helvetica18_Character_189,Helvetica18_Character_190,Helvetica18_Character_191, + Helvetica18_Character_192,Helvetica18_Character_193,Helvetica18_Character_194,Helvetica18_Character_195,Helvetica18_Character_196,Helvetica18_Character_197,Helvetica18_Character_198,Helvetica18_Character_199,Helvetica18_Character_200,Helvetica18_Character_201,Helvetica18_Character_202,Helvetica18_Character_203,Helvetica18_Character_204,Helvetica18_Character_205,Helvetica18_Character_206,Helvetica18_Character_207, + Helvetica18_Character_208,Helvetica18_Character_209,Helvetica18_Character_210,Helvetica18_Character_211,Helvetica18_Character_212,Helvetica18_Character_213,Helvetica18_Character_214,Helvetica18_Character_215,Helvetica18_Character_216,Helvetica18_Character_217,Helvetica18_Character_218,Helvetica18_Character_219,Helvetica18_Character_220,Helvetica18_Character_221,Helvetica18_Character_222,Helvetica18_Character_223, + Helvetica18_Character_224,Helvetica18_Character_225,Helvetica18_Character_226,Helvetica18_Character_227,Helvetica18_Character_228,Helvetica18_Character_229,Helvetica18_Character_230,Helvetica18_Character_231,Helvetica18_Character_232,Helvetica18_Character_233,Helvetica18_Character_234,Helvetica18_Character_235,Helvetica18_Character_236,Helvetica18_Character_237,Helvetica18_Character_238,Helvetica18_Character_239, + Helvetica18_Character_240,Helvetica18_Character_241,Helvetica18_Character_242,Helvetica18_Character_243,Helvetica18_Character_244,Helvetica18_Character_245,Helvetica18_Character_246,Helvetica18_Character_247,Helvetica18_Character_248,Helvetica18_Character_249,Helvetica18_Character_250,Helvetica18_Character_251,Helvetica18_Character_252,Helvetica18_Character_253,Helvetica18_Character_254,Helvetica18_Character_255,NULL}; + +/* The font structure: */ +SFG_Font fgFontHelvetica18 = { "-adobe-helvetica-medium-r-normal--18-180-75-75-p-98-iso8859-1", 256, 23, Helvetica18_Character_Map, 0, 5 }; + +/* +static const GLubyte TimesRoman10_Character_000[] = { 8, 0, 0, 0, 0,170, 0,130, 0,130, 0,170, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_001[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_002[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_003[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_004[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_005[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_006[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_007[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_008[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_009[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_010[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_011[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_012[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_013[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_014[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_015[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_016[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_017[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_018[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_019[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_020[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_021[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_022[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_023[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_024[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_025[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_026[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_027[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_028[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_029[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_030[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_031[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +*/ +static const GLubyte TimesRoman10_Character_032[] = { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_033[] = { 3, 0, 0, 0, 0, 64, 0, 64, 64, 64, 64, 64, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_034[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,160,160, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_035[] = { 5, 0, 0, 0, 0, 80, 80,248, 80,248, 80, 80, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_036[] = { 5, 0, 0, 0, 32,224,144, 16, 96,128,144,112, 32, 0, 0}; +static const GLubyte TimesRoman10_Character_037[] = { 8, 0, 0, 0, 0, 68, 42, 42, 86,168,164,126, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_038[] = { 8, 0, 0, 0, 0,118,141,152,116,110, 80, 48, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_039[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64,192, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_040[] = { 4, 0, 0, 32, 64, 64,128,128,128, 64, 64, 32, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_041[] = { 4, 0, 0,128, 64, 64, 32, 32, 32, 64, 64,128, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_042[] = { 5, 0, 0, 0, 0, 0, 0, 0, 0,160, 64,160, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_043[] = { 6, 0, 0, 0, 0, 32, 32,248, 32, 32, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_044[] = { 3, 0, 0, 64, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_045[] = { 7, 0, 0, 0, 0, 0, 0,120, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_046[] = { 3, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_047[] = { 3, 0, 0, 0, 0,128,128, 64, 64, 64, 32, 32, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_048[] = { 5, 0, 0, 0, 0, 96,144,144,144,144,144, 96, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_049[] = { 5, 0, 0, 0, 0,112, 32, 32, 32, 32, 96, 32, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_050[] = { 5, 0, 0, 0, 0,240, 64, 32, 32, 16,144, 96, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_051[] = { 5, 0, 0, 0, 0,224, 16, 16, 96, 16,144, 96, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_052[] = { 5, 0, 0, 0, 0, 16, 16,248,144, 80, 48, 16, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_053[] = { 5, 0, 0, 0, 0,224,144, 16, 16,224, 64,112, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_054[] = { 5, 0, 0, 0, 0, 96,144,144,144,224, 64, 48, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_055[] = { 5, 0, 0, 0, 0, 64, 64, 64, 32, 32,144,240, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_056[] = { 5, 0, 0, 0, 0, 96,144,144, 96,144,144, 96, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_057[] = { 5, 0, 0, 0, 0,192, 32,112,144,144,144, 96, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_058[] = { 3, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_059[] = { 3, 0, 0, 64, 64, 64, 0, 0, 0, 64, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_060[] = { 5, 0, 0, 0, 0, 16, 32, 64, 32, 16, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_061[] = { 6, 0, 0, 0, 0, 0,248, 0,248, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_062[] = { 5, 0, 0, 0, 0,128, 64, 32, 64,128, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_063[] = { 4, 0, 0, 0, 0, 64, 0, 64, 64, 32,160,224, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_064[] = { 9, 0, 0, 0, 0, 62, 0, 64, 0,146, 0,173, 0,165, 0,165, 0,157, 0, 66, 0, 60, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_065[] = { 8, 0, 0, 0, 0,238, 68,124, 40, 40, 56, 16, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_066[] = { 6, 0, 0, 0, 0,240, 72, 72,112, 72, 72,240, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_067[] = { 7, 0, 0, 0, 0,120,196,128,128,128,196,124, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_068[] = { 7, 0, 0, 0, 0,248, 76, 68, 68, 68, 76,248, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_069[] = { 6, 0, 0, 0, 0,248, 72, 64,112, 64, 72,248, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_070[] = { 6, 0, 0, 0, 0,224, 64, 64,112, 64, 72,248, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_071[] = { 7, 0, 0, 0, 0,120,196,132,156,128,196,124, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_072[] = { 8, 0, 0, 0, 0,238, 68, 68,124, 68, 68,238, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_073[] = { 4, 0, 0, 0, 0,224, 64, 64, 64, 64, 64,224, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_074[] = { 4, 0, 0, 0, 0,192,160, 32, 32, 32, 32,112, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_075[] = { 7, 0, 0, 0, 0,236, 72, 80, 96, 80, 72,236, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_076[] = { 6, 0, 0, 0, 0,248, 72, 64, 64, 64, 64,224, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_077[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,235,128, 73, 0, 85, 0, 85, 0, 99, 0, 99, 0,227,128, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_078[] = { 8, 0, 0, 0, 0,228, 76, 76, 84, 84,100,238, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_079[] = { 7, 0, 0, 0, 0,120,204,132,132,132,204,120, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_080[] = { 6, 0, 0, 0, 0,224, 64, 64,112, 72, 72,240, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_081[] = { 7, 0, 0, 12, 24,112,204,132,132,132,204,120, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_082[] = { 7, 0, 0, 0, 0,236, 72, 80,112, 72, 72,240, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_083[] = { 5, 0, 0, 0, 0,224,144, 16, 96,192,144,112, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_084[] = { 6, 0, 0, 0, 0,112, 32, 32, 32, 32,168,248, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_085[] = { 8, 0, 0, 0, 0, 56,108, 68, 68, 68, 68,238, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_086[] = { 8, 0, 0, 0, 0, 16, 16, 40, 40,108, 68,238, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_087[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 34, 0, 85, 0, 85, 0,201,128,136,128,221,192, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_088[] = { 8, 0, 0, 0, 0,238, 68, 40, 16, 40, 68,238, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_089[] = { 8, 0, 0, 0, 0, 56, 16, 16, 40, 40, 68,238, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_090[] = { 6, 0, 0, 0, 0,248,136, 64, 32, 16,136,248, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_091[] = { 3, 0, 0,192,128,128,128,128,128,128,128,192, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_092[] = { 3, 0, 0, 0, 0, 32, 32, 64, 64, 64,128,128, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_093[] = { 3, 0, 0,192, 64, 64, 64, 64, 64, 64, 64,192, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_094[] = { 5, 0, 0, 0, 0, 0, 0, 0, 0, 80, 80, 32, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_095[] = { 5, 0,248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_096[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,128, 0, 0}; +static const GLubyte TimesRoman10_Character_097[] = { 4, 0, 0, 0, 0,224,160, 96, 32,192, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_098[] = { 5, 0, 0, 0, 0,224,144,144,144,224,128,128, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_099[] = { 4, 0, 0, 0, 0, 96,128,128,128, 96, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_100[] = { 5, 0, 0, 0, 0,104,144,144,144,112, 16, 48, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_101[] = { 4, 0, 0, 0, 0, 96,128,192,160, 96, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_102[] = { 4, 0, 0, 0, 0,224, 64, 64, 64,224, 64, 48, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_103[] = { 5, 0, 0,224,144, 96, 64,160,160,112, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_104[] = { 5, 0, 0, 0, 0,216,144,144,144,224,128,128, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_105[] = { 3, 0, 0, 0, 0, 64, 64, 64, 64,192, 0, 64, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_106[] = { 3, 0, 0,128, 64, 64, 64, 64, 64,192, 0, 64, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_107[] = { 5, 0, 0, 0, 0,152,144,224,160,144,128,128, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_108[] = { 4, 0, 0, 0, 0,224, 64, 64, 64, 64, 64,192, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_109[] = { 8, 0, 0, 0, 0,219,146,146,146,236, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_110[] = { 5, 0, 0, 0, 0,216,144,144,144,224, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_111[] = { 5, 0, 0, 0, 0, 96,144,144,144, 96, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_112[] = { 5, 0, 0,192,128,224,144,144,144,224, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_113[] = { 5, 0, 0, 56, 16,112,144,144,144,112, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_114[] = { 4, 0, 0, 0, 0,224, 64, 64, 96,160, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_115[] = { 4, 0, 0, 0, 0,224, 32, 96,128,224, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_116[] = { 4, 0, 0, 0, 0, 48, 64, 64, 64,224, 64, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_117[] = { 5, 0, 0, 0, 0,104,144,144,144,144, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_118[] = { 5, 0, 0, 0, 0, 32, 96, 80,144,216, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_119[] = { 8, 0, 0, 0, 0, 40,108, 84,146,219, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_120[] = { 6, 0, 0, 0, 0,216, 80, 32, 80,216, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_121[] = { 5, 0, 0,128,128, 64, 96,160,144,184, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_122[] = { 5, 0, 0, 0, 0,240,144, 64, 32,240, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_123[] = { 4, 0, 0, 32, 64, 64, 64,128, 64, 64, 64, 32, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_124[] = { 2, 0, 0,128,128,128,128,128,128,128,128,128, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_125[] = { 4, 0, 0,128, 64, 64, 64, 32, 64, 64, 64,128, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_126[] = { 7, 0, 0, 0, 0, 0, 0,152,100, 0, 0, 0, 0, 0, 0}; +/* +static const GLubyte TimesRoman10_Character_127[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_128[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_129[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_130[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_131[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_132[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_133[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_134[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_135[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_136[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_137[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_138[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_139[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_140[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_141[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_142[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_143[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_144[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_145[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_146[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_147[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_148[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_149[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_150[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_151[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_152[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_153[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_154[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_155[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_156[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_157[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_158[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_159[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0, 0, 0}; +*/ +static const GLubyte TimesRoman10_Character_160[] = { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_161[] = { 3, 0, 0, 64, 64, 64, 64, 64, 0, 64, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_162[] = { 5, 0, 0, 0,128,224,144,128,144,112, 16, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_163[] = { 5, 0, 0, 0, 0,240,200, 64,224, 64, 80, 48, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_164[] = { 5, 0, 0, 0, 0, 0,136,112, 80, 80,112,136, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_165[] = { 5, 0, 0, 0, 0,112, 32,248, 32,216, 80,136, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_166[] = { 2, 0, 0, 0, 0,128,128,128, 0,128,128,128, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_167[] = { 5, 0, 0, 0,224,144, 32, 80,144,160, 64,144,112, 0, 0}; +static const GLubyte TimesRoman10_Character_168[] = { 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_169[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 34, 0, 77, 0, 81, 0, 77, 0, 34, 0, 28, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_170[] = { 4, 0, 0, 0, 0, 0, 0,224, 0,160, 32,192, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_171[] = { 5, 0, 0, 0, 0, 0, 80,160,160, 80, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_172[] = { 7, 0, 0, 0, 0, 0, 4, 4,124, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_173[] = { 4, 0, 0, 0, 0, 0, 0,224, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_174[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 34, 0, 85, 0, 89, 0, 93, 0, 34, 0, 28, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_175[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,224, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_176[] = { 4, 0, 0, 0, 0, 0, 0, 0, 96,144,144, 96, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_177[] = { 6, 0, 0, 0, 0,248, 0, 32, 32,248, 32, 32, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_178[] = { 3, 0, 0, 0, 0, 0, 0, 0,224, 64,160, 96, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_179[] = { 3, 0, 0, 0, 0, 0, 0, 0,192, 32, 64,224, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_180[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 64, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_181[] = { 5, 0, 0,128,128,232,144,144,144,144, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_182[] = { 6, 0, 0, 40, 40, 40, 40,104,232,232,232,124, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_183[] = { 2, 0, 0, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_184[] = { 4, 0,192, 32, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_185[] = { 3, 0, 0, 0, 0, 0, 0, 0,224, 64,192, 64, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_186[] = { 4, 0, 0, 0, 0, 0, 0,224, 0, 64,160, 64, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_187[] = { 5, 0, 0, 0, 0, 0,160, 80, 80,160, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_188[] = { 8, 0, 0, 0, 0, 68, 62, 44,244, 72,200, 68, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_189[] = { 8, 0, 0, 0, 0, 78, 36, 42,246, 72,200, 68, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_190[] = { 8, 0, 0, 0, 0, 68, 62, 44,212, 40, 72,228, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_191[] = { 4, 0, 0,224,160,128, 64, 64, 0, 64, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_192[] = { 8, 0, 0, 0, 0,238, 68,124, 40, 40, 56, 16, 0, 16, 32}; +static const GLubyte TimesRoman10_Character_193[] = { 8, 0, 0, 0, 0,238, 68,124, 40, 40, 56, 16, 0, 16, 8}; +static const GLubyte TimesRoman10_Character_194[] = { 8, 0, 0, 0, 0,238, 68,124, 40, 40, 56, 16, 0, 40, 16}; +static const GLubyte TimesRoman10_Character_195[] = { 8, 0, 0, 0, 0,238, 68,124, 40, 40, 56, 16, 0, 40, 20}; +static const GLubyte TimesRoman10_Character_196[] = { 8, 0, 0, 0, 0,238, 68,124, 40, 40, 56, 16, 0, 40, 0}; +static const GLubyte TimesRoman10_Character_197[] = { 8, 0, 0, 0, 0,238, 68,124, 40, 40, 56, 16, 16, 40, 16}; +static const GLubyte TimesRoman10_Character_198[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,239, 0, 73, 0,120, 0, 46, 0, 40, 0, 57, 0, 31, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_199[] = { 7, 0, 96, 16, 32,120,196,128,128,128,196,124, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_200[] = { 6, 0, 0, 0, 0,248, 72, 64,112, 64, 72,248, 0, 32, 64}; +static const GLubyte TimesRoman10_Character_201[] = { 6, 0, 0, 0, 0,248, 72, 64,112, 64, 72,248, 0, 32, 16}; +static const GLubyte TimesRoman10_Character_202[] = { 6, 0, 0, 0, 0,248, 72, 64,112, 64, 72,248, 0, 80, 32}; +static const GLubyte TimesRoman10_Character_203[] = { 6, 0, 0, 0, 0,248, 72, 64,112, 64, 72,248, 0, 80, 0}; +static const GLubyte TimesRoman10_Character_204[] = { 4, 0, 0, 0, 0,224, 64, 64, 64, 64, 64,224, 0, 64,128}; +static const GLubyte TimesRoman10_Character_205[] = { 4, 0, 0, 0, 0,224, 64, 64, 64, 64, 64,224, 0, 64, 32}; +static const GLubyte TimesRoman10_Character_206[] = { 4, 0, 0, 0, 0,224, 64, 64, 64, 64, 64,224, 0,160, 64}; +static const GLubyte TimesRoman10_Character_207[] = { 4, 0, 0, 0, 0,224, 64, 64, 64, 64, 64,224, 0,160, 0}; +static const GLubyte TimesRoman10_Character_208[] = { 7, 0, 0, 0, 0,248, 76, 68,228, 68, 76,248, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_209[] = { 8, 0, 0, 0, 0,228, 76, 76, 84, 84,100,238, 0, 80, 40}; +static const GLubyte TimesRoman10_Character_210[] = { 7, 0, 0, 0, 0,120,204,132,132,132,204,120, 0, 32, 64}; +static const GLubyte TimesRoman10_Character_211[] = { 7, 0, 0, 0, 0,120,204,132,132,132,204,120, 0, 16, 8}; +static const GLubyte TimesRoman10_Character_212[] = { 7, 0, 0, 0, 0,120,204,132,132,132,204,120, 0, 80, 32}; +static const GLubyte TimesRoman10_Character_213[] = { 7, 0, 0, 0, 0,120,204,132,132,132,204,120, 0, 80, 40}; +static const GLubyte TimesRoman10_Character_214[] = { 7, 0, 0, 0, 0,120,204,132,132,132,204,120, 0, 80, 0}; +static const GLubyte TimesRoman10_Character_215[] = { 6, 0, 0, 0, 0,136, 80, 32, 80,136, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_216[] = { 8, 0, 0, 0,128,124,102, 82, 82, 74,102, 62, 1, 0, 0}; +static const GLubyte TimesRoman10_Character_217[] = { 8, 0, 0, 0, 0, 56,108, 68, 68, 68, 68,238, 0, 16, 32}; +static const GLubyte TimesRoman10_Character_218[] = { 8, 0, 0, 0, 0, 56,108, 68, 68, 68, 68,238, 0, 16, 8}; +static const GLubyte TimesRoman10_Character_219[] = { 8, 0, 0, 0, 0, 56,108, 68, 68, 68, 68,238, 0, 40, 16}; +static const GLubyte TimesRoman10_Character_220[] = { 8, 0, 0, 0, 0, 56,108, 68, 68, 68, 68,238, 0, 40, 0}; +static const GLubyte TimesRoman10_Character_221[] = { 8, 0, 0, 0, 0, 56, 16, 16, 40, 40, 68,238, 0, 16, 8}; +static const GLubyte TimesRoman10_Character_222[] = { 6, 0, 0, 0, 0,224, 64,112, 72,112, 64,224, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_223[] = { 5, 0, 0, 0, 0,224, 80, 80, 96, 80, 80, 32, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_224[] = { 4, 0, 0, 0, 0,224,160, 96, 32,192, 0, 64,128, 0, 0}; +static const GLubyte TimesRoman10_Character_225[] = { 4, 0, 0, 0, 0,224,160, 96, 32,192, 0, 64, 32, 0, 0}; +static const GLubyte TimesRoman10_Character_226[] = { 4, 0, 0, 0, 0,224,160, 96, 32,192, 0,160, 64, 0, 0}; +static const GLubyte TimesRoman10_Character_227[] = { 4, 0, 0, 0, 0,224,160, 96, 32,192, 0,160, 80, 0, 0}; +static const GLubyte TimesRoman10_Character_228[] = { 4, 0, 0, 0, 0,224,160, 96, 32,192, 0,160, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_229[] = { 4, 0, 0, 0, 0,224,160, 96, 32,192, 64,160, 64, 0, 0}; +static const GLubyte TimesRoman10_Character_230[] = { 6, 0, 0, 0, 0,216,160,112, 40,216, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_231[] = { 4, 0,192, 32, 64, 96,128,128,128, 96, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_232[] = { 4, 0, 0, 0, 0, 96,128,192,160, 96, 0, 64,128, 0, 0}; +static const GLubyte TimesRoman10_Character_233[] = { 4, 0, 0, 0, 0, 96,128,192,160, 96, 0, 64, 32, 0, 0}; +static const GLubyte TimesRoman10_Character_234[] = { 4, 0, 0, 0, 0, 96,128,192,160, 96, 0,160, 64, 0, 0}; +static const GLubyte TimesRoman10_Character_235[] = { 4, 0, 0, 0, 0, 96,128,192,160, 96, 0,160, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_236[] = { 4, 0, 0, 0, 0,224, 64, 64, 64,192, 0, 64,128, 0, 0}; +static const GLubyte TimesRoman10_Character_237[] = { 4, 0, 0, 0, 0,224, 64, 64, 64,192, 0, 64, 32, 0, 0}; +static const GLubyte TimesRoman10_Character_238[] = { 4, 0, 0, 0, 0,224, 64, 64, 64,192, 0,160, 64, 0, 0}; +static const GLubyte TimesRoman10_Character_239[] = { 4, 0, 0, 0, 0,224, 64, 64, 64,192, 0,160, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_240[] = { 5, 0, 0, 0, 0, 96,144,144,144,112,160,112, 64, 0, 0}; +static const GLubyte TimesRoman10_Character_241[] = { 5, 0, 0, 0, 0,216,144,144,144,224, 0,160, 80, 0, 0}; +static const GLubyte TimesRoman10_Character_242[] = { 5, 0, 0, 0, 0, 96,144,144,144, 96, 0, 32, 64, 0, 0}; +static const GLubyte TimesRoman10_Character_243[] = { 5, 0, 0, 0, 0, 96,144,144,144, 96, 0, 64, 32, 0, 0}; +static const GLubyte TimesRoman10_Character_244[] = { 5, 0, 0, 0, 0, 96,144,144,144, 96, 0,160, 64, 0, 0}; +static const GLubyte TimesRoman10_Character_245[] = { 5, 0, 0, 0, 0, 96,144,144,144, 96, 0,160, 80, 0, 0}; +static const GLubyte TimesRoman10_Character_246[] = { 5, 0, 0, 0, 0, 96,144,144,144, 96, 0,160, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_247[] = { 6, 0, 0, 0, 0, 32, 0,248, 0, 32, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_248[] = { 5, 0, 0, 0, 0,224,144,144,144,112, 8, 0, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_249[] = { 5, 0, 0, 0, 0,104,144,144,144,144, 0, 32, 64, 0, 0}; +static const GLubyte TimesRoman10_Character_250[] = { 5, 0, 0, 0, 0,104,144,144,144,144, 0, 64, 32, 0, 0}; +static const GLubyte TimesRoman10_Character_251[] = { 5, 0, 0, 0, 0,104,144,144,144,144, 0, 80, 32, 0, 0}; +static const GLubyte TimesRoman10_Character_252[] = { 5, 0, 0, 0, 0,104,144,144,144,144, 0, 80, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_253[] = { 5, 0, 0,128,192, 64, 96,160,144,184, 0, 32, 16, 0, 0}; +static const GLubyte TimesRoman10_Character_254[] = { 5, 0, 0,192,128,224,144,144,144,224,128,128, 0, 0, 0}; +static const GLubyte TimesRoman10_Character_255[] = { 5, 0, 0,128,192, 64, 96,160,144,184, 0,160, 0, 0, 0}; + +/* The font characters mapping: */ +static const GLubyte* TimesRoman10_Character_Map[] = {TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032, + TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032, + TimesRoman10_Character_032,TimesRoman10_Character_033,TimesRoman10_Character_034,TimesRoman10_Character_035,TimesRoman10_Character_036,TimesRoman10_Character_037,TimesRoman10_Character_038,TimesRoman10_Character_039,TimesRoman10_Character_040,TimesRoman10_Character_041,TimesRoman10_Character_042,TimesRoman10_Character_043,TimesRoman10_Character_044,TimesRoman10_Character_045,TimesRoman10_Character_046,TimesRoman10_Character_047, + TimesRoman10_Character_048,TimesRoman10_Character_049,TimesRoman10_Character_050,TimesRoman10_Character_051,TimesRoman10_Character_052,TimesRoman10_Character_053,TimesRoman10_Character_054,TimesRoman10_Character_055,TimesRoman10_Character_056,TimesRoman10_Character_057,TimesRoman10_Character_058,TimesRoman10_Character_059,TimesRoman10_Character_060,TimesRoman10_Character_061,TimesRoman10_Character_062,TimesRoman10_Character_063, + TimesRoman10_Character_064,TimesRoman10_Character_065,TimesRoman10_Character_066,TimesRoman10_Character_067,TimesRoman10_Character_068,TimesRoman10_Character_069,TimesRoman10_Character_070,TimesRoman10_Character_071,TimesRoman10_Character_072,TimesRoman10_Character_073,TimesRoman10_Character_074,TimesRoman10_Character_075,TimesRoman10_Character_076,TimesRoman10_Character_077,TimesRoman10_Character_078,TimesRoman10_Character_079, + TimesRoman10_Character_080,TimesRoman10_Character_081,TimesRoman10_Character_082,TimesRoman10_Character_083,TimesRoman10_Character_084,TimesRoman10_Character_085,TimesRoman10_Character_086,TimesRoman10_Character_087,TimesRoman10_Character_088,TimesRoman10_Character_089,TimesRoman10_Character_090,TimesRoman10_Character_091,TimesRoman10_Character_092,TimesRoman10_Character_093,TimesRoman10_Character_094,TimesRoman10_Character_095, + TimesRoman10_Character_096,TimesRoman10_Character_097,TimesRoman10_Character_098,TimesRoman10_Character_099,TimesRoman10_Character_100,TimesRoman10_Character_101,TimesRoman10_Character_102,TimesRoman10_Character_103,TimesRoman10_Character_104,TimesRoman10_Character_105,TimesRoman10_Character_106,TimesRoman10_Character_107,TimesRoman10_Character_108,TimesRoman10_Character_109,TimesRoman10_Character_110,TimesRoman10_Character_111, + TimesRoman10_Character_112,TimesRoman10_Character_113,TimesRoman10_Character_114,TimesRoman10_Character_115,TimesRoman10_Character_116,TimesRoman10_Character_117,TimesRoman10_Character_118,TimesRoman10_Character_119,TimesRoman10_Character_120,TimesRoman10_Character_121,TimesRoman10_Character_122,TimesRoman10_Character_123,TimesRoman10_Character_124,TimesRoman10_Character_125,TimesRoman10_Character_126,TimesRoman10_Character_032, + TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032, + TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032,TimesRoman10_Character_032, + TimesRoman10_Character_160,TimesRoman10_Character_161,TimesRoman10_Character_162,TimesRoman10_Character_163,TimesRoman10_Character_164,TimesRoman10_Character_165,TimesRoman10_Character_166,TimesRoman10_Character_167,TimesRoman10_Character_168,TimesRoman10_Character_169,TimesRoman10_Character_170,TimesRoman10_Character_171,TimesRoman10_Character_172,TimesRoman10_Character_173,TimesRoman10_Character_174,TimesRoman10_Character_175, + TimesRoman10_Character_176,TimesRoman10_Character_177,TimesRoman10_Character_178,TimesRoman10_Character_179,TimesRoman10_Character_180,TimesRoman10_Character_181,TimesRoman10_Character_182,TimesRoman10_Character_183,TimesRoman10_Character_184,TimesRoman10_Character_185,TimesRoman10_Character_186,TimesRoman10_Character_187,TimesRoman10_Character_188,TimesRoman10_Character_189,TimesRoman10_Character_190,TimesRoman10_Character_191, + TimesRoman10_Character_192,TimesRoman10_Character_193,TimesRoman10_Character_194,TimesRoman10_Character_195,TimesRoman10_Character_196,TimesRoman10_Character_197,TimesRoman10_Character_198,TimesRoman10_Character_199,TimesRoman10_Character_200,TimesRoman10_Character_201,TimesRoman10_Character_202,TimesRoman10_Character_203,TimesRoman10_Character_204,TimesRoman10_Character_205,TimesRoman10_Character_206,TimesRoman10_Character_207, + TimesRoman10_Character_208,TimesRoman10_Character_209,TimesRoman10_Character_210,TimesRoman10_Character_211,TimesRoman10_Character_212,TimesRoman10_Character_213,TimesRoman10_Character_214,TimesRoman10_Character_215,TimesRoman10_Character_216,TimesRoman10_Character_217,TimesRoman10_Character_218,TimesRoman10_Character_219,TimesRoman10_Character_220,TimesRoman10_Character_221,TimesRoman10_Character_222,TimesRoman10_Character_223, + TimesRoman10_Character_224,TimesRoman10_Character_225,TimesRoman10_Character_226,TimesRoman10_Character_227,TimesRoman10_Character_228,TimesRoman10_Character_229,TimesRoman10_Character_230,TimesRoman10_Character_231,TimesRoman10_Character_232,TimesRoman10_Character_233,TimesRoman10_Character_234,TimesRoman10_Character_235,TimesRoman10_Character_236,TimesRoman10_Character_237,TimesRoman10_Character_238,TimesRoman10_Character_239, + TimesRoman10_Character_240,TimesRoman10_Character_241,TimesRoman10_Character_242,TimesRoman10_Character_243,TimesRoman10_Character_244,TimesRoman10_Character_245,TimesRoman10_Character_246,TimesRoman10_Character_247,TimesRoman10_Character_248,TimesRoman10_Character_249,TimesRoman10_Character_250,TimesRoman10_Character_251,TimesRoman10_Character_252,TimesRoman10_Character_253,TimesRoman10_Character_254,TimesRoman10_Character_255,NULL}; + +/* The font structure: */ +SFG_Font fgFontTimesRoman10 = { "-adobe-times-medium-r-normal--10-100-75-75-p-54-iso8859-1", 256, 14, TimesRoman10_Character_Map, 0, 4 }; +/* +static const GLubyte TimesRoman24_Character_000[] = { 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 64, 0, 64, 0, 0, 0, 64, 0, 64, 0, 0, 0, 64, 0, 64, 0, 0, 0, 64, 0, 64, 0, 0, 0, 64, 0, 64, 0, 0, 0, 64, 0, 64, 0, 0, 0, 64, 0, 64, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_001[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_002[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_003[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_004[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_005[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_006[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_007[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_008[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_009[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_010[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_011[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_012[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_013[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_014[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_015[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_016[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_017[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_018[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_019[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_020[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_021[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_022[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_023[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_024[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_025[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_026[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_027[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_028[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_029[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_030[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_031[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +*/ +static const GLubyte TimesRoman24_Character_032[] = { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_033[] = { 8, 0, 0, 0, 0, 0, 0, 0, 24, 24, 0, 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_034[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0,102, 0,102, 0,102, 0,102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_035[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 17, 0, 17, 0, 17, 0,127,224,127,224, 8,128, 8,128, 8,128, 63,240, 63,240, 4, 64, 4, 64, 4, 64, 4, 64, 4, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_036[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 63, 0,229,192,196,192,132, 96,132, 96, 4, 96, 4,224, 7,192, 7,128, 30, 0, 60, 0,116, 0,100, 0,100, 32,100, 96, 52,224, 31,128, 4, 0, 4, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_037[] = { 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 30, 0, 12, 57, 0, 6, 48,128, 2, 48, 64, 3, 48, 64, 1,152, 64, 0,140,192, 0,199,128, 60, 96, 0,114, 32, 0, 97, 48, 0, 96,152, 0, 96,136, 0, 48,140, 0, 25,254, 0, 15, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_038[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 0, 63,191, 0,112,240,128, 96, 96, 0, 96,224, 0, 96,208, 0, 49,144, 0, 27,136, 0, 15, 12, 0, 7, 31, 0, 7,128, 0, 14,192, 0, 12, 96, 0, 12, 32, 0, 12, 32, 0, 6, 96, 0, 3,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_039[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 12, 4, 28, 24, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_040[] = { 8, 0, 0, 2, 4, 8, 24, 16, 48, 48, 96, 96, 96, 96, 96, 96, 96, 96, 48, 48, 16, 24, 8, 4, 2, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_041[] = { 8, 0, 0, 64, 32, 16, 24, 8, 12, 12, 6, 6, 6, 6, 6, 6, 6, 6, 12, 12, 8, 24, 16, 32, 64, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_042[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 7, 0, 50, 96, 58,224, 7, 0, 58,224, 50, 96, 7, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_043[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0,127,248,127,248, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_044[] = { 7, 0, 0, 0, 0, 48, 24, 8, 56, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_045[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,248,127,248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_046[] = { 6, 0, 0, 0, 0, 0, 0, 0, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_047[] = { 7, 0, 0, 0, 0,192,192,192, 64, 96, 96, 32, 48, 48, 16, 24, 24, 8, 12, 12, 4, 6, 6, 6, 6, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_048[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 25,128, 48,192, 48,192,112,224, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 48,192, 48,192, 25,128, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_049[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,192, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 30, 0, 6, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_050[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,192,127,224, 48, 32, 24, 0, 12, 0, 6, 0, 2, 0, 3, 0, 1,128, 1,128, 0,192, 0,192, 64,192, 64,192, 33,192, 63,128, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_051[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0,115, 0, 97,128, 0,128, 0,192, 0,192, 0,192, 1,192, 3,128, 15, 0, 6, 0, 3, 0, 65,128, 65,128, 35,128, 63, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_052[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,128, 1,128, 1,128, 1,128,127,224,127,224, 97,128, 33,128, 49,128, 17,128, 25,128, 9,128, 13,128, 5,128, 3,128, 3,128, 1,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_053[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0,113,192, 96,192, 0, 96, 0, 96, 0, 96, 0, 96, 0,224, 1,192, 7,192, 63, 0, 60, 0, 48, 0, 16, 0, 16, 0, 15,192, 15,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_054[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 61,192, 48,192,112, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,192,121,192,119, 0, 48, 0, 56, 0, 24, 0, 12, 0, 7, 0, 1,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_055[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 12, 0, 6, 0, 6, 0, 6, 0, 2, 0, 3, 0, 3, 0, 1, 0, 1,128, 1,128, 0,128, 0,192, 64,192, 96, 96,127,224, 63,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_056[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 57,192,112,192, 96, 96, 96, 96, 96, 96, 32,224, 48,192, 27,128, 15, 0, 15, 0, 25,128, 48,192, 48,192, 48,192, 25,128, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_057[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120, 0, 14, 0, 3, 0, 1,128, 1,192, 0,192, 14,192, 57,224, 48,224, 96, 96, 96, 96, 96, 96, 96, 96, 96,224, 48,192, 59,192, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_058[] = { 6, 0, 0, 0, 0, 0, 0, 0, 48, 48, 0, 0, 0, 0, 0, 0, 0, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_059[] = { 7, 0, 0, 0, 0, 48, 24, 8, 56, 48, 0, 0, 0, 0, 0, 0, 0, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_060[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0,224, 3,128, 14, 0, 56, 0, 96, 0, 56, 0, 14, 0, 3,128, 0,224, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_061[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,248,127,248, 0, 0, 0, 0,127,248,127,248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_062[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 56, 0, 14, 0, 3,128, 0,224, 0, 48, 0,224, 3,128, 14, 0, 56, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_063[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 12, 0, 0, 0, 0, 0, 4, 0, 4, 0, 4, 0, 6, 0, 6, 0, 3, 0, 3,128, 1,192, 48,192, 48,192, 32,192, 49,128, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_064[] = { 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 0, 3,131, 0, 6, 0, 0, 12, 0, 0, 24,119,128, 24,222,192, 49,142, 96, 49,134, 32, 49,134, 48, 49,134, 16, 49,131, 16, 48,195, 16, 48,227, 16, 56,127, 16, 24, 59, 48, 28, 0, 32, 14, 0, 96, 7, 0,192, 3,195,128, 0,254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_065[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 31,128, 48, 6, 0, 16, 6, 0, 16, 12, 0, 24, 12, 0, 8, 12, 0, 15,248, 0, 12, 24, 0, 4, 24, 0, 4, 48, 0, 6, 48, 0, 2, 48, 0, 2, 96, 0, 1, 96, 0, 1,192, 0, 1,192, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_066[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,240, 24, 60, 24, 12, 24, 6, 24, 6, 24, 6, 24, 12, 24, 28, 31,240, 24, 32, 24, 24, 24, 12, 24, 12, 24, 12, 24, 24, 24, 56,127,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_067[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 15, 28, 28, 4, 48, 2, 48, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0, 48, 2, 48, 2, 28, 6, 14, 30, 3,242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_068[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,224, 0, 24, 56, 0, 24, 28, 0, 24, 6, 0, 24, 6, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0, 24, 6, 0, 24, 6, 0, 24, 28, 0, 24, 56, 0,127,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_069[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,252, 24, 12, 24, 4, 24, 4, 24, 0, 24, 0, 24, 32, 24, 32, 31,224, 24, 32, 24, 32, 24, 0, 24, 0, 24, 8, 24, 8, 24, 24,127,248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_070[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 16, 24, 16, 31,240, 24, 16, 24, 16, 24, 0, 24, 0, 24, 8, 24, 8, 24, 24,127,248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_071[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 15, 28, 0, 28, 14, 0, 48, 6, 0, 48, 6, 0, 96, 6, 0, 96, 6, 0, 96, 31,128, 96, 0, 0, 96, 0, 0, 96, 0, 0, 96, 0, 0, 48, 2, 0, 48, 2, 0, 28, 6, 0, 14, 30, 0, 3,242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_072[] = { 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 15,192, 24, 3, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0, 31,255, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0,126, 15,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_073[] = { 8, 0, 0, 0, 0, 0, 0, 0,126, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,126, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_074[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0,102, 0, 99, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 15,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_075[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 15,128, 24, 7, 0, 24, 14, 0, 24, 28, 0, 24, 56, 0, 24,112, 0, 24,224, 0, 25,192, 0, 31,128, 0, 31, 0, 0, 25,128, 0, 24,192, 0, 24, 96, 0, 24, 48, 0, 24, 24, 0, 24, 12, 0,126, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_076[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,252, 24, 12, 24, 4, 24, 4, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0,126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_077[] = { 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,124, 16,252, 16, 48, 48, 16, 48, 48, 16,104, 48, 16,104, 48, 16,196, 48, 16,196, 48, 17,132, 48, 17,130, 48, 19, 2, 48, 19, 1, 48, 22, 1, 48, 22, 1, 48, 28, 0,176, 28, 0,176, 24, 0,112,120, 0,124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_078[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,124, 6, 0, 16, 14, 0, 16, 14, 0, 16, 26, 0, 16, 50, 0, 16, 50, 0, 16, 98, 0, 16,194, 0, 16,194, 0, 17,130, 0, 19, 2, 0, 19, 2, 0, 22, 2, 0, 28, 2, 0, 28, 2, 0, 24, 2, 0,120, 15,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_079[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 14, 28, 0, 28, 14, 0, 48, 3, 0, 48, 3, 0, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 48, 3, 0, 48, 3, 0, 28, 14, 0, 14, 28, 0, 3,240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_080[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 31,224, 24, 56, 24, 24, 24, 12, 24, 12, 24, 12, 24, 24, 24, 56,127,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_081[] = { 18, 0, 0, 0, 0, 0, 0, 0, 7,128, 0, 28, 0, 0, 56, 0, 0,112, 0, 0,224, 0, 3,240, 0, 14, 28, 0, 28, 14, 0, 48, 3, 0, 48, 3, 0, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 48, 3, 0, 48, 3, 0, 28, 14, 0, 14, 28, 0, 3,240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_082[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 15, 24, 14, 24, 28, 24, 56, 24, 48, 24, 96, 24,224, 25,192, 31,224, 24, 56, 24, 24, 24, 28, 24, 12, 24, 28, 24, 24, 24, 56,127,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_083[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 0,120,192, 96, 96, 64, 48, 64, 48, 0, 48, 0,112, 1,224, 7,192, 15, 0, 60, 0,112, 0, 96, 32, 96, 32, 96, 96, 49,224, 15, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_084[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,224, 1,128, 1,128, 1,128, 1,128, 1,128, 1,128, 1,128, 1,128, 1,128, 1,128, 1,128, 1,128, 65,130, 65,130, 97,134,127,254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_085[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 14, 24, 0, 12, 4, 0, 24, 4, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0,126, 15,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_086[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,128, 0, 1,128, 0, 1,128, 0, 3,192, 0, 3, 64, 0, 3, 96, 0, 6, 32, 0, 6, 32, 0, 6, 48, 0, 12, 16, 0, 12, 24, 0, 24, 8, 0, 24, 8, 0, 24, 12, 0, 48, 4, 0, 48, 6, 0,252, 31,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_087[] = { 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,131, 0, 1,131, 0, 1,131,128, 3,135,128, 3, 70,128, 3, 70,192, 6, 70, 64, 6, 76, 64, 6, 76, 96, 12, 44, 96, 12, 44, 32, 24, 44, 32, 24, 24, 48, 24, 24, 16, 48, 24, 16, 48, 24, 24,252,126,126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_088[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 15,192, 48, 3,128, 24, 7, 0, 8, 14, 0, 4, 12, 0, 6, 24, 0, 2, 56, 0, 1,112, 0, 0,224, 0, 0,192, 0, 1,192, 0, 3,160, 0, 3, 16, 0, 6, 8, 0, 14, 12, 0, 28, 6, 0,126, 15,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_089[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,224, 1,128, 1,128, 1,128, 1,128, 1,128, 1,128, 3,192, 3, 64, 6, 96, 6, 32, 12, 48, 28, 16, 24, 24, 56, 8, 48, 12,252, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_090[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,252,112, 12, 56, 4, 24, 4, 28, 0, 12, 0, 14, 0, 7, 0, 3, 0, 3,128, 1,128, 1,192, 0,224, 64, 96, 64,112, 96, 56,127,248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_091[] = { 8, 0, 0, 0, 62, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 62, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_092[] = { 7, 0, 0, 0, 0, 0, 0, 0, 6, 6, 4, 12, 12, 8, 24, 24, 16, 48, 48, 32, 96, 96, 64,192,192, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_093[] = { 8, 0, 0, 0,124, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,124, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_094[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 64, 96,192, 32,128, 49,128, 17, 0, 27, 0, 10, 0, 14, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_095[] = { 13, 0, 0, 0, 0,255,248,255,248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_096[] = { 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48,112, 64, 96, 48, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_097[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,192,125,128, 99,128, 97,128, 97,128, 49,128, 29,128, 7,128, 1,128, 49,128, 51,128, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_098[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 57,192, 48,192, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48,192, 57,192, 55, 0, 48, 0, 48, 0, 48, 0, 48, 0,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_099[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 63,128, 56, 64,112, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0, 32,192, 49,192, 15,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_100[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 96, 57,192, 48,192, 96,192, 96,192, 96,192, 96,192, 96,192, 96,192, 48,192, 57,192, 14,192, 0,192, 0,192, 0,192, 0,192, 1,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_101[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 63,128, 56, 64,112, 0, 96, 0, 96, 0, 96, 0,127,192, 96,192, 32,192, 49,128, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_102[] = { 7, 0, 0, 0, 0, 0, 0, 0,120, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,254, 48, 48, 48, 22, 14, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_103[] = { 12, 0, 0, 0, 0, 31,128,120,224, 96, 48, 96, 16, 48, 48, 31,224, 63,128, 48, 0, 24, 0, 31, 0, 25,128, 48,192, 48,192, 48,192, 48,192, 25,128, 15,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_104[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120,240, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 56,224, 55,192, 51,128, 48, 0, 48, 0, 48, 0, 48, 0,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_105[] = { 6, 0, 0, 0, 0, 0, 0, 0,120, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,112, 0, 0, 0, 48, 48, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_106[] = { 6, 0, 0,192,224, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,112, 0, 0, 0, 48, 48, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_107[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,121,240, 48,224, 49,192, 51,128, 55, 0, 54, 0, 60, 0, 52, 0, 50, 0, 51, 0, 49,128, 51,224, 48, 0, 48, 0, 48, 0, 48, 0,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_108[] = { 6, 0, 0, 0, 0, 0, 0, 0,120, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,112, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_109[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120,241,224, 48, 96,192, 48, 96,192, 48, 96,192, 48, 96,192, 48, 96,192, 48, 96,192, 48, 96,192, 48, 96,192, 56,241,192, 55,207,128,115,135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_110[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120,240, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 56,224, 55,192,115,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_111[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 57,192, 48,192, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 48,192, 57,192, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_112[] = { 12, 0, 0, 0, 0,120, 0, 48, 0, 48, 0, 48, 0, 48, 0, 55, 0, 57,192, 48,192, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48,192, 57,192,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_113[] = { 12, 0, 0, 0, 0, 1,224, 0,192, 0,192, 0,192, 0,192, 14,192, 57,192, 48,192, 96,192, 96,192, 96,192, 96,192, 96,192, 96,192, 48,192, 57,192, 14,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_114[] = { 8, 0, 0, 0, 0, 0, 0, 0,120, 48, 48, 48, 48, 48, 48, 48, 48, 59, 55,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_115[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,124, 0, 99, 0, 65,128, 1,128, 3,128, 15, 0, 62, 0, 56, 0,112, 0, 97, 0, 51, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_116[] = { 7, 0, 0, 0, 0, 0, 0, 0, 28, 50, 48, 48, 48, 48, 48, 48, 48, 48, 48,254,112, 48, 16, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_117[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14,112, 31, 96, 56,224, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96,112,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_118[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 14, 0, 14, 0, 26, 0, 25, 0, 25, 0, 49, 0, 48,128, 48,128, 96,128, 96,192,241,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_119[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 16, 0, 14, 56, 0, 14, 56, 0, 26, 40, 0, 26,100, 0, 25,100, 0, 49,100, 0, 48,194, 0, 48,194, 0, 96,194, 0, 96,195, 0,241,231,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_120[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120,240, 48, 96, 16,192, 25,192, 13,128, 7, 0, 6, 0, 13, 0, 28,128, 24,192, 48, 96,120,240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_121[] = { 11, 0, 0, 0, 0,224, 0,240, 0, 24, 0, 8, 0, 12, 0, 4, 0, 14, 0, 14, 0, 26, 0, 25, 0, 25, 0, 49, 0, 48,128, 48,128, 96,128, 96,192,241,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_122[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,128, 97,128, 48,128, 56, 0, 24, 0, 28, 0, 12, 0, 14, 0, 7, 0, 67, 0, 97,128,127,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_123[] = { 10, 0, 0, 0, 0, 3,128, 6, 0, 12, 0, 12, 0, 12, 0, 12, 0, 12, 0, 12, 0, 8, 0, 24, 0, 16, 0, 96, 0, 16, 0, 24, 0, 8, 0, 12, 0, 12, 0, 12, 0, 12, 0, 12, 0, 6, 0, 3,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_124[] = { 6, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_125[] = { 10, 0, 0, 0, 0,112, 0, 24, 0, 12, 0, 12, 0, 12, 0, 12, 0, 12, 0, 12, 0, 4, 0, 6, 0, 2, 0, 1,128, 2, 0, 6, 0, 4, 0, 12, 0, 12, 0, 12, 0, 12, 0, 12, 0, 24, 0,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_126[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65,192, 99,224, 62, 48, 28, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +/* +static const GLubyte TimesRoman24_Character_127[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_128[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_129[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_130[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_131[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_132[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_133[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_134[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_135[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_136[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_137[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_138[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_139[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_140[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_141[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_142[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_143[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_144[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_145[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_146[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_147[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_148[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_149[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_150[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_151[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_152[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_153[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_154[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_155[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_156[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_157[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_158[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_159[] = { 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 64, 0, 64, 0, 0, 0, 0, 0, 85, 85, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +*/ +static const GLubyte TimesRoman24_Character_160[] = { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_161[] = { 8, 0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_162[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 32, 0, 31, 0, 63,128, 56, 64,104, 0,100, 0,100, 0,100, 0, 98, 0, 98, 0, 33,192, 49,192, 15,128, 0,128, 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_163[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,115,192, 95, 96, 60, 32, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0,126, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24,192, 12,192, 7,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_164[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 48,119,112, 63,224, 24,192, 48, 96, 48, 96, 48, 96, 48, 96, 24,192, 63,224,119,112, 96, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_165[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,192, 3, 0, 3, 0, 3, 0, 3, 0, 31,224, 3, 0, 31,224, 3, 0, 7,128, 12,128, 12,192, 24, 64, 24, 96, 48, 32,112, 48,248,124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_166[] = { 6, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_167[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 25, 0, 24,128, 1,128, 3,128, 7, 0, 14, 0, 29, 0, 56,128, 48,192, 32,192, 33,192, 19,128, 15, 0, 14, 0, 28, 0, 24, 0, 17,128, 9,128, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_168[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,102,102, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_169[] = { 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,248, 0, 14, 14, 0, 24, 3, 0, 48,225,128, 35,184,128, 98, 12,192, 70, 0, 64, 68, 0, 64, 68, 0, 64, 68, 0, 64, 70, 0, 64, 98, 12,192, 35,152,128, 48,241,128, 24, 3, 0, 14, 14, 0, 3,248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_170[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 0,118,204,204,124, 12,204,120, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_171[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 32, 6, 96, 12,192, 25,128, 51, 0, 51, 0, 25,128, 12,192, 6, 96, 2, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_172[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24,127,248,127,248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_173[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_174[] = { 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,248, 0, 14, 14, 0, 24, 3, 0, 48, 1,128, 35,140,128, 97, 24,192, 65, 16, 64, 65, 32, 64, 65,240, 64, 65, 24, 64, 65, 8, 64, 97, 8,192, 33, 24,128, 51,241,128, 24, 3, 0, 14, 14, 0, 3,248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_175[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126,126, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_176[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 34, 0, 65, 0, 65, 0, 65, 0, 34, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_177[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,248,127,248, 0, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0,127,248,127,248, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_178[] = { 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 68, 32, 48, 16, 8, 12,140, 76, 56, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_179[] = { 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,112,136,140, 12, 8, 48, 8,140, 76, 56, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_180[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 24, 14, 6, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_181[] = { 13, 0, 0, 0, 0, 32, 0,112, 0, 96, 0, 32, 0, 32, 0, 46,112, 63, 96, 56,224, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96,112,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_182[] = { 11, 0, 0, 0, 0, 4,128, 4,128, 4,128, 4,128, 4,128, 4,128, 4,128, 4,128, 4,128, 4,128, 4,128, 12,128, 28,128, 60,128, 60,128,124,128,124,128,124,128, 60,128, 60,128, 28,128, 15,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_183[] = { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_184[] = { 8, 0, 60,102, 6, 30, 24, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_185[] = { 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,124, 16, 16, 16, 16, 16, 16, 80, 48, 16, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_186[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 0, 60,102,102,102,102,102, 60, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_187[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 51, 0, 25,128, 12,192, 6, 96, 6, 96, 12,192, 25,128, 51, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_188[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 2, 0, 8, 2, 0, 12,127,128, 4, 34, 0, 6, 50, 0, 3, 18, 0, 1, 10, 0,125,142, 0, 16,134, 0, 16,194, 0, 16, 96, 0, 16, 32, 0, 16, 48, 0, 16, 16, 0, 80, 24, 0, 48, 12, 0, 16, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_189[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 63, 0, 8, 17, 0, 12, 8, 0, 4, 12, 0, 6, 4, 0, 3, 2, 0, 1, 3, 0,125,163, 0, 16,147, 0, 16,206, 0, 16, 96, 0, 16, 32, 0, 16, 48, 0, 16, 16, 0, 80, 24, 0, 48, 12, 0, 16, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_190[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 2, 0, 8, 2, 0, 12,127,128, 4, 34, 0, 6, 50, 0, 3, 18, 0, 1, 10, 0,113,142, 0,136,134, 0,140,194, 0, 12, 96, 0, 8, 32, 0, 48, 48, 0, 8, 16, 0,140, 24, 0, 76, 12, 0, 56, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_191[] = { 11, 0, 0, 0, 0, 31, 0, 49,128, 96,128, 97,128, 97,128,112, 0, 56, 0, 24, 0, 28, 0, 12, 0, 12, 0, 4, 0, 4, 0, 0, 0, 0, 0, 6, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_192[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 31,128, 48, 6, 0, 16, 6, 0, 16, 12, 0, 24, 12, 0, 8, 12, 0, 15,248, 0, 12, 24, 0, 4, 24, 0, 4, 48, 0, 6, 48, 0, 2, 48, 0, 2, 96, 0, 1, 96, 0, 1,192, 0, 1,192, 0, 0,128, 0, 0, 0, 0, 0, 32, 0, 0,192, 0, 3,128, 0, 3, 0, 0}; +static const GLubyte TimesRoman24_Character_193[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 31,128, 48, 6, 0, 16, 6, 0, 16, 12, 0, 24, 12, 0, 8, 12, 0, 15,248, 0, 12, 24, 0, 4, 24, 0, 4, 48, 0, 6, 48, 0, 2, 48, 0, 2, 96, 0, 1, 96, 0, 1,192, 0, 1,192, 0, 0,128, 0, 0, 0, 0, 1, 0, 0, 0,192, 0, 0,112, 0, 0, 48, 0}; +static const GLubyte TimesRoman24_Character_194[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 31,128, 48, 6, 0, 16, 6, 0, 16, 12, 0, 24, 12, 0, 8, 12, 0, 15,248, 0, 12, 24, 0, 4, 24, 0, 4, 48, 0, 6, 48, 0, 2, 48, 0, 2, 96, 0, 1, 96, 0, 1,192, 0, 1,192, 0, 0,128, 0, 0, 0, 0, 8, 16, 0, 6, 96, 0, 3,192, 0, 1,128, 0}; +static const GLubyte TimesRoman24_Character_195[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 31,128, 48, 7, 0, 16, 6, 0, 16, 12, 0, 24, 12, 0, 8, 12, 0, 15,248, 0, 12, 24, 0, 4, 24, 0, 4, 48, 0, 6, 48, 0, 2, 48, 0, 2, 96, 0, 1, 96, 0, 1,192, 0, 1,192, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 4,224, 0, 3,144, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_196[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 31,128, 48, 6, 0, 16, 6, 0, 16, 12, 0, 24, 12, 0, 8, 12, 0, 15,248, 0, 12, 24, 0, 4, 24, 0, 4, 48, 0, 6, 48, 0, 2, 48, 0, 2, 96, 0, 1, 96, 0, 1,192, 0, 1,192, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 6, 48, 0, 6, 48, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_197[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 31,128, 48, 6, 0, 16, 6, 0, 16, 12, 0, 24, 12, 0, 8, 12, 0, 15,248, 0, 12, 24, 0, 4, 24, 0, 4, 48, 0, 6, 48, 0, 2, 48, 0, 2, 96, 0, 1, 96, 0, 1,192, 0, 1,192, 0, 0,128, 0, 1,192, 0, 2, 32, 0, 2, 32, 0, 1,192, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_198[] = { 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,249,255,240, 48, 96, 48, 16, 96, 16, 16, 96, 16, 24, 96, 0, 8, 96, 0, 15,224,128, 12, 96,128, 4,127,128, 4, 96,128, 6, 96,128, 2, 96, 0, 2, 96, 0, 1, 96, 32, 1, 96, 32, 1,224, 96, 3,255,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_199[] = { 16, 0, 0, 3,192, 6, 96, 0, 96, 1,224, 1,128, 0,128, 3,240, 15, 28, 28, 4, 48, 2, 48, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0, 48, 2, 48, 2, 28, 6, 14, 30, 3,242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_200[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,252, 24, 12, 24, 4, 24, 4, 24, 0, 24, 0, 24, 32, 24, 32, 31,224, 24, 32, 24, 32, 24, 0, 24, 0, 24, 8, 24, 8, 24, 24,127,248, 0, 0, 0,128, 3, 0, 14, 0, 12, 0}; +static const GLubyte TimesRoman24_Character_201[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,252, 24, 12, 24, 4, 24, 4, 24, 0, 24, 0, 24, 32, 24, 32, 31,224, 24, 32, 24, 32, 24, 0, 24, 0, 24, 8, 24, 8, 24, 24,127,248, 0, 0, 2, 0, 1,128, 0,224, 0, 96}; +static const GLubyte TimesRoman24_Character_202[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,252, 24, 12, 24, 4, 24, 4, 24, 0, 24, 0, 24, 32, 24, 32, 31,224, 24, 32, 24, 32, 24, 0, 24, 0, 24, 8, 24, 8, 24, 24,127,248, 0, 0, 8, 16, 6, 96, 3,192, 1,128}; +static const GLubyte TimesRoman24_Character_203[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,252, 24, 12, 24, 4, 24, 4, 24, 0, 24, 0, 24, 32, 24, 32, 31,224, 24, 32, 24, 32, 24, 0, 24, 0, 24, 8, 24, 8, 24, 24,127,248, 0, 0, 0, 0, 12,192, 12,192, 0, 0}; +static const GLubyte TimesRoman24_Character_204[] = { 8, 0, 0, 0, 0, 0, 0, 0,126, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,126, 0, 4, 24,112, 96}; +static const GLubyte TimesRoman24_Character_205[] = { 8, 0, 0, 0, 0, 0, 0, 0,126, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,126, 0, 32, 24, 14, 6}; +static const GLubyte TimesRoman24_Character_206[] = { 8, 0, 0, 0, 0, 0, 0, 0, 63, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 63, 0, 64, 51, 30, 12}; +static const GLubyte TimesRoman24_Character_207[] = { 8, 0, 0, 0, 0, 0, 0, 0,126, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,126, 0, 0,102,102, 0}; +static const GLubyte TimesRoman24_Character_208[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127,224, 0, 24, 56, 0, 24, 28, 0, 24, 6, 0, 24, 6, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0,255, 3, 0, 24, 3, 0, 24, 3, 0, 24, 3, 0, 24, 6, 0, 24, 6, 0, 24, 28, 0, 24, 56, 0,127,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_209[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,124, 6, 0, 16, 14, 0, 16, 14, 0, 16, 26, 0, 16, 50, 0, 16, 50, 0, 16, 98, 0, 16,194, 0, 16,194, 0, 17,130, 0, 19, 2, 0, 19, 2, 0, 22, 2, 0, 28, 2, 0, 28, 2, 0, 24, 2, 0,120, 15,128, 0, 0, 0, 0, 0, 0, 2,112, 0, 1,200, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_210[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 14, 28, 0, 28, 14, 0, 48, 3, 0, 48, 3, 0, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 48, 3, 0, 48, 3, 0, 28, 14, 0, 14, 28, 0, 3,240, 0, 0, 0, 0, 0, 32, 0, 0,192, 0, 3,128, 0, 3, 0, 0}; +static const GLubyte TimesRoman24_Character_211[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 14, 28, 0, 28, 14, 0, 48, 3, 0, 48, 3, 0, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 48, 3, 0, 48, 3, 0, 28, 14, 0, 14, 28, 0, 3,240, 0, 0, 0, 0, 0,128, 0, 0, 96, 0, 0, 56, 0, 0, 24, 0}; +static const GLubyte TimesRoman24_Character_212[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 14, 28, 0, 28, 14, 0, 48, 3, 0, 48, 3, 0, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 48, 3, 0, 48, 3, 0, 28, 14, 0, 14, 28, 0, 3,240, 0, 0, 0, 0, 4, 8, 0, 3, 48, 0, 1,224, 0, 0,192, 0}; +static const GLubyte TimesRoman24_Character_213[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 14, 28, 0, 28, 14, 0, 48, 3, 0, 48, 3, 0, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 48, 3, 0, 48, 3, 0, 28, 14, 0, 14, 28, 0, 3,240, 0, 0, 0, 0, 0, 0, 0, 2,112, 0, 1,200, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_214[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 14, 28, 0, 28, 14, 0, 48, 3, 0, 48, 3, 0, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 96, 1,128, 48, 3, 0, 48, 3, 0, 28, 14, 0, 14, 28, 0, 3,240, 0, 0, 0, 0, 0, 0, 0, 3, 48, 0, 3, 48, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_215[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 16, 48, 48, 24, 96, 12,192, 7,128, 3, 0, 7,128, 12,192, 24, 96, 48, 48, 32, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_216[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 19,240, 0, 14, 28, 0, 28, 14, 0, 52, 3, 0, 50, 3, 0, 97, 1,128, 97, 1,128, 96,129,128, 96,129,128, 96, 65,128, 96, 65,128, 96, 33,128, 48, 35, 0, 48, 19, 0, 28, 14, 0, 14, 28, 0, 3,242, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_217[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 14, 24, 0, 12, 4, 0, 24, 4, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0,126, 15,128, 0, 0, 0, 0, 32, 0, 0,192, 0, 3,128, 0, 3, 0, 0}; +static const GLubyte TimesRoman24_Character_218[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 14, 24, 0, 12, 4, 0, 24, 4, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0,126, 15,128, 0, 0, 0, 0,128, 0, 0, 96, 0, 0, 56, 0, 0, 24, 0}; +static const GLubyte TimesRoman24_Character_219[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 14, 24, 0, 12, 4, 0, 24, 4, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0,126, 15,128, 0, 0, 0, 4, 8, 0, 3, 48, 0, 1,224, 0, 0,192, 0}; +static const GLubyte TimesRoman24_Character_220[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 14, 24, 0, 12, 4, 0, 24, 4, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0, 24, 2, 0,126, 15,128, 0, 0, 0, 0, 0, 0, 3, 24, 0, 3, 24, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_221[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,224, 1,128, 1,128, 1,128, 1,128, 1,128, 1,128, 3,192, 3, 64, 6, 96, 6, 32, 12, 48, 28, 16, 24, 24, 56, 8, 48, 12,252, 63, 0, 0, 1, 0, 0,192, 0,112, 0, 48}; +static const GLubyte TimesRoman24_Character_222[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 0, 24, 0, 24, 0, 24, 0, 31,224, 24, 56, 24, 24, 24, 12, 24, 12, 24, 12, 24, 24, 24, 56, 31,224, 24, 0, 24, 0, 24, 0,126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_223[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,115,128, 54, 64, 54, 96, 48, 96, 48, 96, 48,224, 48,192, 49,192, 51,128, 54, 0, 49,128, 48,192, 48,192, 48,192, 48,192, 25,128, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_224[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,192,125,128, 99,128, 97,128, 97,128, 49,128, 29,128, 7,128, 1,128, 49,128, 51,128, 31, 0, 0, 0, 2, 0, 12, 0, 56, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_225[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,192,125,128, 99,128, 97,128, 97,128, 49,128, 29,128, 7,128, 1,128, 49,128, 51,128, 31, 0, 0, 0, 8, 0, 6, 0, 3,128, 1,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_226[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,192,125,128, 99,128, 97,128, 97,128, 49,128, 29,128, 7,128, 1,128, 49,128, 51,128, 31, 0, 0, 0, 33, 0, 18, 0, 30, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_227[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,192,125,128, 99,128, 97,128, 97,128, 49,128, 29,128, 7,128, 1,128, 49,128, 51,128, 31, 0, 0, 0, 0, 0, 46, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_228[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,192,125,128, 99,128, 97,128, 97,128, 49,128, 29,128, 7,128, 1,128, 49,128, 51,128, 31, 0, 0, 0, 0, 0, 51, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_229[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,192,125,128, 99,128, 97,128, 97,128, 49,128, 29,128, 7,128, 1,128, 49,128, 51,128, 31, 0, 0, 0, 14, 0, 17, 0, 17, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_230[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,120,125,252, 99,194, 97,128, 97,128, 49,128, 29,128, 7,254, 1,134, 49,134, 51,204, 30,120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_231[] = { 11, 0, 0, 30, 0, 51, 0, 3, 0, 15, 0, 12, 0, 4, 0, 15, 0, 63,128, 56, 64,112, 0, 96, 0, 96, 0, 96, 0, 96, 0, 96, 0, 32,192, 49,192, 15,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_232[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 63,128, 56, 64,112, 0, 96, 0, 96, 0, 96, 0,127,192, 96,192, 32,192, 49,128, 15, 0, 0, 0, 2, 0, 12, 0, 56, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_233[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 63,128, 56, 64,112, 0, 96, 0, 96, 0, 96, 0,127,192, 96,192, 32,192, 49,128, 15, 0, 0, 0, 8, 0, 6, 0, 3,128, 1,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_234[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 63,128, 56, 64,112, 0, 96, 0, 96, 0, 96, 0,127,192, 96,192, 32,192, 49,128, 15, 0, 0, 0, 16,128, 9, 0, 15, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_235[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 63,128, 56, 64,112, 0, 96, 0, 96, 0, 96, 0,127,192, 96,192, 32,192, 49,128, 15, 0, 0, 0, 0, 0, 25,128, 25,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_236[] = { 6, 0, 0, 0, 0, 0, 0, 0,120, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,112, 0, 8, 48,224,192, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_237[] = { 6, 0, 0, 0, 0, 0, 0, 0,120, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,112, 0, 64, 48, 28, 12, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_238[] = { 6, 0, 0, 0, 0, 0, 0, 0,120, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,112, 0,132, 72,120, 48, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_239[] = { 6, 0, 0, 0, 0, 0, 0, 0,120, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,112, 0, 0,204,204, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_240[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 57,192, 48,192, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 48,192, 57,192, 15,128, 99, 0, 30, 0, 15, 0, 56,192, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_241[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120,240, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 56,224, 55,192,115,128, 0, 0, 0, 0, 19,128, 14, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_242[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 57,192, 48,192, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 48,192, 57,192, 15, 0, 0, 0, 1, 0, 6, 0, 28, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_243[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 57,192, 48,192, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 48,192, 57,192, 15, 0, 0, 0, 4, 0, 3, 0, 1,192, 0,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_244[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 57,192, 48,192, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 48,192, 57,192, 15, 0, 0, 0, 16,128, 9, 0, 15, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_245[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 57,192, 48,192, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 48,192, 57,192, 15, 0, 0, 0, 0, 0, 19,128, 14, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_246[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 57,192, 48,192, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 48,192, 57,192, 15, 0, 0, 0, 0, 0, 25,128, 25,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_247[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0, 0,127,248,127,248, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_248[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0,111, 0, 57,192, 56,192,104, 96,108, 96,100, 96,102, 96, 98, 96, 99, 96, 49,192, 57,192, 15, 96, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_249[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14,112, 31, 96, 56,224, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96,112,224, 0, 0, 1, 0, 6, 0, 28, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_250[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14,112, 31, 96, 56,224, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96,112,224, 0, 0, 4, 0, 3, 0, 1,192, 0,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_251[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14,112, 31, 96, 56,224, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96,112,224, 0, 0, 16,128, 9, 0, 15, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_252[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14,112, 31, 96, 56,224, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96,112,224, 0, 0, 0, 0, 25,128, 25,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_253[] = { 11, 0, 0, 0, 0,224, 0,240, 0, 24, 0, 8, 0, 12, 0, 4, 0, 14, 0, 14, 0, 26, 0, 25, 0, 25, 0, 49, 0, 48,128, 48,128, 96,128, 96,192,241,224, 0, 0, 8, 0, 6, 0, 3,128, 1,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_254[] = { 12, 0, 0, 0, 0,120, 0, 48, 0, 48, 0, 48, 0, 48, 0, 55, 0, 57,192, 48,192, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48, 96, 48,192, 57,192, 55, 0, 48, 0, 48, 0, 48, 0, 48, 0,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte TimesRoman24_Character_255[] = { 11, 0, 0, 0, 0,224, 0,240, 0, 24, 0, 8, 0, 12, 0, 4, 0, 14, 0, 14, 0, 26, 0, 25, 0, 25, 0, 49, 0, 48,128, 48,128, 96,128, 96,192,241,224, 0, 0, 0, 0, 51, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +/* The font characters mapping: */ +static const GLubyte* TimesRoman24_Character_Map[] = {TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032, + TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032, + TimesRoman24_Character_032,TimesRoman24_Character_033,TimesRoman24_Character_034,TimesRoman24_Character_035,TimesRoman24_Character_036,TimesRoman24_Character_037,TimesRoman24_Character_038,TimesRoman24_Character_039,TimesRoman24_Character_040,TimesRoman24_Character_041,TimesRoman24_Character_042,TimesRoman24_Character_043,TimesRoman24_Character_044,TimesRoman24_Character_045,TimesRoman24_Character_046,TimesRoman24_Character_047, + TimesRoman24_Character_048,TimesRoman24_Character_049,TimesRoman24_Character_050,TimesRoman24_Character_051,TimesRoman24_Character_052,TimesRoman24_Character_053,TimesRoman24_Character_054,TimesRoman24_Character_055,TimesRoman24_Character_056,TimesRoman24_Character_057,TimesRoman24_Character_058,TimesRoman24_Character_059,TimesRoman24_Character_060,TimesRoman24_Character_061,TimesRoman24_Character_062,TimesRoman24_Character_063, + TimesRoman24_Character_064,TimesRoman24_Character_065,TimesRoman24_Character_066,TimesRoman24_Character_067,TimesRoman24_Character_068,TimesRoman24_Character_069,TimesRoman24_Character_070,TimesRoman24_Character_071,TimesRoman24_Character_072,TimesRoman24_Character_073,TimesRoman24_Character_074,TimesRoman24_Character_075,TimesRoman24_Character_076,TimesRoman24_Character_077,TimesRoman24_Character_078,TimesRoman24_Character_079, + TimesRoman24_Character_080,TimesRoman24_Character_081,TimesRoman24_Character_082,TimesRoman24_Character_083,TimesRoman24_Character_084,TimesRoman24_Character_085,TimesRoman24_Character_086,TimesRoman24_Character_087,TimesRoman24_Character_088,TimesRoman24_Character_089,TimesRoman24_Character_090,TimesRoman24_Character_091,TimesRoman24_Character_092,TimesRoman24_Character_093,TimesRoman24_Character_094,TimesRoman24_Character_095, + TimesRoman24_Character_096,TimesRoman24_Character_097,TimesRoman24_Character_098,TimesRoman24_Character_099,TimesRoman24_Character_100,TimesRoman24_Character_101,TimesRoman24_Character_102,TimesRoman24_Character_103,TimesRoman24_Character_104,TimesRoman24_Character_105,TimesRoman24_Character_106,TimesRoman24_Character_107,TimesRoman24_Character_108,TimesRoman24_Character_109,TimesRoman24_Character_110,TimesRoman24_Character_111, + TimesRoman24_Character_112,TimesRoman24_Character_113,TimesRoman24_Character_114,TimesRoman24_Character_115,TimesRoman24_Character_116,TimesRoman24_Character_117,TimesRoman24_Character_118,TimesRoman24_Character_119,TimesRoman24_Character_120,TimesRoman24_Character_121,TimesRoman24_Character_122,TimesRoman24_Character_123,TimesRoman24_Character_124,TimesRoman24_Character_125,TimesRoman24_Character_126,TimesRoman24_Character_032, + TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032, + TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032,TimesRoman24_Character_032, + TimesRoman24_Character_160,TimesRoman24_Character_161,TimesRoman24_Character_162,TimesRoman24_Character_163,TimesRoman24_Character_164,TimesRoman24_Character_165,TimesRoman24_Character_166,TimesRoman24_Character_167,TimesRoman24_Character_168,TimesRoman24_Character_169,TimesRoman24_Character_170,TimesRoman24_Character_171,TimesRoman24_Character_172,TimesRoman24_Character_173,TimesRoman24_Character_174,TimesRoman24_Character_175, + TimesRoman24_Character_176,TimesRoman24_Character_177,TimesRoman24_Character_178,TimesRoman24_Character_179,TimesRoman24_Character_180,TimesRoman24_Character_181,TimesRoman24_Character_182,TimesRoman24_Character_183,TimesRoman24_Character_184,TimesRoman24_Character_185,TimesRoman24_Character_186,TimesRoman24_Character_187,TimesRoman24_Character_188,TimesRoman24_Character_189,TimesRoman24_Character_190,TimesRoman24_Character_191, + TimesRoman24_Character_192,TimesRoman24_Character_193,TimesRoman24_Character_194,TimesRoman24_Character_195,TimesRoman24_Character_196,TimesRoman24_Character_197,TimesRoman24_Character_198,TimesRoman24_Character_199,TimesRoman24_Character_200,TimesRoman24_Character_201,TimesRoman24_Character_202,TimesRoman24_Character_203,TimesRoman24_Character_204,TimesRoman24_Character_205,TimesRoman24_Character_206,TimesRoman24_Character_207, + TimesRoman24_Character_208,TimesRoman24_Character_209,TimesRoman24_Character_210,TimesRoman24_Character_211,TimesRoman24_Character_212,TimesRoman24_Character_213,TimesRoman24_Character_214,TimesRoman24_Character_215,TimesRoman24_Character_216,TimesRoman24_Character_217,TimesRoman24_Character_218,TimesRoman24_Character_219,TimesRoman24_Character_220,TimesRoman24_Character_221,TimesRoman24_Character_222,TimesRoman24_Character_223, + TimesRoman24_Character_224,TimesRoman24_Character_225,TimesRoman24_Character_226,TimesRoman24_Character_227,TimesRoman24_Character_228,TimesRoman24_Character_229,TimesRoman24_Character_230,TimesRoman24_Character_231,TimesRoman24_Character_232,TimesRoman24_Character_233,TimesRoman24_Character_234,TimesRoman24_Character_235,TimesRoman24_Character_236,TimesRoman24_Character_237,TimesRoman24_Character_238,TimesRoman24_Character_239, + TimesRoman24_Character_240,TimesRoman24_Character_241,TimesRoman24_Character_242,TimesRoman24_Character_243,TimesRoman24_Character_244,TimesRoman24_Character_245,TimesRoman24_Character_246,TimesRoman24_Character_247,TimesRoman24_Character_248,TimesRoman24_Character_249,TimesRoman24_Character_250,TimesRoman24_Character_251,TimesRoman24_Character_252,TimesRoman24_Character_253,TimesRoman24_Character_254,TimesRoman24_Character_255,NULL}; + +/* The font structure: */ +SFG_Font fgFontTimesRoman24 = { "-adobe-times-medium-r-normal--24-240-75-75-p-124-iso8859-1", 256, 29, TimesRoman24_Character_Map, 0, 7 }; + diff --git a/src/fg_gamemode.c b/src/fg_gamemode.c new file mode 100644 index 0000000..f8559d4 --- /dev/null +++ b/src/fg_gamemode.c @@ -0,0 +1,168 @@ +/* + * fg_gamemode.c + * + * The game mode handling code. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Thu Dec 16 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" + + +/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ +extern void fgPlatformRememberState( void ); +extern void fgPlatformRestoreState( void ); +extern GLboolean fgPlatformChangeDisplayMode( GLboolean haveToTest ); +extern void fgPlatformEnterGameMode( void ); +extern void fgPlatformLeaveGameMode( void ); + + +/* -- INTERFACE FUNCTIONS -------------------------------------------------- */ + +/* + * Sets the game mode display string + */ +void FGAPIENTRY glutGameModeString( const char* string ) +{ + int width = -1, height = -1, depth = -1, refresh = -1; + + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGameModeString" ); + + /* + * This one seems a bit easier than glutInitDisplayString. The bad thing + * about it that I was unable to find the game mode string definition, so + * that I assumed it is: "[width]x[height]:[depth]@[refresh rate]", which + * appears in all GLUT game mode programs I have seen to date. + */ + if( sscanf( string, "%ix%i:%i@%i", &width, &height, &depth, &refresh ) != + 4 ) + if( sscanf( string, "%ix%i:%i", &width, &height, &depth ) != 3 ) + if( sscanf( string, "%ix%i@%i", &width, &height, &refresh ) != 3 ) + if( sscanf( string, "%ix%i", &width, &height ) != 2 ) + if( sscanf( string, ":%i@%i", &depth, &refresh ) != 2 ) + if( sscanf( string, ":%i", &depth ) != 1 ) + if( sscanf( string, "@%i", &refresh ) != 1 ) + fgWarning( + "unable to parse game mode string `%s'", + string + ); + + /* All values not specified are now set to -1, which means those + * aspects of the current display mode are not changed in + * fgPlatformChangeDisplayMode() above. + */ + fgState.GameModeSize.X = width; + fgState.GameModeSize.Y = height; + fgState.GameModeDepth = depth; + fgState.GameModeRefresh = refresh; +} + + + +/* + * Enters the game mode + */ +int FGAPIENTRY glutEnterGameMode( void ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutEnterGameMode" ); + + if( fgStructure.GameModeWindow ) + fgAddToWindowDestroyList( fgStructure.GameModeWindow ); + else + fgPlatformRememberState( ); + + if( ! fgPlatformChangeDisplayMode( GL_FALSE ) ) + { + fgWarning( "failed to change screen settings" ); + return 0; + } + + fgStructure.GameModeWindow = fgCreateWindow( + NULL, "FREEGLUT", GL_TRUE, 0, 0, + GL_TRUE, fgState.GameModeSize.X, fgState.GameModeSize.Y, + GL_TRUE, GL_FALSE + ); + + glutFullScreen(); + + fgPlatformEnterGameMode(); + + return fgStructure.GameModeWindow->ID; +} + +/* + * Leaves the game mode + */ +void FGAPIENTRY glutLeaveGameMode( void ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutLeaveGameMode" ); + + freeglut_return_if_fail( fgStructure.GameModeWindow ); + + fgAddToWindowDestroyList( fgStructure.GameModeWindow ); + fgStructure.GameModeWindow = NULL; + + fgPlatformLeaveGameMode(); + + fgPlatformRestoreState(); +} + +/* + * Returns information concerning the freeglut game mode + */ +int FGAPIENTRY glutGameModeGet( GLenum eWhat ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGameModeGet" ); + + switch( eWhat ) + { + case GLUT_GAME_MODE_ACTIVE: + return !!fgStructure.GameModeWindow; + + case GLUT_GAME_MODE_POSSIBLE: + return fgPlatformChangeDisplayMode( GL_TRUE ); + + case GLUT_GAME_MODE_WIDTH: + return fgState.GameModeSize.X; + + case GLUT_GAME_MODE_HEIGHT: + return fgState.GameModeSize.Y; + + case GLUT_GAME_MODE_PIXEL_DEPTH: + return fgState.GameModeDepth; + + case GLUT_GAME_MODE_REFRESH_RATE: + return fgState.GameModeRefresh; + + case GLUT_GAME_MODE_DISPLAY_CHANGED: + /* + * This is true if the game mode has been activated successfully.. + */ + return !!fgStructure.GameModeWindow; + } + + fgWarning( "Unknown gamemode get: %d", eWhat ); + return -1; +} + +/*** END OF FILE ***/ diff --git a/src/fg_geometry.c b/src/fg_geometry.c new file mode 100644 index 0000000..ee7cc89 --- /dev/null +++ b/src/fg_geometry.c @@ -0,0 +1,2335 @@ +/* + * fg_geometry.c + * + * Freeglut geometry rendering methods. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Fri Dec 3 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" +#include "fg_gl2.h" +#include + +/* + * A note: We do not use the GLuint data type for vertex index arrays + * in this code as Open GL ES1 only supports GLushort. This affects the + * cylindrical objects only (Torus, Sphere, Cylinder and Cone) and limits + * their number of vertices to 65535 (2^16-1). Thats about 256*256 + * subdivisions, which is sufficient for just about any usage case, so + * I am not going to worry about it for now. + * One could do compile time detection of the gluint type through CMake, + * but it is likely that we'll eventually move to runtime selection + * of OpenGL or GLES1/2, which would make that strategy useless... + */ + +/* declare for drawing using the different OpenGL versions here so we can + have a nice code order below */ +#ifndef GL_VERSION_1_1 +static void fghDrawGeometryWire10(GLfloat *varr, GLfloat *narr, GLushort *iarr, + GLsizei nparts, GLsizei npartverts, GLenum prim, GLushort *iarr2, + GLsizei nparts2, GLsizei npartverts2); +static void fghDrawGeometrySolid10(GLfloat *varr, GLfloat *narr, GLfloat *tarr, + GLsizei nverts, GLushort *iarr, GLsizei nparts, GLsizei npartverts); +static void fghDrawNormalVisualization10(void); +#endif +static void fghDrawGeometryWire11(GLfloat *vertices, GLfloat *normals, + GLushort *vertIdxs, GLsizei numParts, GLsizei numVertPerPart, GLenum vertexMode, + GLushort *vertIdxs2, GLsizei numParts2, GLsizei numVertPerPart2); +static void fghDrawGeometrySolid11(GLfloat *vertices, GLfloat *normals, GLfloat *textcs, GLsizei numVertices, + GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart); +static void fghDrawGeometryWire20(GLfloat *vertices, GLfloat *normals, GLsizei numVertices, + GLushort *vertIdxs, GLsizei numParts, GLsizei numVertPerPart, GLenum vertexMode, + GLushort *vertIdxs2, GLsizei numParts2, GLsizei numVertPerPart2, + GLint attribute_v_coord, GLint attribute_v_normal); +static void fghDrawGeometrySolid20(GLfloat *vertices, GLfloat *normals, GLfloat *textcs, GLsizei numVertices, + GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart, + GLint attribute_v_coord, GLint attribute_v_normal, GLint attribute_v_texture); +/* declare function for generating visualization of normals */ +static void fghGenerateNormalVisualization(GLfloat *vertices, GLfloat *normals, GLsizei numVertices); +static void fghDrawNormalVisualization11(void); +static void fghDrawNormalVisualization20(GLint attribute_v_coord); + +/* Drawing geometry: + * Explanation of the functions has to be separate for the polyhedra and + * the non-polyhedra (objects with a circular cross-section). + * Polyhedra: + * - We have only implemented the five platonic solids and the rhomboid + * dodecahedron. If you need more types of polyhedra, please see + * CPolyhedron in MRPT + * - Solids are drawn by glDrawArrays if composed of triangular faces + * (the tetrahedron, octahedron, and icosahedron), or are first + * decomposed into triangles and then drawn by glDrawElements if its + * faces are squares or pentagons (cube, dodecahedron and rhombic + * dodecahedron) as some vertices are repeated in that case. + * - WireFrame drawing is done using a GL_LINE_LOOP per face, and thus + * issuing one draw call per face. glDrawArrays is always used as no + * triangle decomposition is needed to draw faces. We use the "first" + * parameter in glDrawArrays to go from face to face. + * + * Non-polyhedra: + * - We have implemented the sphere, cylinder, cone and torus. + * - All shapes are characterized by two parameters: the number of + * subdivisions along two axes used to construct the shape's vertices + * (e.g. stacks and slices for the sphere). + * As different subdivisions are most suitable for different shapes, + * and are thus also named differently, I wont provide general comments + * on them here. + * - Solids are drawn using glDrawArrays and GL_TRIANGLE_STRIP. Each + * strip covers one revolution around one of the two subdivision axes + * of the shape. + * - WireFrame drawing is done for the subdivisions along the two axes + * separately, usually using GL_LINE_LOOP. Vertex index arrays are + * built containing the vertices to be drawn for each loop, which are + * then drawn using multiple calls to glDrawElements. As the number of + * subdivisions along the two axes is not guaranteed to be equal, the + * vertex indices for e.g. stacks and slices are stored in separate + * arrays, which makes the input to the drawing function a bit clunky, + * but allows for the same drawing function to be used for all shapes. + */ + + +/** + * Draw geometric shape in wire mode (only edges) + * + * Arguments: + * GLfloat *vertices, GLfloat *normals, GLsizei numVertices + * The vertex coordinate and normal buffers, and the number of entries in + * those + * GLushort *vertIdxs + * a vertex indices buffer, optional (never passed for the polyhedra) + * GLsizei numParts, GLsizei numVertPerPart + * polyhedra: number of faces, and the number of vertices for drawing + * each face + * non-polyhedra: number of edges to draw for first subdivision (not + * necessarily equal to number of subdivisions requested by user, e.g. + * as each subdivision is enclosed by two edges), and number of + * vertices for drawing each + * numParts * numVertPerPart gives the number of entries in the vertex + * array vertIdxs + * GLenum vertexMode + * vertex drawing mode (e.g. always GL_LINE_LOOP for polyhedra, varies + * for others) + * GLushort *vertIdxs2, GLsizei numParts2, GLsizei numVertPerPart2 + * non-polyhedra only: same as the above, but now for subdivisions along + * the other axis. Always drawn as GL_LINE_LOOP. + * + * Feel free to contribute better naming ;) + */ +void fghDrawGeometryWire(GLfloat *vertices, GLfloat *normals, GLsizei numVertices, + GLushort *vertIdxs, GLsizei numParts, GLsizei numVertPerPart, GLenum vertexMode, + GLushort *vertIdxs2, GLsizei numParts2, GLsizei numVertPerPart2 + ) +{ + SFG_Window *win = fgStructure.CurrentWindow; + + GLint attribute_v_coord = win ? win->Window.attribute_v_coord : -1; + GLint attribute_v_normal = win ? win->Window.attribute_v_normal : -1; + + if (fgState.HasOpenGL20 && (attribute_v_coord != -1 || attribute_v_normal != -1)) + /* User requested a 2.0 draw */ + fghDrawGeometryWire20(vertices, normals, numVertices, + vertIdxs, numParts, numVertPerPart, vertexMode, + vertIdxs2, numParts2, numVertPerPart2, + attribute_v_coord, attribute_v_normal); + else + fghDrawGeometryWire11(vertices, normals, + vertIdxs, numParts, numVertPerPart, vertexMode, + vertIdxs2, numParts2, numVertPerPart2); +} + +/* Draw the geometric shape with filled triangles + * + * Arguments: + * GLfloat *vertices, GLfloat *normals, GLfloat *textcs, GLsizei numVertices + * The vertex coordinate, normal and texture coordinate buffers, and the + * number of entries in those + * GLushort *vertIdxs + * a vertex indices buffer, optional (not passed for the polyhedra with + * triangular faces) + * GLsizei numParts, GLsizei numVertPerPart + * polyhedra: not used for polyhedra with triangular faces + (numEdgePerFace==3), as each vertex+normal pair is drawn only once, + so no vertex indices are used. + Else, the shape was triangulated (DECOMPOSE_TO_TRIANGLE), leading to + reuse of some vertex+normal pairs, and thus the need to draw with + glDrawElements. numParts is always 1 in this case (we can draw the + whole object with one call to glDrawElements as the vertex index + array contains separate triangles), and numVertPerPart indicates + the number of vertex indices in the vertex array. + * non-polyhedra: number of parts (GL_TRIANGLE_STRIPs) to be drawn + separately (numParts calls to glDrawElements) to create the object. + numVertPerPart indicates the number of vertex indices to be + processed at each draw call. + * numParts * numVertPerPart gives the number of entries in the vertex + * array vertIdxs + */ +void fghDrawGeometrySolid(GLfloat *vertices, GLfloat *normals, GLfloat *textcs, GLsizei numVertices, + GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart) +{ + GLint attribute_v_coord, attribute_v_normal, attribute_v_texture; + SFG_Window *win = fgStructure.CurrentWindow; + if(win) { + attribute_v_coord = win->Window.attribute_v_coord; + attribute_v_normal = win->Window.attribute_v_normal; + attribute_v_texture = win->Window.attribute_v_texture; + } else { + attribute_v_coord = attribute_v_normal = attribute_v_texture = -1; + } + + if (win && win->State.VisualizeNormals) + /* generate normals for each vertex to be drawn as well */ + fghGenerateNormalVisualization(vertices, normals, numVertices); + + if (fgState.HasOpenGL20 && (attribute_v_coord != -1 || attribute_v_normal != -1)) + { + /* User requested a 2.0 draw */ + fghDrawGeometrySolid20(vertices, normals, textcs, numVertices, + vertIdxs, numParts, numVertIdxsPerPart, + attribute_v_coord, attribute_v_normal, attribute_v_texture); + + if (win && win->State.VisualizeNormals) + /* draw normals for each vertex as well */ + fghDrawNormalVisualization20(attribute_v_coord); + } + else + { + fghDrawGeometrySolid11(vertices, normals, textcs, numVertices, + vertIdxs, numParts, numVertIdxsPerPart); + + if (win && win->State.VisualizeNormals) + /* draw normals for each vertex as well */ + fghDrawNormalVisualization11(); + } +} + +#ifndef GL_VERSION_1_1 +static void fghDrawGeometryWire10(GLfloat *varr, GLfloat *narr, GLushort *iarr, + GLsizei nparts, GLsizei npartverts, GLenum prim, GLushort *iarr2, + GLsizei nparts2, GLsizei npartverts2) +{ + int i, j; + GLfloat *vptr, *nptr; + GLushort *iptr; + + if(!iarr) { + vptr = varr; + nptr = narr; + for(i=0; i 1) { + for(i=0; i1) + for (i=0; i= 2.0 */ +static void fghDrawGeometryWire20(GLfloat *vertices, GLfloat *normals, GLsizei numVertices, + GLushort *vertIdxs, GLsizei numParts, GLsizei numVertPerPart, GLenum vertexMode, + GLushort *vertIdxs2, GLsizei numParts2, GLsizei numVertPerPart2, + GLint attribute_v_coord, GLint attribute_v_normal) +{ +#if defined(GL_VERSION_1_1) || defined(GL_VERSION_ES_CM_1_0) + GLuint vbo_coords = 0, vbo_normals = 0, + ibo_elements = 0, ibo_elements2 = 0; + GLsizei numVertIdxs = numParts * numVertPerPart; + GLsizei numVertIdxs2 = numParts2 * numVertPerPart2; + int i; + + if (numVertices > 0 && attribute_v_coord != -1) { + fghGenBuffers(1, &vbo_coords); + fghBindBuffer(FGH_ARRAY_BUFFER, vbo_coords); + fghBufferData(FGH_ARRAY_BUFFER, numVertices * 3 * sizeof(vertices[0]), + vertices, FGH_STATIC_DRAW); + } + + if (numVertices > 0 && attribute_v_normal != -1) { + fghGenBuffers(1, &vbo_normals); + fghBindBuffer(FGH_ARRAY_BUFFER, vbo_normals); + fghBufferData(FGH_ARRAY_BUFFER, numVertices * 3 * sizeof(normals[0]), + normals, FGH_STATIC_DRAW); + } + + if (vertIdxs != NULL) { + fghGenBuffers(1, &ibo_elements); + fghBindBuffer(FGH_ELEMENT_ARRAY_BUFFER, ibo_elements); + fghBufferData(FGH_ELEMENT_ARRAY_BUFFER, numVertIdxs * sizeof(vertIdxs[0]), + vertIdxs, FGH_STATIC_DRAW); + fghBindBuffer(FGH_ELEMENT_ARRAY_BUFFER, 0); + } + + if (vertIdxs2 != NULL) { + fghGenBuffers(1, &ibo_elements2); + fghBindBuffer(FGH_ELEMENT_ARRAY_BUFFER, ibo_elements2); + fghBufferData(FGH_ELEMENT_ARRAY_BUFFER, numVertIdxs2 * sizeof(vertIdxs2[0]), + vertIdxs2, FGH_STATIC_DRAW); + fghBindBuffer(FGH_ELEMENT_ARRAY_BUFFER, 0); + } + + if (vbo_coords) { + fghEnableVertexAttribArray(attribute_v_coord); + fghBindBuffer(FGH_ARRAY_BUFFER, vbo_coords); + fghVertexAttribPointer( + attribute_v_coord, /* attribute */ + 3, /* number of elements per vertex, here (x,y,z) */ + GL_FLOAT, /* the type of each element */ + GL_FALSE, /* take our values as-is */ + 0, /* no extra data between each position */ + 0 /* offset of first element */ + ); + fghBindBuffer(FGH_ARRAY_BUFFER, 0); + } + + if (vbo_normals) { + fghEnableVertexAttribArray(attribute_v_normal); + fghBindBuffer(FGH_ARRAY_BUFFER, vbo_normals); + fghVertexAttribPointer( + attribute_v_normal, /* attribute */ + 3, /* number of elements per vertex, here (x,y,z) */ + GL_FLOAT, /* the type of each element */ + GL_FALSE, /* take our values as-is */ + 0, /* no extra data between each position */ + 0 /* offset of first element */ + ); + fghBindBuffer(FGH_ARRAY_BUFFER, 0); + } + + if (!vertIdxs) { + /* Draw per face (TODO: could use glMultiDrawArrays if available) */ + for (i=0; i= 2.0 */ +static void fghDrawGeometrySolid20(GLfloat *vertices, GLfloat *normals, GLfloat *textcs, GLsizei numVertices, + GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart, + GLint attribute_v_coord, GLint attribute_v_normal, GLint attribute_v_texture) +{ +#if defined(GL_VERSION_1_1) || defined(GL_VERSION_ES_CM_1_0) + GLuint vbo_coords = 0, vbo_normals = 0, vbo_textcs = 0, ibo_elements = 0; + GLsizei numVertIdxs = numParts * numVertIdxsPerPart; + int i; + + if (numVertices > 0 && attribute_v_coord != -1) { + fghGenBuffers(1, &vbo_coords); + fghBindBuffer(FGH_ARRAY_BUFFER, vbo_coords); + fghBufferData(FGH_ARRAY_BUFFER, numVertices * 3 * sizeof(vertices[0]), + vertices, FGH_STATIC_DRAW); + fghBindBuffer(FGH_ARRAY_BUFFER, 0); + } + + if (numVertices > 0 && attribute_v_normal != -1) { + fghGenBuffers(1, &vbo_normals); + fghBindBuffer(FGH_ARRAY_BUFFER, vbo_normals); + fghBufferData(FGH_ARRAY_BUFFER, numVertices * 3 * sizeof(normals[0]), + normals, FGH_STATIC_DRAW); + fghBindBuffer(FGH_ARRAY_BUFFER, 0); + } + + if (numVertices > 0 && attribute_v_texture != -1 && textcs) { + fghGenBuffers(1, &vbo_textcs); + fghBindBuffer(FGH_ARRAY_BUFFER, vbo_textcs); + fghBufferData(FGH_ARRAY_BUFFER, numVertices * 2 * sizeof(textcs[0]), + textcs, FGH_STATIC_DRAW); + fghBindBuffer(FGH_ARRAY_BUFFER, 0); + } + + if (vertIdxs != NULL) { + fghGenBuffers(1, &ibo_elements); + fghBindBuffer(FGH_ELEMENT_ARRAY_BUFFER, ibo_elements); + fghBufferData(FGH_ELEMENT_ARRAY_BUFFER, numVertIdxs * sizeof(vertIdxs[0]), + vertIdxs, FGH_STATIC_DRAW); + fghBindBuffer(FGH_ELEMENT_ARRAY_BUFFER, 0); + } + + if (vbo_coords) { + fghEnableVertexAttribArray(attribute_v_coord); + fghBindBuffer(FGH_ARRAY_BUFFER, vbo_coords); + fghVertexAttribPointer( + attribute_v_coord, /* attribute */ + 3, /* number of elements per vertex, here (x,y,z) */ + GL_FLOAT, /* the type of each element */ + GL_FALSE, /* take our values as-is */ + 0, /* no extra data between each position */ + 0 /* offset of first element */ + ); + fghBindBuffer(FGH_ARRAY_BUFFER, 0); + }; + + if (vbo_normals) { + fghEnableVertexAttribArray(attribute_v_normal); + fghBindBuffer(FGH_ARRAY_BUFFER, vbo_normals); + fghVertexAttribPointer( + attribute_v_normal, /* attribute */ + 3, /* number of elements per vertex, here (x,y,z) */ + GL_FLOAT, /* the type of each element */ + GL_FALSE, /* take our values as-is */ + 0, /* no extra data between each position */ + 0 /* offset of first element */ + ); + fghBindBuffer(FGH_ARRAY_BUFFER, 0); + }; + + if (vbo_textcs) { + fghEnableVertexAttribArray(attribute_v_texture); + fghBindBuffer(FGH_ARRAY_BUFFER, vbo_textcs); + fghVertexAttribPointer( + attribute_v_texture,/* attribute */ + 2, /* number of elements per vertex, here (s,t) */ + GL_FLOAT, /* the type of each element */ + GL_FALSE, /* take our values as-is */ + 0, /* no extra data between each position */ + 0 /* offset of first element */ + ); + fghBindBuffer(FGH_ARRAY_BUFFER, 0); + }; + + if (vertIdxs == NULL) { + glDrawArrays(GL_TRIANGLES, 0, numVertices); + } else { + fghBindBuffer(FGH_ELEMENT_ARRAY_BUFFER, ibo_elements); + if (numParts>1) { + for (i=0; i= 2.0 */ +static void fghDrawNormalVisualization20(GLint attribute_v_coord) +{ +#if defined(GL_VERSION_1_1) || defined(GL_VERSION_ES_CM_1_0) + GLuint vbo_coords = 0; + + if (attribute_v_coord != -1) { + fghGenBuffers(1, &vbo_coords); + fghBindBuffer(FGH_ARRAY_BUFFER, vbo_coords); + fghBufferData(FGH_ARRAY_BUFFER, numNormalVertices * 3 * sizeof(verticesForNormalVisualization[0]), + verticesForNormalVisualization, FGH_STATIC_DRAW); + } + + + if (vbo_coords) { + fghEnableVertexAttribArray(attribute_v_coord); + fghBindBuffer(FGH_ARRAY_BUFFER, vbo_coords); + fghVertexAttribPointer( + attribute_v_coord, /* attribute */ + 3, /* number of elements per vertex, here (x,y,z) */ + GL_FLOAT, /* the type of each element */ + GL_FALSE, /* take our values as-is */ + 0, /* no extra data between each position */ + 0 /* offset of first element */ + ); + fghBindBuffer(FGH_ARRAY_BUFFER, 0); + } + + glDrawArrays(GL_LINES, 0, numNormalVertices); + + if (vbo_coords != 0) + fghDisableVertexAttribArray(attribute_v_coord); + + if (vbo_coords != 0) + fghDeleteBuffers(1, &vbo_coords); + + /* Done, free memory */ + free(verticesForNormalVisualization); +#endif /* GL version at least 1.1 */ +} + +/** + * Generate all combinations of vertices and normals needed to draw object. + * Optional shape decomposition to triangles: + * We'll use glDrawElements to draw all shapes that are not naturally + * composed of triangles, so generate an index vector here, using the + * below sampling scheme. + * Be careful to keep winding of all triangles counter-clockwise, + * assuming that input has correct winding... + */ +static GLubyte vert4Decomp[6] = {0,1,2, 0,2,3}; /* quad : 4 input vertices, 6 output (2 triangles) */ +static GLubyte vert5Decomp[9] = {0,1,2, 0,2,4, 4,2,3}; /* pentagon: 5 input vertices, 9 output (3 triangles) */ + +static void fghGenerateGeometryWithIndexArray(int numFaces, int numEdgePerFace, GLfloat *vertices, GLubyte *vertIndices, GLfloat *normals, GLfloat *vertOut, GLfloat *normOut, GLushort *vertIdxOut) +{ + int i,j,numEdgeIdxPerFace; + GLubyte *vertSamps = NULL; + switch (numEdgePerFace) + { + case 3: + /* nothing to do here, we'll draw with glDrawArrays */ + break; + case 4: + vertSamps = vert4Decomp; + numEdgeIdxPerFace = 6; /* 6 output vertices for each face */ + break; + case 5: + vertSamps = vert5Decomp; + numEdgeIdxPerFace = 9; /* 9 output vertices for each face */ + break; + } + /* + * Build array with vertices using vertex coordinates and vertex indices + * Do same for normals. + * Need to do this because of different normals at shared vertices. + */ + for (i=0; i 0 ) + { + double local_offset[3] ; /* Use a local variable to avoid buildup of roundoff errors */ + unsigned int stride = ipow(4,--numLevels)*TETRAHEDRON_VERT_ELEM_PER_OBJ; + scale /= 2.0 ; + for ( i = 0 ; i < TETRAHEDRON_NUM_FACES ; i++ ) + { + int idx = i*3; + local_offset[0] = offset[0] + scale * tetrahedron_v[idx ]; + local_offset[1] = offset[1] + scale * tetrahedron_v[idx+1]; + local_offset[2] = offset[2] + scale * tetrahedron_v[idx+2]; + fghSierpinskiSpongeGenerate ( numLevels, local_offset, scale, vertices+i*stride, normals+i*stride ); + } + } +} + +/* -- Now the various non-polyhedra (shapes involving circles) -- */ +/* + * Compute lookup table of cos and sin values forming a circle + * (or half circle if halfCircle==TRUE) + * + * Notes: + * It is the responsibility of the caller to free these tables + * The size of the table is (n+1) to form a connected loop + * The last entry is exactly the same as the first + * The sign of n can be flipped to get the reverse loop + */ +static void fghCircleTable(GLfloat **sint, GLfloat **cost, const int n, const GLboolean halfCircle) +{ + int i; + + /* Table size, the sign of n flips the circle direction */ + const int size = abs(n); + + /* Determine the angle between samples */ + const GLfloat angle = (halfCircle?1:2)*(GLfloat)M_PI/(GLfloat)( ( n == 0 ) ? 1 : n ); + + /* Allocate memory for n samples, plus duplicate of first entry at the end */ + *sint = malloc(sizeof(GLfloat) * (size+1)); + *cost = malloc(sizeof(GLfloat) * (size+1)); + + /* Bail out if memory allocation fails, fgError never returns */ + if (!(*sint) || !(*cost)) + { + free(*sint); + free(*cost); + fgError("Failed to allocate memory in fghCircleTable"); + } + + /* Compute cos and sin around the circle */ + (*sint)[0] = 0.0; + (*cost)[0] = 1.0; + + for (i=1; i 65535) + /* + * limit of glushort, thats 256*256 subdivisions, should be enough in practice. See note above + */ + fgWarning("fghGenerateSphere: too many slices or stacks requested, indices will wrap"); + + /* precompute values on unit circle */ + fghCircleTable(&sint1,&cost1,-slices,GL_FALSE); + fghCircleTable(&sint2,&cost2, stacks,GL_TRUE); + + /* Allocate vertex and normal buffers, bail out if memory allocation fails */ + *vertices = malloc((*nVert)*3*sizeof(GLfloat)); + *normals = malloc((*nVert)*3*sizeof(GLfloat)); + if (!(*vertices) || !(*normals)) + { + free(*vertices); + free(*normals); + fgError("Failed to allocate memory in fghGenerateSphere"); + } + + /* top */ + (*vertices)[0] = 0.f; + (*vertices)[1] = 0.f; + (*vertices)[2] = radius; + (*normals )[0] = 0.f; + (*normals )[1] = 0.f; + (*normals )[2] = 1.f; + idx = 3; + + /* each stack */ + for( i=1; i 0 ) ? stacks : 1 ); + const GLfloat rStep = (GLfloat)base / ( ( stacks > 0 ) ? stacks : 1 ); + + /* Scaling factors for vertex normals */ + const GLfloat cosn = (GLfloat) (height / sqrt( height * height + base * base )); + const GLfloat sinn = (GLfloat) (base / sqrt( height * height + base * base )); + + + + /* number of unique vertices */ + if (slices==0 || stacks<1) + { + /* nothing to generate */ + *nVert = 0; + return; + } + *nVert = slices*(stacks+2)+1; /* need an extra stack for closing off bottom with correct normals */ + + if ((*nVert) > 65535) + /* + * limit of glushort, thats 256*256 subdivisions, should be enough in practice. See note above + */ + fgWarning("fghGenerateCone: too many slices or stacks requested, indices will wrap"); + + /* Pre-computed circle */ + fghCircleTable(&sint,&cost,-slices,GL_FALSE); + + /* Allocate vertex and normal buffers, bail out if memory allocation fails */ + *vertices = malloc((*nVert)*3*sizeof(GLfloat)); + *normals = malloc((*nVert)*3*sizeof(GLfloat)); + if (!(*vertices) || !(*normals)) + { + free(*vertices); + free(*normals); + fgError("Failed to allocate memory in fghGenerateCone"); + } + + /* bottom */ + (*vertices)[0] = 0.f; + (*vertices)[1] = 0.f; + (*vertices)[2] = z; + (*normals )[0] = 0.f; + (*normals )[1] = 0.f; + (*normals )[2] = -1.f; + idx = 3; + /* other on bottom (get normals right) */ + for (j=0; j 0 ) ? stacks : 1 ); + + /* Pre-computed circle */ + GLfloat *sint,*cost; + + /* number of unique vertices */ + if (slices==0 || stacks<1) + { + /* nothing to generate */ + *nVert = 0; + return; + } + *nVert = slices*(stacks+3)+2; /* need two extra stacks for closing off top and bottom with correct normals */ + + if ((*nVert) > 65535) + /* + * limit of glushort, thats 256*256 subdivisions, should be enough in practice. See note above + */ + fgWarning("fghGenerateCylinder: too many slices or stacks requested, indices will wrap"); + + /* Pre-computed circle */ + fghCircleTable(&sint,&cost,-slices,GL_FALSE); + + /* Allocate vertex and normal buffers, bail out if memory allocation fails */ + *vertices = malloc((*nVert)*3*sizeof(GLfloat)); + *normals = malloc((*nVert)*3*sizeof(GLfloat)); + if (!(*vertices) || !(*normals)) + { + free(*vertices); + free(*normals); + fgError("Failed to allocate memory in fghGenerateCylinder"); + } + + z=0; + /* top on Z-axis */ + (*vertices)[0] = 0.f; + (*vertices)[1] = 0.f; + (*vertices)[2] = 0.f; + (*normals )[0] = 0.f; + (*normals )[1] = 0.f; + (*normals )[2] = -1.f; + idx = 3; + /* other on top (get normals right) */ + for (j=0; j 65535) + /* + * limit of glushort, thats 256*256 subdivisions, should be enough in practice. See note above + */ + fgWarning("fghGenerateTorus: too many slices or stacks requested, indices will wrap"); + + /* precompute values on unit circle */ + fghCircleTable(&spsi,&cpsi, nRings,GL_FALSE); + fghCircleTable(&sphi,&cphi,-nSides,GL_FALSE); + + /* Allocate vertex and normal buffers, bail out if memory allocation fails */ + *vertices = malloc((*nVert)*3*sizeof(GLfloat)); + *normals = malloc((*nVert)*3*sizeof(GLfloat)); + if (!(*vertices) || !(*normals)) + { + free(*vertices); + free(*normals); + fgError("Failed to allocate memory in fghGenerateTorus"); + } + + for( j=0; j +#include "fg_internal.h" +#include "fg_gl2.h" + +#ifndef GL_ES_VERSION_2_0 +/* GLES2 has the corresponding entry points built-in, and these fgh-prefixed + * names are defined in fg_gl2.h header to reference them, for any other case, + * define them as function pointers here. + */ +FGH_PFNGLGENBUFFERSPROC fghGenBuffers; +FGH_PFNGLDELETEBUFFERSPROC fghDeleteBuffers; +FGH_PFNGLBINDBUFFERPROC fghBindBuffer; +FGH_PFNGLBUFFERDATAPROC fghBufferData; +FGH_PFNGLENABLEVERTEXATTRIBARRAYPROC fghEnableVertexAttribArray; +FGH_PFNGLDISABLEVERTEXATTRIBARRAYPROC fghDisableVertexAttribArray; +FGH_PFNGLVERTEXATTRIBPOINTERPROC fghVertexAttribPointer; +#endif + +void FGAPIENTRY glutSetVertexAttribCoord3(GLint attrib) { + if (fgStructure.CurrentWindow != NULL) + fgStructure.CurrentWindow->Window.attribute_v_coord = attrib; +} + +void FGAPIENTRY glutSetVertexAttribNormal(GLint attrib) { + if (fgStructure.CurrentWindow != NULL) + fgStructure.CurrentWindow->Window.attribute_v_normal = attrib; +} + +void FGAPIENTRY glutSetVertexAttribTexCoord2(GLint attrib) { + if (fgStructure.CurrentWindow != NULL) + fgStructure.CurrentWindow->Window.attribute_v_texture = attrib; +} + +#define LOADFUNC(ptr, type, name) \ + do { if(!(ptr = (type)glutGetProcAddress(name))) return; } while(0) + +void fgInitGL2() { +#ifdef GL_ES_VERSION_2_0 + fgState.HasOpenGL20 = (fgState.MajorVersion >= 2); +#else + /* TODO: Mesa returns a valid stub function, rather than NULL, + when we request a non-existent function */ + LOADFUNC(fghGenBuffers, FGH_PFNGLGENBUFFERSPROC, "glGenBuffers"); + LOADFUNC(fghDeleteBuffers, FGH_PFNGLDELETEBUFFERSPROC, "glDeleteBuffers"); + LOADFUNC(fghBindBuffer, FGH_PFNGLBINDBUFFERPROC, "glBindBuffer"); + LOADFUNC(fghBufferData, FGH_PFNGLBUFFERDATAPROC, "glBufferData"); + LOADFUNC(fghVertexAttribPointer, FGH_PFNGLVERTEXATTRIBPOINTERPROC, "glVertexAttribPointer"); + LOADFUNC(fghEnableVertexAttribArray, FGH_PFNGLENABLEVERTEXATTRIBARRAYPROC, "glEnableVertexAttribArray"); + LOADFUNC(fghDisableVertexAttribArray, FGH_PFNGLDISABLEVERTEXATTRIBARRAYPROC, "glDisableVertexAttribArray"); + fgState.HasOpenGL20 = 1; +#endif +} diff --git a/src/fg_gl2.h b/src/fg_gl2.h new file mode 100644 index 0000000..53cbc33 --- /dev/null +++ b/src/fg_gl2.h @@ -0,0 +1,82 @@ +/* + * fg_gl2.h + * + * Load OpenGL (ES) 2.0 functions used by fg_geometry + * + * Copyright (C) 2012 Sylvain Beucler + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef FG_GL2_H +#define FG_GL2_H + +#include +#include "fg_internal.h" + +#ifdef GL_ES_VERSION_2_0 +/* Use existing functions on GLES 2.0 */ + +#define FGH_ARRAY_BUFFER GL_ARRAY_BUFFER +#define FGH_STATIC_DRAW GL_STATIC_DRAW +#define FGH_ELEMENT_ARRAY_BUFFER GL_ELEMENT_ARRAY_BUFFER + +#define fghGenBuffers glGenBuffers +#define fghDeleteBuffers glDeleteBuffers +#define fghBindBuffer glBindBuffer +#define fghBufferData glBufferData +#define fghEnableVertexAttribArray glEnableVertexAttribArray +#define fghDisableVertexAttribArray glDisableVertexAttribArray +#define fghVertexAttribPointer glVertexAttribPointer + +#else +/* Load functions dynamically, they are not defined in e.g. win32's + OpenGL headers */ + +# ifndef APIENTRY +# define APIENTRY +# endif + +/* extension #defines, types and entries, avoiding a dependency on additional + libraries like GLEW or the GL/glext.h header */ +#define FGH_ARRAY_BUFFER 0x8892 +#define FGH_STATIC_DRAW 0x88E4 +#define FGH_ELEMENT_ARRAY_BUFFER 0x8893 + +typedef int fghGLsizeiptr; +typedef void (APIENTRY *FGH_PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers); +typedef void (APIENTRY *FGH_PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); +typedef void (APIENTRY *FGH_PFNGLBUFFERDATAPROC) (GLenum target, fghGLsizeiptr size, const GLvoid *data, GLenum usage); +typedef void (APIENTRY *FGH_PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint* buffers); +typedef void (APIENTRY *FGH_PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index); +typedef void (APIENTRY *FGH_PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint); +typedef void (APIENTRY *FGH_PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); + +extern FGH_PFNGLGENBUFFERSPROC fghGenBuffers; +extern FGH_PFNGLDELETEBUFFERSPROC fghDeleteBuffers; +extern FGH_PFNGLBINDBUFFERPROC fghBindBuffer; +extern FGH_PFNGLBUFFERDATAPROC fghBufferData; +extern FGH_PFNGLENABLEVERTEXATTRIBARRAYPROC fghEnableVertexAttribArray; +extern FGH_PFNGLDISABLEVERTEXATTRIBARRAYPROC fghDisableVertexAttribArray; +extern FGH_PFNGLVERTEXATTRIBPOINTERPROC fghVertexAttribPointer; + +# endif + +extern void fgInitGL2(); + +#endif diff --git a/src/fg_init.c b/src/fg_init.c new file mode 100644 index 0000000..b8a38f7 --- /dev/null +++ b/src/fg_init.c @@ -0,0 +1,732 @@ +/* + * fg_init.c + * + * Various freeglut initialization functions. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Thu Dec 2 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#define FREEGLUT_BUILDING_LIB +#include +#include "fg_internal.h" + +/* + * TODO BEFORE THE STABLE RELEASE: + * + * fgDeinitialize() -- Win32's OK, X11 needs the OS-specific + * deinitialization done + * glutInitDisplayString() -- display mode string parsing + * + * Wouldn't it be cool to use gettext() for error messages? I just love + * bash saying "nie znaleziono pliku" instead of "file not found" :) + * Is gettext easily portable? + */ + +/* -- GLOBAL VARIABLES ----------------------------------------------------- */ + +/* + * A structure pointed by fgDisplay holds all information + * regarding the display, screen, root window etc. + */ +SFG_Display fgDisplay; + +/* + * The settings for the current freeglut session + */ +SFG_State fgState = { { -1, -1, GL_FALSE }, /* Position */ + { 300, 300, GL_TRUE }, /* Size */ + GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH, /* DisplayMode */ + GL_FALSE, /* Initialised */ + GLUT_TRY_DIRECT_CONTEXT, /* DirectContext */ + GL_FALSE, /* ForceIconic */ + GL_FALSE, /* UseCurrentContext */ + GL_FALSE, /* GLDebugSwitch */ + GL_FALSE, /* XSyncSwitch */ + GLUT_KEY_REPEAT_ON, /* KeyRepeat */ + INVALID_MODIFIERS, /* Modifiers */ + 0, /* FPSInterval */ + 0, /* SwapCount */ + 0, /* SwapTime */ + 0, /* Time */ + { NULL, NULL }, /* Timers */ + { NULL, NULL }, /* FreeTimers */ + NULL, /* IdleCallback */ + NULL, /* IdleCallbackData */ + 0, /* ActiveMenus */ + NULL, /* MenuStateCallback */ + NULL, /* MenuStatusCallback */ + NULL, /* MenuStatusCallbackData */ + FREEGLUT_MENU_FONT, + { -1, -1, GL_TRUE }, /* GameModeSize */ + -1, /* GameModeDepth */ + -1, /* GameModeRefresh */ + GLUT_ACTION_EXIT, /* ActionOnWindowClose */ + GLUT_EXEC_STATE_INIT, /* ExecState */ + NULL, /* ProgramName */ + GL_FALSE, /* JoysticksInitialised */ + 0, /* NumActiveJoysticks */ + GL_FALSE, /* InputDevsInitialised */ + 0, /* MouseWheelTicks */ + 1, /* AuxiliaryBufferNumber */ + 4, /* SampleNumber */ + GL_FALSE, /* SkipStaleMotion */ + GL_FALSE, /* StrokeFontDrawJoinDots */ + GL_FALSE, /* AllowNegativeWindowPosition */ + 1, /* OpenGL context MajorVersion */ + 0, /* OpenGL context MinorVersion */ + 0, /* OpenGL ContextFlags */ + 0, /* OpenGL ContextProfile */ + 0, /* HasOpenGL20 */ + NULL, /* ErrorFunc */ + NULL, /* ErrorFuncData */ + NULL, /* WarningFunc */ + NULL /* WarningFuncData */ +}; + + +/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ + +extern void fgPlatformInitialize( const char* displayName ); +extern void fgPlatformDeinitialiseInputDevices ( void ); +extern void fgPlatformCloseDisplay ( void ); +extern void fgPlatformDestroyContext ( SFG_PlatformDisplay pDisplay, SFG_WindowContextType MContext ); + +void fghParseCommandLineArguments ( int* pargc, char** argv, char **pDisplayName, char **pGeometry ) +{ +#ifndef _WIN32_WCE + int i, j, argc = *pargc; + + { + /* check if GLUT_FPS env var is set */ + const char *fps = getenv( "GLUT_FPS" ); + + if( fps ) + { + int interval; + sscanf( fps, "%d", &interval ); + + if( interval <= 0 ) + fgState.FPSInterval = 5000; /* 5000 millisecond default */ + else + fgState.FPSInterval = interval; + } + } + + *pDisplayName = getenv( "DISPLAY" ); + + for( i = 1; i < argc; i++ ) + { + if( strcmp( argv[ i ], "-display" ) == 0 ) + { + if( ++i >= argc ) + fgError( "-display parameter must be followed by display name" ); + + *pDisplayName = argv[ i ]; + + argv[ i - 1 ] = NULL; + argv[ i ] = NULL; + ( *pargc ) -= 2; + } + else if( strcmp( argv[ i ], "-geometry" ) == 0 ) + { + if( ++i >= argc ) + fgError( "-geometry parameter must be followed by window " + "geometry settings" ); + + *pGeometry = argv[ i ]; + + argv[ i - 1 ] = NULL; + argv[ i ] = NULL; + ( *pargc ) -= 2; + } + else if( strcmp( argv[ i ], "-direct" ) == 0) + { + if( fgState.DirectContext == GLUT_FORCE_INDIRECT_CONTEXT ) + fgError( "parameters ambiguity, -direct and -indirect " + "cannot be both specified" ); + + fgState.DirectContext = GLUT_FORCE_DIRECT_CONTEXT; + argv[ i ] = NULL; + ( *pargc )--; + } + else if( strcmp( argv[ i ], "-indirect" ) == 0 ) + { + if( fgState.DirectContext == GLUT_FORCE_DIRECT_CONTEXT ) + fgError( "parameters ambiguity, -direct and -indirect " + "cannot be both specified" ); + + fgState.DirectContext = GLUT_FORCE_INDIRECT_CONTEXT; + argv[ i ] = NULL; + (*pargc)--; + } + else if( strcmp( argv[ i ], "-iconic" ) == 0 ) + { + fgState.ForceIconic = GL_TRUE; + argv[ i ] = NULL; + ( *pargc )--; + } + else if( strcmp( argv[ i ], "-gldebug" ) == 0 ) + { + fgState.GLDebugSwitch = GL_TRUE; + argv[ i ] = NULL; + ( *pargc )--; + } + else if( strcmp( argv[ i ], "-sync" ) == 0 ) + { + fgState.XSyncSwitch = GL_TRUE; + argv[ i ] = NULL; + ( *pargc )--; + } + } + + /* Compact {argv}. */ + for( i = j = 1; i < *pargc; i++, j++ ) + { + /* Guaranteed to end because there are "*pargc" arguments left */ + while ( argv[ j ] == NULL ) + j++; + if ( i != j ) + argv[ i ] = argv[ j ]; + } + +#endif /* _WIN32_WCE */ + +} + + +void fghCloseInputDevices ( void ) +{ + if ( fgState.JoysticksInitialised ) + fgJoystickClose( ); + + if ( fgState.InputDevsInitialised ) + fgInputDeviceClose( ); +} + + +/* + * Perform the freeglut deinitialization... + */ +void fgDeinitialize( void ) +{ + SFG_Timer *timer; + + if( !fgState.Initialised ) + { + return; + } + + /* If we're in game mode, we want to leave game mode */ + if( fgStructure.GameModeWindow ) { + glutLeaveGameMode(); + } + + /* If there was a menu created, destroy the rendering context */ + if( fgStructure.MenuContext ) + { + fgPlatformDestroyContext (fgDisplay.pDisplay, fgStructure.MenuContext->MContext ); + free( fgStructure.MenuContext ); + fgStructure.MenuContext = NULL; + } + + fgDestroyStructure( ); + + while( ( timer = fgState.Timers.First) ) + { + fgListRemove( &fgState.Timers, &timer->Node ); + free( timer ); + } + + while( ( timer = fgState.FreeTimers.First) ) + { + fgListRemove( &fgState.FreeTimers, &timer->Node ); + free( timer ); + } + + fgPlatformDeinitialiseInputDevices (); + + fgState.MouseWheelTicks = 0; + + fgState.MajorVersion = 1; + fgState.MinorVersion = 0; + fgState.ContextFlags = 0; + fgState.ContextProfile = 0; + + fgState.Initialised = GL_FALSE; + + fgState.Position.X = -1; + fgState.Position.Y = -1; + fgState.Position.Use = GL_FALSE; + + fgState.Size.X = 300; + fgState.Size.Y = 300; + fgState.Size.Use = GL_TRUE; + + fgState.DisplayMode = GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH; + + fgState.DirectContext = GLUT_TRY_DIRECT_CONTEXT; + fgState.ForceIconic = GL_FALSE; + fgState.UseCurrentContext = GL_FALSE; + fgState.GLDebugSwitch = GL_FALSE; + fgState.XSyncSwitch = GL_FALSE; + fgState.ActionOnWindowClose = GLUT_ACTION_EXIT; + fgState.ExecState = GLUT_EXEC_STATE_INIT; + + fgState.KeyRepeat = GLUT_KEY_REPEAT_ON; + fgState.Modifiers = INVALID_MODIFIERS; + + fgState.GameModeSize.X = -1; + fgState.GameModeSize.Y = -1; + fgState.GameModeDepth = -1; + fgState.GameModeRefresh = -1; + + fgListInit( &fgState.Timers ); + fgListInit( &fgState.FreeTimers ); + + fgState.IdleCallback = ( FGCBIdleUC )NULL; + fgState.IdleCallbackData = NULL; + fgState.MenuStateCallback = ( FGCBMenuState )NULL; + fgState.MenuStatusCallback = ( FGCBMenuStatusUC )NULL; + fgState.MenuStatusCallbackData = NULL; + + fgState.SwapCount = 0; + fgState.SwapTime = 0; + fgState.FPSInterval = 0; + + if( fgState.ProgramName ) + { + free( fgState.ProgramName ); + fgState.ProgramName = NULL; + } + + fgPlatformCloseDisplay (); + + fgState.Initialised = GL_FALSE; +} + + +/* -- INTERFACE FUNCTIONS -------------------------------------------------- */ +#if defined(NEED_XPARSEGEOMETRY_IMPL) || defined(TARGET_HOST_MS_WINDOWS) +# include "util/xparsegeometry_repl.h" +#endif + +/* + * Perform initialization. This usually happens on the program startup + * and restarting after glutMainLoop termination... + */ +void FGAPIENTRY glutInit( int* pargc, char** argv ) +{ + char* displayName = NULL; + char* geometry = NULL; + if( fgState.Initialised ) + fgError( "illegal glutInit() reinitialization attempt" ); + + if (pargc && *pargc && argv && *argv && **argv) + { + fgState.ProgramName = strdup (*argv); + + if( !fgState.ProgramName ) + fgError ("Could not allocate space for the program's name."); + } + + fgCreateStructure( ); + + fghParseCommandLineArguments ( pargc, argv, &displayName, &geometry ); + + /* + * Have the display created now. If there wasn't a "-display" + * in the program arguments, we will use the DISPLAY environment + * variable for opening the X display (see code above): + */ + fgPlatformInitialize( displayName ); + + /* + * Geometry parsing deferred until here because we may need the screen + * size. + */ + + if ( geometry ) + { + unsigned int parsedWidth, parsedHeight; + int mask = XParseGeometry( geometry, + &fgState.Position.X, &fgState.Position.Y, + &parsedWidth, &parsedHeight ); + /* TODO: Check for overflow? */ + fgState.Size.X = parsedWidth; + fgState.Size.Y = parsedHeight; + + if( (mask & (WidthValue|HeightValue)) == (WidthValue|HeightValue) ) + fgState.Size.Use = GL_TRUE; + + if( ( mask & XNegative ) && !fgState.AllowNegativeWindowPosition ) + fgState.Position.X += fgDisplay.ScreenWidth - fgState.Size.X; + + if( ( mask & YNegative ) && !fgState.AllowNegativeWindowPosition ) + fgState.Position.Y += fgDisplay.ScreenHeight - fgState.Size.Y; + + if( (mask & (XValue|YValue)) == (XValue|YValue) ) + fgState.Position.Use = GL_TRUE; + } +} + +/* + * Undoes all the "glutInit" stuff + */ +void FGAPIENTRY glutExit ( void ) +{ + fgDeinitialize (); +} + +/* + * Sets the default initial window position for new windows + */ +void FGAPIENTRY glutInitWindowPosition( int x, int y ) +{ + fgState.Position.X = x; + fgState.Position.Y = y; + + if( ( ( x >= 0 ) && ( y >= 0 ) ) || fgState.AllowNegativeWindowPosition ) + fgState.Position.Use = GL_TRUE; + else + fgState.Position.Use = GL_FALSE; +} + +/* + * Sets the default initial window size for new windows + */ +void FGAPIENTRY glutInitWindowSize( int width, int height ) +{ + fgState.Size.X = width; + fgState.Size.Y = height; + + if( ( width > 0 ) && ( height > 0 ) ) + fgState.Size.Use = GL_TRUE; + else + fgState.Size.Use = GL_FALSE; +} + +/* + * Sets the default display mode for all new windows + */ +void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode ) +{ + /* We will make use of this value when creating a new OpenGL context... */ + fgState.DisplayMode = displayMode; +} + + +/* -- INIT DISPLAY STRING PARSING ------------------------------------------ */ + +static char* Tokens[] = +{ + "alpha", "acca", "acc", "blue", "buffer", "conformant", "depth", "double", + "green", "index", "num", "red", "rgba", "rgb", "luminance", "stencil", + "single", "stereo", "samples", "slow", "win32pdf", "win32pfd", "xvisual", + "xstaticgray", "xgrayscale", "xstaticcolor", "xpseudocolor", + "xtruecolor", "xdirectcolor", + "xstaticgrey", "xgreyscale", "xstaticcolour", "xpseudocolour", + "xtruecolour", "xdirectcolour", "borderless", "aux" +}; +#define NUM_TOKENS (sizeof(Tokens) / sizeof(*Tokens)) + +void FGAPIENTRY glutInitDisplayString( const char* displayMode ) +{ + int glut_state_flag = 0 ; + /* + * Unpack a lot of options from a character string. The options are + * delimited by blanks or tabs. + */ + char *token ; + size_t len = strlen ( displayMode ); + char *buffer = (char *)malloc ( (len+1) * sizeof(char) ); + memcpy ( buffer, displayMode, len ); + buffer[len] = '\0'; + + token = strtok ( buffer, " \t" ); + + while ( token ) + { + /* Process this token */ + int i ; + + /* Temporary fix: Ignore any length specifications and at least + * process the basic token + * TODO: Fix this permanently + */ + size_t cleanlength = strcspn ( token, "=<>~!" ); + + for ( i = 0; i < NUM_TOKENS; i++ ) + { + if ( strncmp ( token, Tokens[i], cleanlength ) == 0 ) break ; + } + + switch ( i ) + { + case 0 : /* "alpha": Alpha color buffer precision in bits */ + glut_state_flag |= GLUT_ALPHA ; /* Somebody fix this for me! */ + break ; + + case 1 : /* "acca": Red, green, blue, and alpha accumulation buffer + precision in bits */ + break ; + + case 2 : /* "acc": Red, green, and blue accumulation buffer precision + in bits with zero bits alpha */ + glut_state_flag |= GLUT_ACCUM ; /* Somebody fix this for me! */ + break ; + + case 3 : /* "blue": Blue color buffer precision in bits */ + break ; + + case 4 : /* "buffer": Number of bits in the color index color buffer + */ + break ; + + case 5 : /* "conformant": Boolean indicating if the frame buffer + configuration is conformant or not */ + break ; + + case 6 : /* "depth": Number of bits of precision in the depth buffer */ + glut_state_flag |= GLUT_DEPTH ; /* Somebody fix this for me! */ + break ; + + case 7 : /* "double": Boolean indicating if the color buffer is + double buffered */ + glut_state_flag |= GLUT_DOUBLE ; + break ; + + case 8 : /* "green": Green color buffer precision in bits */ + break ; + + case 9 : /* "index": Boolean if the color model is color index or not + */ + glut_state_flag |= GLUT_INDEX ; + break ; + + case 10 : /* "num": A special capability name indicating where the + value represents the Nth frame buffer configuration + matching the description string */ + break ; + + case 11 : /* "red": Red color buffer precision in bits */ + break ; + + case 12 : /* "rgba": Number of bits of red, green, blue, and alpha in + the RGBA color buffer */ + glut_state_flag |= GLUT_RGBA ; /* Somebody fix this for me! */ + break ; + + case 13 : /* "rgb": Number of bits of red, green, and blue in the + RGBA color buffer with zero bits alpha */ + glut_state_flag |= GLUT_RGB ; /* Somebody fix this for me! */ + break ; + + case 14 : /* "luminance": Number of bits of red in the RGBA and zero + bits of green, blue (alpha not specified) of color buffer + precision */ + glut_state_flag |= GLUT_LUMINANCE ; /* Somebody fix this for me! */ + break ; + + case 15 : /* "stencil": Number of bits in the stencil buffer */ + glut_state_flag |= GLUT_STENCIL; /* Somebody fix this for me! */ + break ; + + case 16 : /* "single": Boolean indicate the color buffer is single + buffered */ + glut_state_flag |= GLUT_SINGLE ; + break ; + + case 17 : /* "stereo": Boolean indicating the color buffer supports + OpenGL-style stereo */ + glut_state_flag |= GLUT_STEREO ; + break ; + + case 18 : /* "samples": Indicates the number of multisamples to use + based on GLX's SGIS_multisample extension (for + antialiasing) */ + glut_state_flag |= GLUT_MULTISAMPLE ; /*Somebody fix this for me!*/ + break ; + + case 19 : /* "slow": Boolean indicating if the frame buffer + configuration is slow or not */ + break ; + + case 20 : /* "win32pdf": (incorrect spelling but was there before */ + case 21 : /* "win32pfd": matches the Win32 Pixel Format Descriptor by + number */ +#if TARGET_HOST_MS_WINDOWS +#endif + break ; + + case 22 : /* "xvisual": matches the X visual ID by number */ +#if TARGET_HOST_POSIX_X11 +#endif + break ; + + case 23 : /* "xstaticgray": */ + case 29 : /* "xstaticgrey": boolean indicating if the frame buffer + configuration's X visual is of type StaticGray */ +#if TARGET_HOST_POSIX_X11 +#endif + break ; + + case 24 : /* "xgrayscale": */ + case 30 : /* "xgreyscale": boolean indicating if the frame buffer + configuration's X visual is of type GrayScale */ +#if TARGET_HOST_POSIX_X11 +#endif + break ; + + case 25 : /* "xstaticcolor": */ + case 31 : /* "xstaticcolour": boolean indicating if the frame buffer + configuration's X visual is of type StaticColor */ +#if TARGET_HOST_POSIX_X11 +#endif + break ; + + case 26 : /* "xpseudocolor": */ + case 32 : /* "xpseudocolour": boolean indicating if the frame buffer + configuration's X visual is of type PseudoColor */ +#if TARGET_HOST_POSIX_X11 +#endif + break ; + + case 27 : /* "xtruecolor": */ + case 33 : /* "xtruecolour": boolean indicating if the frame buffer + configuration's X visual is of type TrueColor */ +#if TARGET_HOST_POSIX_X11 +#endif + break ; + + case 28 : /* "xdirectcolor": */ + case 34 : /* "xdirectcolour": boolean indicating if the frame buffer + configuration's X visual is of type DirectColor */ +#if TARGET_HOST_POSIX_X11 +#endif + break ; + + case 35 : /* "borderless": windows should not have borders */ + glut_state_flag |= GLUT_BORDERLESS; + break ; + + case 36 : /* "aux": some number of aux buffers */ + glut_state_flag |= GLUT_AUX; + break ; + + case 37 : /* Unrecognized */ + fgWarning ( "WARNING - Display string token not recognized: %s", + token ); + break ; + } + + token = strtok ( NULL, " \t" ); + } + + free ( buffer ); + + /* We will make use of this value when creating a new OpenGL context... */ + fgState.DisplayMode = glut_state_flag; +} + +/* -- SETTING OPENGL 3.0 CONTEXT CREATION PARAMETERS ---------------------- */ + +void FGAPIENTRY glutInitContextVersion( int majorVersion, int minorVersion ) +{ + /* We will make use of these value when creating a new OpenGL context... */ + fgState.MajorVersion = majorVersion; + fgState.MinorVersion = minorVersion; +} + + +void FGAPIENTRY glutInitContextFlags( int flags ) +{ + /* We will make use of this value when creating a new OpenGL context... */ + fgState.ContextFlags = flags; +} + +void FGAPIENTRY glutInitContextProfile( int profile ) +{ + /* We will make use of this value when creating a new OpenGL context... */ + fgState.ContextProfile = profile; +} + +/* -------------- User Defined Error/Warning Handler Support -------------- */ + +/* + * Sets the user error handler (note the use of va_list for the args to the fmt) + */ +void FGAPIENTRY glutInitErrorFuncUcall( FGErrorUC callback, FGCBUserData userData ) +{ + /* This allows user programs to handle freeglut errors */ + fgState.ErrorFunc = callback; + fgState.ErrorFuncData = userData; +} + +static void fghInitErrorFuncCallback( const char *fmt, va_list ap, FGCBUserData userData ) +{ + FGError* callback = (FGError*)&userData; + (*callback)( fmt, ap ); +} + +void FGAPIENTRY glutInitErrorFunc( FGError callback ) +{ + if (callback) + { + FGError* reference = &callback; + glutInitErrorFuncUcall( fghInitErrorFuncCallback, *((FGCBUserData*)reference) ); + } + else + { + glutInitErrorFuncUcall( NULL, NULL ); + } +} + +/* + * Sets the user warning handler (note the use of va_list for the args to the fmt) + */ +void FGAPIENTRY glutInitWarningFuncUcall( FGWarningUC callback, FGCBUserData userData ) +{ + /* This allows user programs to handle freeglut warnings */ + fgState.WarningFunc = callback; + fgState.WarningFuncData = userData; +} + +static void fghInitWarningFuncCallback( const char *fmt, va_list ap, FGCBUserData userData ) +{ + FGWarning* callback = (FGWarning*)&userData; + (*callback)( fmt, ap ); +} + +void FGAPIENTRY glutInitWarningFunc( FGWarning callback ) +{ + if (callback) + { + FGWarning* reference = &callback; + glutInitWarningFuncUcall( fghInitWarningFuncCallback, *((FGCBUserData*)reference) ); + } + else + { + glutInitWarningFuncUcall( NULL, NULL ); + } +} + +/*** END OF FILE ***/ diff --git a/src/fg_init.h b/src/fg_init.h new file mode 100644 index 0000000..a9fdb17 --- /dev/null +++ b/src/fg_init.h @@ -0,0 +1,34 @@ +/* + * fg_init.h + * + * Various freeglut initialization functions. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Thu Dec 2 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __FG_INIT_H__ +#define __FG_INIT_H__ + +extern void fghCloseInputDevices(void); +extern void fgDeinitialize(void); + +#endif diff --git a/src/fg_input_devices.c b/src/fg_input_devices.c new file mode 100644 index 0000000..d4869d1 --- /dev/null +++ b/src/fg_input_devices.c @@ -0,0 +1,207 @@ +/* + * fg_input_devices.c + * + * Handles miscellaneous input devices via direct serial-port access. + * Proper X11 XInput device support is not yet supported. + * Also lacks Mac support. + * + * Written by Joe Krahn 2005 + * + * Copyright (c) 2005 Stephen J. Baker. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA OR STEPHEN J. BAKER BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" + +typedef struct _serialport SERIALPORT; + + +/********************* Dialbox definitions ***********************/ + +#define DIAL_NUM_VALUATORS 8 + +/* dial parser state machine states */ +#define DIAL_NEW (-1) +#define DIAL_WHICH_DEVICE 0 +#define DIAL_VALUE_HIGH 1 +#define DIAL_VALUE_LOW 2 + +/* dial/button box commands */ +#define DIAL_INITIALIZE 0x20 +#define DIAL_SET_LEDS 0x75 +#define DIAL_SET_TEXT 0x61 +#define DIAL_SET_AUTO_DIALS 0x50 +#define DIAL_SET_AUTO_DELTA_DIALS 0x51 +#define DIAL_SET_FILTER 0x53 +#define DIAL_SET_BUTTONS_MOM_TYPE 0x71 +#define DIAL_SET_AUTO_MOM_BUTTONS 0x73 +#define DIAL_SET_ALL_LEDS 0x4b +#define DIAL_CLEAR_ALL_LEDS 0x4c + +/* dial/button box replies and events */ +#define DIAL_INITIALIZED 0x20 +#define DIAL_BASE 0x30 +#define DIAL_DELTA_BASE 0x40 +#define DIAL_PRESS_BASE 0xc0 +#define DIAL_RELEASE_BASE 0xe0 + +/* macros to determine reply type */ +#define IS_DIAL_EVENT(ch) (((ch)>=DIAL_BASE)&&((ch)=DIAL_PRESS_BASE)&&((ch)=DIAL_RELEASE_BASE)&&((ch)Callbacks[CB_Dials] */ + INVOKE_WCB ( *window,Dials, ( ((int*)enumerator->data)[0], ((int*)enumerator->data)[1]) ); + fgEnumSubWindows ( window, fghcbEnumDialCallbacks, enumerator ); +} + +static void send_dial_event ( int num, int value ) +{ + SFG_Enumerator enumerator; + int data[2]; + data[0] = num; + data[1] = value; + enumerator.found = GL_FALSE; + enumerator.data = data; + fgEnumWindows ( fghcbEnumDialCallbacks, &enumerator ); +} + +/********************************************************************/ +static void poll_dials ( int id ) +{ + int data; + static int dial_state = DIAL_NEW; + static int dial_which; + static int dial_value; + + if ( !dialbox_port ) return; + + while ( (data=fg_serial_getchar(dialbox_port)) != EOF ) + { + if ( ( dial_state > DIAL_WHICH_DEVICE ) || IS_DIAL_EVENT ( data ) ) + { + switch ( dial_state ) + { + case DIAL_WHICH_DEVICE: + dial_which = data - DIAL_BASE; + dial_state++; + break; + case DIAL_VALUE_HIGH: + dial_value = ( data << 8 ); + dial_state++; + break; + case DIAL_VALUE_LOW: + dial_value |= data; + if ( dial_value & 0x8000 ) dial_value -= 0x10000; + send_dial_event ( dial_which + 1, dial_value * 360 / 256 ); + dial_state = DIAL_WHICH_DEVICE; + break; + default: + /* error: Impossible state value! */ + break; + } + } + else if ( data == DIAL_INITIALIZED ) + { + fgState.InputDevsInitialised = GL_TRUE; + dial_state = DIAL_WHICH_DEVICE; + fg_serial_putchar(dialbox_port,DIAL_SET_AUTO_DIALS); + fg_serial_putchar(dialbox_port,0xff); + fg_serial_putchar(dialbox_port,0xff); + } + else /* Unknown data; try flushing. */ + fg_serial_flush(dialbox_port); + } + + glutTimerFunc ( 2, poll_dials, 0 ); +} + diff --git a/src/fg_internal.h b/src/fg_internal.h new file mode 100644 index 0000000..04d187f --- /dev/null +++ b/src/fg_internal.h @@ -0,0 +1,1178 @@ +/* + * fg_internal.h + * + * The freeglut library private include file. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Thu Dec 2 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef FREEGLUT_INTERNAL_H +#define FREEGLUT_INTERNAL_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "fg_version.h" +#include "fg_callback_macros.h" + +/* Freeglut is intended to function under all Unix/X11 and Win32 platforms. */ +/* XXX: Don't all MS-Windows compilers (except Cygwin) have _WIN32 defined? + * XXX: If so, remove the first set of defined()'s below. + */ +#if !defined(TARGET_HOST_POSIX_X11) && !defined(TARGET_HOST_MS_WINDOWS) && !defined(TARGET_HOST_MAC_OSX) && !defined(TARGET_HOST_SOLARIS) && \ + !defined(TARGET_HOST_ANDROID) && !defined(TARGET_HOST_BLACKBERRY) && !defined(TARGET_HOST_POSIX_WAYLAND) +#if defined(_MSC_VER) || defined(__WATCOMC__) || defined(__MINGW32__) \ + || defined(_WIN32) || defined(_WIN32_WCE) \ + || ( defined(__CYGWIN__) && defined(X_DISPLAY_MISSING) ) +# define TARGET_HOST_MS_WINDOWS 1 + +#elif defined (__ANDROID__) +# define TARGET_HOST_ANDROID 1 + +#elif defined (__QNXNTO__) || defined (__PLAYBOOK__) +# define TARGET_HOST_BLACKBERRY 1 + +#elif defined(__posix__) || defined(unix) || defined(__unix__) || defined(__linux__) || defined(__sun) +# if defined(FREEGLUT_WAYLAND) +# define TARGET_HOST_POSIX_WAYLAND 1 +# else +# define TARGET_HOST_POSIX_X11 1 +# endif + +#elif defined(__APPLE__) +/* This is a placeholder until we get native OSX support ironed out -- JFF 11/18/09 */ +# define TARGET_HOST_POSIX_X11 1 +/* # define TARGET_HOST_MAC_OSX 1 */ + +#else +# error "Unrecognized target host!" + +#endif +#endif + +/* Detect both SunPro and gcc compilers on Sun Solaris */ +#if defined (__SVR4) && defined (__sun) +# define TARGET_HOST_SOLARIS 1 +#endif + +#ifndef TARGET_HOST_MS_WINDOWS +# define TARGET_HOST_MS_WINDOWS 0 +#endif + +#ifndef TARGET_HOST_ANDROID +# define TARGET_HOST_ANDROID 0 +#endif + +#ifndef TARGET_HOST_BLACKBERRY +# define TARGET_HOST_BLACKBERRY 0 +#endif + +#ifndef TARGET_HOST_POSIX_WAYLAND +# define TARGET_HOST_POSIX_WAYLAND 0 +#endif + +#ifndef TARGET_HOST_POSIX_X11 +# define TARGET_HOST_POSIX_X11 0 +#endif + +#ifndef TARGET_HOST_MAC_OSX +# define TARGET_HOST_MAC_OSX 0 +#endif + +#ifndef TARGET_HOST_SOLARIS +# define TARGET_HOST_SOLARIS 0 +#endif + +/* -- FIXED CONFIGURATION LIMITS ------------------------------------------- */ + +#define FREEGLUT_MAX_MENUS 3 + +/* These files should be available on every platform. */ +#include +#include +#include +#include +#include + +/* These are included based on autoconf directives. */ +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef TIME_WITH_SYS_TIME +# include +# include +#elif defined(HAVE_SYS_TIME_H) +# include +#else +# include +#endif + +/* -- AUTOCONF HACKS --------------------------------------------------------*/ + +/* XXX: Update autoconf to avoid these. + * XXX: Are non-POSIX platforms intended not to use autoconf? + * If so, perhaps there should be a config_guess.h for them. Alternatively, + * config guesses could be placed above, just after the config.h exclusion. + */ +#if defined(__FreeBSD__) || defined(__NetBSD__) +# define HAVE_USB_JS 1 +#endif + +#if defined(_MSC_VER) || defined(__WATCOMC__) +/* strdup() is non-standard, for all but POSIX-2001 */ +#define strdup _strdup +#endif + +/* M_PI is non-standard (defined by BSD, not ISO-C) */ +#ifndef M_PI +# define M_PI 3.14159265358979323846 +#endif + +#ifdef HAVE_STDBOOL_H +# include +# ifndef TRUE +# define TRUE true +# endif +# ifndef FALSE +# define FALSE false +# endif +#else +# ifndef TRUE +# define TRUE 1 +# endif +# ifndef FALSE +# define FALSE 0 +# endif +#endif + +/* General defines */ +#define INVALID_MODIFIERS 0xffffffff + +/* FreeGLUT internal time type */ +#if defined(HAVE_STDINT_H) +# include + typedef uint64_t fg_time_t; +#elif defined(HAVE_INTTYPES_H) +# include + typedef uint64_t fg_time_t; +#elif defined(HAVE_U__INT64) + typedef unsigned __int64 fg_time_t; +#elif defined(HAVE_ULONG_LONG) + typedef unsigned long long fg_time_t; +#else + typedef unsigned long fg_time_t; +#endif + +#ifndef __fg_unused +# ifdef __GNUC__ +# define __fg_unused __attribute__((unused)) +# else +# define __fg_unused +# endif +#endif + +/* Platform-specific includes */ +#if TARGET_HOST_POSIX_WAYLAND +#include "wayland/fg_internal_wl.h" +#endif +#if TARGET_HOST_POSIX_X11 +#include "x11/fg_internal_x11.h" +#endif +#if TARGET_HOST_MS_WINDOWS +#include "mswin/fg_internal_mswin.h" +#endif +#if TARGET_HOST_ANDROID +#include "android/fg_internal_android.h" +#endif +#if TARGET_HOST_BLACKBERRY +#include "blackberry/fg_internal_blackberry.h" +#endif + + +/* -- GLOBAL TYPE DEFINITIONS ---------------------------------------------- */ + +/* + * Freeglut callbacks type definitions + * + * If anything here is modified or added, update fg_callback_macros.h functions. + * + * This is not ideal, but freeglut needs to either define minimal compiler specs, + * or update header every time this is changed or updated. + */ +typedef void* FGCBUserData; + +typedef void (* FGCBDisplay )( void ); +typedef void (* FGCBDisplayUC )( FGCBUserData ); +typedef void (* FGCBReshape )( int, int ); +typedef void (* FGCBReshapeUC )( int, int, FGCBUserData ); +typedef void (* FGCBPosition )( int, int ); +typedef void (* FGCBPositionUC )( int, int, FGCBUserData ); +typedef void (* FGCBVisibility )( int ); +typedef void (* FGCBVisibilityUC )( int, FGCBUserData ); +typedef void (* FGCBKeyboard )( unsigned char, int, int ); +typedef void (* FGCBKeyboardUC )( unsigned char, int, int, FGCBUserData ); +typedef void (* FGCBKeyboardUp )( unsigned char, int, int ); +typedef void (* FGCBKeyboardUpUC )( unsigned char, int, int, FGCBUserData ); +typedef void (* FGCBSpecial )( int, int, int ); +typedef void (* FGCBSpecialUC )( int, int, int, FGCBUserData ); +typedef void (* FGCBSpecialUp )( int, int, int ); +typedef void (* FGCBSpecialUpUC )( int, int, int, FGCBUserData ); +typedef void (* FGCBMouse )( int, int, int, int ); +typedef void (* FGCBMouseUC )( int, int, int, int, FGCBUserData ); +typedef void (* FGCBMouseWheel )( int, int, int, int ); +typedef void (* FGCBMouseWheelUC )( int, int, int, int, FGCBUserData ); +typedef void (* FGCBMotion )( int, int ); +typedef void (* FGCBMotionUC )( int, int, FGCBUserData ); +typedef void (* FGCBPassive )( int, int ); +typedef void (* FGCBPassiveUC )( int, int, FGCBUserData ); +typedef void (* FGCBEntry )( int ); +typedef void (* FGCBEntryUC )( int, FGCBUserData ); +typedef void (* FGCBWindowStatus )( int ); +typedef void (* FGCBWindowStatusUC )( int, FGCBUserData ); +typedef void (* FGCBJoystick )( unsigned int, int, int, int ); +typedef void (* FGCBJoystickUC )( unsigned int, int, int, int, FGCBUserData ); +typedef void (* FGCBOverlayDisplay )( void ); +typedef void (* FGCBOverlayDisplayUC)( FGCBUserData ); +typedef void (* FGCBSpaceMotion )( int, int, int ); +typedef void (* FGCBSpaceMotionUC )( int, int, int, FGCBUserData ); +typedef void (* FGCBSpaceRotation )( int, int, int ); +typedef void (* FGCBSpaceRotationUC )( int, int, int, FGCBUserData ); +typedef void (* FGCBSpaceButton )( int, int ); +typedef void (* FGCBSpaceButtonUC )( int, int, FGCBUserData ); +typedef void (* FGCBDials )( int, int ); +typedef void (* FGCBDialsUC )( int, int, FGCBUserData ); +typedef void (* FGCBButtonBox )( int, int ); +typedef void (* FGCBButtonBoxUC )( int, int, FGCBUserData ); +typedef void (* FGCBTabletMotion )( int, int ); +typedef void (* FGCBTabletMotionUC )( int, int, FGCBUserData ); +typedef void (* FGCBTabletButton )( int, int, int, int ); +typedef void (* FGCBTabletButtonUC )( int, int, int, int, FGCBUserData ); +typedef void (* FGCBDestroy )( void ); /* Used for both window and menu destroy callbacks */ +typedef void (* FGCBDestroyUC )( FGCBUserData ); + +typedef void (* FGCBMultiEntry )( int, int ); +typedef void (* FGCBMultiEntryUC )( int, int, FGCBUserData ); +typedef void (* FGCBMultiButton )( int, int, int, int, int ); +typedef void (* FGCBMultiButtonUC )( int, int, int, int, int, FGCBUserData ); +typedef void (* FGCBMultiMotion )( int, int, int ); +typedef void (* FGCBMultiMotionUC )( int, int, int, FGCBUserData ); +typedef void (* FGCBMultiPassive )( int, int, int ); +typedef void (* FGCBMultiPassiveUC )( int, int, int, FGCBUserData ); + +typedef void (* FGCBInitContext )( void ); +typedef void (* FGCBInitContextUC )( FGCBUserData ); +typedef void (* FGCBAppStatus )( int ); +typedef void (* FGCBAppStatusUC )( int, FGCBUserData ); + +/* The global callbacks type definitions */ +typedef void (* FGCBIdle )( void ); +typedef void (* FGCBIdleUC )( FGCBUserData ); +typedef void (* FGCBTimer )( int ); +typedef void (* FGCBTimerUC )( int, FGCBUserData ); +typedef void (* FGCBMenuState )( int ); +typedef void (* FGCBMenuStatus )( int, int, int ); +typedef void (* FGCBMenuStatusUC )( int, int, int, FGCBUserData ); + +/* The callback used when creating/using menus */ +typedef void (* FGCBMenu )( int ); +typedef void (* FGCBMenuUC )( int, FGCBUserData ); + +/* The FreeGLUT error/warning handler type definition */ +typedef void (* FGError )( const char *fmt, va_list ap ); +typedef void (* FGErrorUC )( const char *fmt, va_list ap, FGCBUserData userData ); +typedef void (* FGWarning )( const char *fmt, va_list ap ); +typedef void (* FGWarningUC )( const char *fmt, va_list ap, FGCBUserData userData ); + + +/* A list structure */ +typedef struct tagSFG_List SFG_List; +struct tagSFG_List +{ + void *First; + void *Last; +}; + +/* A list node structure */ +typedef struct tagSFG_Node SFG_Node; +struct tagSFG_Node +{ + void *Next; + void *Prev; +}; + +/* A helper structure holding two ints and a boolean */ +typedef struct tagSFG_XYUse SFG_XYUse; +struct tagSFG_XYUse +{ + GLint X, Y; /* The two integers... */ + GLboolean Use; /* ...and a single boolean. */ +}; + +/* + * An enumeration containing the state of the GLUT execution: + * initializing, running, or stopping + */ +typedef enum +{ + GLUT_EXEC_STATE_INIT, + GLUT_EXEC_STATE_RUNNING, + GLUT_EXEC_STATE_STOP +} fgExecutionState ; + +/* This structure holds different freeglut settings */ +typedef struct tagSFG_State SFG_State; +struct tagSFG_State +{ + SFG_XYUse Position; /* The default windows' position */ + SFG_XYUse Size; /* The default windows' size */ + unsigned int DisplayMode; /* Display mode for new windows */ + + GLboolean Initialised; /* freeglut has been initialised */ + + int DirectContext; /* Direct rendering state */ + + GLboolean ForceIconic; /* New top windows are iconified */ + GLboolean UseCurrentContext; /* New windows share with current */ + + GLboolean GLDebugSwitch; /* OpenGL state debugging switch */ + GLboolean XSyncSwitch; /* X11 sync protocol switch */ + + int KeyRepeat; /* Global key repeat mode. */ + int Modifiers; /* Current ALT/SHIFT/CTRL state */ + + GLuint FPSInterval; /* Interval between FPS printfs */ + GLuint SwapCount; /* Count of glutSwapBuffer calls */ + GLuint SwapTime; /* Time of last SwapBuffers */ + + fg_time_t Time; /* Time that glutInit was called */ + SFG_List Timers; /* The freeglut timer hooks */ + SFG_List FreeTimers; /* The unused timer hooks */ + + FGCBIdleUC IdleCallback; /* The global idle callback */ + FGCBUserData IdleCallbackData; /* The global idle callback data */ + + int ActiveMenus; /* Num. of currently active menus */ + FGCBMenuState MenuStateCallback; /* Menu callbacks are global */ + FGCBMenuStatusUC MenuStatusCallback; + FGCBUserData MenuStatusCallbackData; + void* MenuFont; /* Font to be used for newly created menus */ + + SFG_XYUse GameModeSize; /* Game mode screen's dimensions */ + int GameModeDepth; /* The pixel depth for game mode */ + int GameModeRefresh; /* The refresh rate for game mode */ + + int ActionOnWindowClose; /* Action when user closes window */ + + fgExecutionState ExecState; /* Used for GLUT termination */ + char *ProgramName; /* Name of the invoking program */ + GLboolean JoysticksInitialised; /* Only initialize if application calls for them */ + int NumActiveJoysticks; /* Number of active joysticks (callback defined and positive pollrate) -- if zero, don't poll joysticks */ + GLboolean InputDevsInitialised; /* Only initialize if application calls for them */ + + int MouseWheelTicks; /* Number of ticks the mouse wheel has turned */ + + int AuxiliaryBufferNumber;/* Number of auxiliary buffers */ + int SampleNumber; /* Number of samples per pixel */ + + GLboolean SkipStaleMotion; /* skip stale motion events */ + + GLboolean StrokeFontDrawJoinDots;/* Draw dots between line segments of stroke fonts? */ + GLboolean AllowNegativeWindowPosition; /* GLUT, by default, doesn't allow negative window positions. Enable it? */ + + int MajorVersion; /* Major OpenGL context version */ + int MinorVersion; /* Minor OpenGL context version */ + int ContextFlags; /* OpenGL context flags */ + int ContextProfile; /* OpenGL context profile */ + int HasOpenGL20; /* fgInitGL2 could find all OpenGL 2.0 functions */ + FGErrorUC ErrorFunc; /* User defined error handler */ + FGCBUserData ErrorFuncData; /* User defined error handler user data */ + FGWarningUC WarningFunc; /* User defined warning handler */ + FGCBUserData WarningFuncData; /* User defined warning handler user data */ +}; + +/* The structure used by display initialization in fg_init.c */ +typedef struct tagSFG_Display SFG_Display; +struct tagSFG_Display +{ + SFG_PlatformDisplay pDisplay; + + int ScreenWidth; /* The screen's width in pixels */ + int ScreenHeight; /* The screen's height in pixels */ + int ScreenWidthMM; /* The screen's width in milimeters */ + int ScreenHeightMM; /* The screen's height in milimeters */ +}; + + +/* The user can create any number of timer hooks */ +typedef struct tagSFG_Timer SFG_Timer; +struct tagSFG_Timer +{ + SFG_Node Node; + int ID; /* The timer ID integer */ + FGCBTimerUC Callback; /* The timer callback */ + FGCBUserData CallbackData; /* The timer callback user data */ + fg_time_t TriggerTime; /* The timer trigger time */ +}; + +/* + * A window and its OpenGL context. The contents of this structure + * are highly dependent on the target operating system we aim at... + */ +typedef struct tagSFG_Context SFG_Context; +struct tagSFG_Context +{ + SFG_WindowHandleType Handle; /* The window's handle */ + SFG_WindowContextType Context; /* The window's OpenGL/WGL context */ + SFG_WindowColormapType cmap; /* The window's colormap/palette */ + int cmap_size; /* colormap number of entries */ + + SFG_PlatformContext pContext; /* The window's FBConfig (X11) or device context (Windows) */ + + int DoubleBuffered; /* Treat the window as double-buffered */ + + /* When drawing geometry to vertex attribute buffers, user specifies + * the attribute indices for vertices, normals and/or texture coords + * to freeglut. Those are stored here + */ + GLint attribute_v_coord; + GLint attribute_v_normal; + GLint attribute_v_texture; +}; + + +/* + * Bitmasks indicating the different kinds of + * actions that can be scheduled for a window. + */ +#define GLUT_INIT_WORK (1<<0) +#define GLUT_VISIBILITY_WORK (1<<1) +#define GLUT_POSITION_WORK (1<<2) +#define GLUT_SIZE_WORK (1<<3) +#define GLUT_ZORDER_WORK (1<<4) +#define GLUT_FULL_SCREEN_WORK (1<<5) +#define GLUT_DISPLAY_WORK (1<<6) + +/* + * An enumeration containing the desired mapping state of a window + */ +typedef enum +{ + DesireHiddenState, + DesireIconicState, + DesireNormalState +} fgDesiredVisibility ; + +/* + * There is considerable confusion about the "right thing to + * do" concerning window size and position. GLUT itself is + * not consistent between Windows and UNIX/X11; since + * platform independence is a virtue for "freeglut", we + * decided to break with GLUT's behaviour. + * + * Under UNIX/X11, it is apparently not possible to get the + * window border sizes in order to subtract them off the + * window's initial position until some time after the window + * has been created. Therefore we decided on the following + * behaviour, both under Windows and under UNIX/X11: + * - When you create a window with position (x,y) and size + * (w,h), the upper left hand corner of the outside of the + * window is at (x,y) and the size of the drawable area is + * (w,h). + * - When you query the size and position of the window--as + * is happening here for Windows--"freeglut" will return + * the size of the drawable area--the (w,h) that you + * specified when you created the window--and the coordinates + * of the upper left hand corner of the drawable area, i.e. + * of the client rect--which is NOT the (x,y) you specified. + */ +typedef struct tagSFG_WindowState SFG_WindowState; +struct tagSFG_WindowState /* as per notes above, sizes always refer to the client area (thus without the window decorations) */ +{ + /* window state - size, position, look */ + int Xpos; /* Window's top-left of client area, X-coordinate */ + int Ypos; /* Window's top-left of client area, Y-coordinate */ + int Width; /* Window's width in pixels */ + int Height; /* The same about the height */ + GLboolean Visible; /* Is the window visible now? Not using fgVisibilityState as we only care if visible or not */ + int Cursor; /* The currently selected cursor style */ + GLboolean IsFullscreen; /* is the window fullscreen? */ + + /* FreeGLUT operations are deferred, that is, window moving, resizing, + * Z-order changing, making full screen or not do not happen immediately + * upon the user's request, but only in the next iteration of the main + * loop, before the display callback is called. This allows multiple + * reshape, position, etc requests to be combined into one and is + * compatible with the way GLUT does things. Callbacks get triggered + * based on the feedback/messages/notifications from the window manager. + * Below here we define what work should be done, as well as the relevant + * parameters for this work. + */ + unsigned int WorkMask; /* work (resize, etc) to be done on the window */ + int DesiredXpos; /* desired X location */ + int DesiredYpos; /* desired Y location */ + int DesiredWidth; /* desired window width */ + int DesiredHeight; /* desired window height */ + int DesiredZOrder; /* desired window Z Order position */ + fgDesiredVisibility DesiredVisibility;/* desired visibility (hidden, iconic, shown/normal) */ + + SFG_PlatformWindowState pWState; /* Window width/height (X11) or rectangle/style (Windows) from before a resize, and other stuff only needed on specific platforms */ + + long JoystickPollRate; /* The joystick polling rate */ + fg_time_t JoystickLastPoll; /* When the last poll happened */ + + int MouseX, MouseY; /* The most recent mouse position */ + + GLboolean IgnoreKeyRepeat; /* Whether to ignore key repeat. */ + + GLboolean VisualizeNormals; /* When drawing objects, draw vectors representing the normals as well? */ +}; + + +/* + * A generic function pointer. We should really use the GLUTproc type + * defined in freeglut_ext.h, but if we include that header in this file + * a bunch of other stuff (font-related) blows up! + */ +typedef void (*SFG_Proc)(); + + +/* + * SET_WCB() is used as: + * + * SET_WCB( window, cbname, func, udata ); + * + * ...where {window} is the freeglut window to set the callback, + * {cbname} is the window-specific callback to set, + * {func} is a function-pointer, + * {udata} is a void* pointer for user data. + * + * Originally, {FETCH_WCB( ... ) = func} was rather sloppily used, + * but this can cause warnings because the FETCH_WCB() macro type- + * casts its result, and a type-cast value shouldn't be an lvalue. + * + * The {if( FETCH_WCB( ... ) != func )} test is to do type-checking + * and for no other reason. Since it's hidden in the macro, the + * ugliness is felt to be rather benign. + * + * If the function-pointer is the same, the data will be the only + * value updated. If the function-pointer changes, the data will + * be changed as well, preventing stail data from being passed in. + * Just updating the data does nothing unless a function-pointer + * exists, as the data is otherwise already allocated. + */ +#define SET_WCB(window,cbname,func,udata) \ +do \ +{ \ + if( FETCH_WCB( window, cbname ) != (SFG_Proc)(func) ) \ + { \ + (((window).CallBacks[WCB_ ## cbname]) = (SFG_Proc)(func)); \ + (((window).CallbackDatas[WCB_ ## cbname]) = (udata)); \ + } \ + else if( FETCH_USER_DATA_WCB( window, cbname ) != udata ) \ + { \ + (((window).CallbackDatas[WCB_ ## cbname]) = (udata)); \ + } \ +} while( 0 ) + +/* + * FETCH_WCB() is used as: + * + * FETCH_WCB( window, cbname ); + * + * ...where {window} is the freeglut window to fetch the callback from, + * {cbname} is the window-specific callback to fetch. + * + * The result is correctly type-cast to the callback function pointer + * type. + */ +#define FETCH_WCB(window,cbname) \ + ((window).CallBacks[WCB_ ## cbname]) + +/* + * FETCH_USER_DATA_WCB() is used as: + * + * FETCH_USER_DATA_WCB( window, cbname ); + * + * ...where {window} is the freeglut window, + * {cbname} is the window-specific callback to be invoked, + * + * This expects a variable named "window" of type tagSFG_Window to exist. + * + * The result is the callback data pointer. + */ +#define FETCH_USER_DATA_WCB(window,cbname) \ + ((window).CallbackDatas[WCB_ ## cbname]) + +/* + * EXPAND_WCB() is used as: + * + * EXPAND_WCB( cbname )(( arg_list, userData )) + * + * ... where {(arg_list)} is the parameter list and userData is user + * provided data. + * + * This will take the arg_list and extend it by one argument, adding + * the argument "userData" to the end of the list. + * + * All of this is defined in fg_callback_macros.h + * + * See that header for more info. + * + * ------------------------------------------------------------------ + */ + +/* + * INVOKE_WCB() is used as: + * + * INVOKE_WCB( window, cbname, ( arg_list ) ); + * + * ...where {window} is the freeglut window, + * {cbname} is the window-specific callback to be invoked, + * {(arg_list)} is the parameter list. + * + * The callback is invoked as: + * + * callback( arg_list, userData ); + * + * ...where userData is added to the arg_list, but the parentheses + * are REQUIRED in the {arg_list}. + * + * NOTE that it does a sanity-check and also sets the + * current window. + * + */ +#define INVOKE_WCB(window,cbname,arg_list) \ +do \ +{ \ + if( FETCH_WCB( window, cbname ) ) \ + { \ + FGCB ## cbname ## UC func = (FGCB ## cbname ## UC)(FETCH_WCB( window, cbname )); \ + FGCBUserData userData = FETCH_USER_DATA_WCB( window, cbname ); \ + fgSetWindow( &window ); \ + func EXPAND_WCB( cbname )(( arg_list, userData )); \ + } \ +} while( 0 ) + +/* + * The window callbacks the user can supply us with. Should be kept portable. + * + * This enumeration provides the freeglut CallBack numbers. + * The symbolic constants are indices into a window's array of + * function callbacks. The names are formed by splicing a common + * prefix onto the callback's base name. (This was originally + * done so that an early stage of development could live side-by- + * side with the old callback code. The old callback code used + * the bare callback's name as a structure member, so I used a + * prefix for the array index name.) + */ +enum +{ + WCB_Display, + WCB_Reshape, + WCB_Position, + WCB_Keyboard, + WCB_KeyboardUp, + WCB_Special, + WCB_SpecialUp, + WCB_Mouse, + WCB_MouseWheel, + WCB_Motion, + WCB_Passive, + WCB_Entry, + WCB_Visibility, + WCB_WindowStatus, + WCB_Joystick, + WCB_Destroy, + + /* Multi-Pointer X and touch related */ + WCB_MultiEntry, + WCB_MultiButton, + WCB_MultiMotion, + WCB_MultiPassive, + + /* Mobile platforms LifeCycle */ + WCB_InitContext, + WCB_AppStatus, + + /* Presently ignored */ + WCB_Select, + WCB_OverlayDisplay, + WCB_SpaceMotion, /* presently implemented only on UNIX/X11 and Windows */ + WCB_SpaceRotation, /* presently implemented only on UNIX/X11 and Windows */ + WCB_SpaceButton, /* presently implemented only on UNIX/X11 and Windows */ + WCB_Dials, + WCB_ButtonBox, + WCB_TabletMotion, + WCB_TabletButton, + + /* Always make this the LAST one */ + TOTAL_CALLBACKS +}; + + +/* This structure holds the OpenGL rendering context for all the menu windows */ +typedef struct tagSFG_MenuContext SFG_MenuContext; +struct tagSFG_MenuContext +{ + SFG_WindowContextType MContext; /* The menu window's WGL context */ +}; + +/* This structure describes a menu */ +typedef struct tagSFG_Window SFG_Window; +typedef struct tagSFG_MenuEntry SFG_MenuEntry; +typedef struct tagSFG_Menu SFG_Menu; +struct tagSFG_Menu +{ + SFG_Node Node; + void *UserData; /* User data passed back at callback */ + int ID; /* The global menu ID */ + SFG_List Entries; /* The menu entries list */ + FGCBMenuUC Callback; /* The menu callback */ + FGCBUserData CallbackData; /* The menu callback user data */ + FGCBDestroyUC Destroy; /* Destruction callback */ + FGCBUserData DestroyData; /* Destruction callback user data */ + GLboolean IsActive; /* Is the menu selected? */ + void* Font; /* Font to be used for displaying this menu */ + int Width; /* Menu box width in pixels */ + int Height; /* Menu box height in pixels */ + int X, Y; /* Menu box raster position */ + + SFG_MenuEntry *ActiveEntry; /* Currently active entry in the menu */ + SFG_Window *Window; /* Window for menu */ + SFG_Window *ParentWindow; /* Window in which the menu is invoked */ +}; + +/* This is a menu entry */ +struct tagSFG_MenuEntry +{ + SFG_Node Node; + int ID; /* The menu entry ID (local) */ + int Ordinal; /* The menu's ordinal number */ + char* Text; /* The text to be displayed */ + SFG_Menu* SubMenu; /* Optional sub-menu tree */ + GLboolean IsActive; /* Is the entry highlighted? */ + int Width; /* Label's width in pixels */ +}; + +/* + * A window, making part of freeglut windows hierarchy. + * Should be kept portable. + * + * NOTE that ActiveMenu is set to menu itself if the window is a menu. + */ +struct tagSFG_Window +{ + SFG_Node Node; + int ID; /* Window's ID number */ + + SFG_Context Window; /* Window and OpenGL context */ + SFG_WindowState State; /* The window state */ + SFG_Proc CallBacks[ TOTAL_CALLBACKS ]; /* Array of window callbacks */ + FGCBUserData CallbackDatas[ TOTAL_CALLBACKS ]; /* Array of window callback datas */ + void *UserData ; /* For use by user */ + + SFG_Menu* Menu[ FREEGLUT_MAX_MENUS ]; /* Menus appended to window */ + SFG_Menu* ActiveMenu; /* The window's active menu */ + + SFG_Window* Parent; /* The parent to this window */ + SFG_List Children; /* The subwindows d.l. list */ + + GLboolean IsMenu; /* Set to 1 if we are a menu */ +}; + + +/* A linked list structure of windows */ +typedef struct tagSFG_WindowList SFG_WindowList ; +struct tagSFG_WindowList +{ + SFG_Node node; + SFG_Window *window ; +}; + +/* This holds information about all the windows, menus etc. */ +typedef struct tagSFG_Structure SFG_Structure; +struct tagSFG_Structure +{ + SFG_List Windows; /* The global windows list */ + SFG_List Menus; /* The global menus list */ + SFG_List WindowsToDestroy; + + SFG_Window* CurrentWindow; /* The currently set window */ + SFG_Menu* CurrentMenu; /* Same, but menu... */ + + SFG_MenuContext* MenuContext; /* OpenGL rendering context for menus */ + + SFG_Window* GameModeWindow; /* The game mode window */ + + int WindowID; /* The window ID for the next window to be created */ + int MenuID; /* The menu ID for the next menu to be created */ +}; + +/* + * This structure is used for the enumeration purposes. + * You can easily extend its functionalities by declaring + * a structure containing enumerator's contents and custom + * data, then casting its pointer to (SFG_Enumerator *). + */ +typedef struct tagSFG_Enumerator SFG_Enumerator; +struct tagSFG_Enumerator +{ + GLboolean found; /* Used to terminate search */ + void* data; /* Custom data pointer */ +}; +typedef void (* FGCBWindowEnumerator )( SFG_Window *, SFG_Enumerator * ); +typedef void (* FGCBMenuEnumerator )( SFG_Menu *, SFG_Enumerator * ); + +/* The bitmap font structure */ +typedef struct tagSFG_Font SFG_Font; +struct tagSFG_Font +{ + char* Name; /* The source font name */ + int Quantity; /* Number of chars in font */ + int Height; /* Height of the characters */ + const GLubyte** Characters; /* The characters mapping */ + + float xorig, yorig; /* Relative origin of the character */ +}; + +/* The stroke font structures */ + +typedef struct tagSFG_StrokeVertex SFG_StrokeVertex; +struct tagSFG_StrokeVertex +{ + GLfloat X, Y; +}; + +typedef struct tagSFG_StrokeStrip SFG_StrokeStrip; +struct tagSFG_StrokeStrip +{ + int Number; + const SFG_StrokeVertex* Vertices; +}; + +typedef struct tagSFG_StrokeChar SFG_StrokeChar; +struct tagSFG_StrokeChar +{ + GLfloat Right; + int Number; + const SFG_StrokeStrip* Strips; +}; + +typedef struct tagSFG_StrokeFont SFG_StrokeFont; +struct tagSFG_StrokeFont +{ + char* Name; /* The source font name */ + int Quantity; /* Number of chars in font */ + GLfloat Height; /* Height of the characters */ + const SFG_StrokeChar** Characters; /* The characters mapping */ +}; + + +/* -- JOYSTICK-SPECIFIC STRUCTURES AND TYPES ------------------------------- */ +/* + * Initial defines from "js.h" starting around line 33 with the existing "fg_joystick.c" + * interspersed + */ + +#if TARGET_HOST_MACINTOSH +# include +#endif + +#if TARGET_HOST_MAC_OSX +# include +# include +# include +#endif + +/* XXX It might be better to poll the operating system for the numbers of buttons and + * XXX axes and then dynamically allocate the arrays. + */ +#define _JS_MAX_BUTTONS 32 + +#if TARGET_HOST_MACINTOSH +# define _JS_MAX_AXES 9 +typedef struct tagSFG_PlatformJoystick SFG_PlatformJoystick; +struct tagSFG_PlatformJoystick +{ +#define ISP_NUM_AXIS 9 +#define ISP_NUM_NEEDS 41 + ISpElementReference isp_elem [ ISP_NUM_NEEDS ]; + ISpNeed isp_needs [ ISP_NUM_NEEDS ]; +}; +#endif + +#if TARGET_HOST_MAC_OSX +# define _JS_MAX_AXES 16 +typedef struct tagSFG_PlatformJoystick SFG_PlatformJoystick; +struct tagSFG_PlatformJoystick +{ + IOHIDDeviceInterface ** hidDev; + IOHIDElementCookie buttonCookies[41]; + IOHIDElementCookie axisCookies[_JS_MAX_AXES]; +/* The next two variables are not used anywhere */ +/* long minReport[_JS_MAX_AXES], + * maxReport[_JS_MAX_AXES]; + */ +}; +#endif + + +/* + * Definition of "SFG_Joystick" structure -- based on JS's "jsJoystick" object class. + * See "js.h" lines 80-178. + */ +typedef struct tagSFG_Joystick SFG_Joystick; +struct tagSFG_Joystick +{ + SFG_PlatformJoystick pJoystick; + + int id; + GLboolean error; + char name [ 128 ]; + int num_axes; + int num_buttons; + + float dead_band[ _JS_MAX_AXES ]; + float saturate [ _JS_MAX_AXES ]; + float center [ _JS_MAX_AXES ]; + float max [ _JS_MAX_AXES ]; + float min [ _JS_MAX_AXES ]; +}; + + + +/* -- GLOBAL VARIABLES EXPORTS --------------------------------------------- */ + +/* Freeglut display related stuff (initialized once per session) */ +extern SFG_Display fgDisplay; + +/* Freeglut internal structure */ +extern SFG_Structure fgStructure; + +/* The current freeglut settings */ +extern SFG_State fgState; + + +/* -- PRIVATE FUNCTION DECLARATIONS ---------------------------------------- */ + +/* + * A call to this function makes us sure that the Display and Structure + * subsystems have been properly initialized and are ready to be used + */ +#define FREEGLUT_EXIT_IF_NOT_INITIALISED( string ) \ + if ( ! fgState.Initialised ) \ + { \ + fgError ( " ERROR: Function <%s> called" \ + " without first calling 'glutInit'.", (string) ) ; \ + } + +#define FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED( string ) \ + if ( ! fgState.Initialised ) \ + { \ + fgError ( " ERROR: Internal <%s> function called" \ + " without first calling 'glutInit'.", (string) ) ; \ + } + +#define FREEGLUT_INTERNAL_ERROR_EXIT( cond, string, function ) \ + if ( ! ( cond ) ) \ + { \ + fgError ( " ERROR: Internal error <%s> in function %s", \ + (string), (function) ) ; \ + } + +/* + * Following definitions are somewhat similar to GLib's, + * but do not generate any log messages: + */ +#define freeglut_return_if_fail( expr ) \ + if( !(expr) ) \ + return; +#define freeglut_return_val_if_fail( expr, val ) \ + if( !(expr) ) \ + return val ; + +/* + * A call to those macros assures us that there is a current + * window set, respectively: + */ +#define FREEGLUT_EXIT_IF_NO_WINDOW( string ) \ + if ( ! fgStructure.CurrentWindow && \ + ( fgState.ActionOnWindowClose != GLUT_ACTION_CONTINUE_EXECUTION ) ) \ + { \ + fgError ( " ERROR: Function <%s> called" \ + " with no current window defined.", (string) ) ; \ + } + +/* + * The deinitialize function gets called on glutMainLoop() end. It should clean up + * everything inside of the freeglut + */ +void fgDeinitialize( void ); + +/* + * Those two functions are used to create/destroy the freeglut internal + * structures. This actually happens when calling glutInit() and when + * quitting the glutMainLoop() (which actually happens, when all windows + * have been closed). + */ +void fgCreateStructure( void ); +void fgDestroyStructure( void ); + +/* + * Window creation, opening, closing and destruction. + * Also CallBack clearing/initialization. + * Defined in fg_structure.c, fg_window.c. + */ +SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, + GLboolean positionUse, int x, int y, + GLboolean sizeUse, int w, int h, + GLboolean gameMode, GLboolean isMenu ); +void fgSetWindow ( SFG_Window *window ); +void fgOpenWindow( SFG_Window* window, const char* title, + GLboolean positionUse, int x, int y, + GLboolean sizeUse, int w, int h, + GLboolean gameMode, GLboolean isSubWindow ); +void fgCloseWindow( SFG_Window* window ); +void fgAddToWindowDestroyList ( SFG_Window* window ); +void fgCloseWindows (); +void fgDestroyWindow( SFG_Window* window ); + +/* Menu creation and destruction. Defined in fg_structure.c */ +SFG_Menu* fgCreateMenu( FGCBMenuUC menuCallback, FGCBUserData userData ); +void fgDestroyMenu( SFG_Menu* menu ); + +/* Joystick device management functions, defined in fg_joystick.c */ +int fgJoystickDetect(void); +void fgInitialiseJoysticks(void); +void fgJoystickClose(void); +void fgJoystickPollWindow(SFG_Window *window); +void fgJoystickRawRead(SFG_Joystick *joy, int *buttons, float *axes); + +/* InputDevice Initialisation and Closure */ +int fgInputDeviceDetect( void ); +void fgInitialiseInputDevices( void ); +void fgInputDeviceClose( void ); + +/* spaceball device functions, defined in fg_spaceball.c */ +void fgInitialiseSpaceball( void ); +void fgSpaceballClose( void ); +void fgSpaceballSetWindow( SFG_Window *window ); + +int fgHasSpaceball( void ); +int fgSpaceballNumButtons( void ); + +/* Setting the cursor for a given window */ +void fgSetCursor ( SFG_Window *window, int cursorID ); + +/* + * Helper function to enumerate through all registered windows + * and one to enumerate all of a window's subwindows... + * + * The GFunc callback for those functions will be defined as: + * + * void enumCallback( gpointer window, gpointer enumerator ); + * + * where window is the enumerated (sub)window pointer (SFG_Window *), + * and userData is the a custom user-supplied pointer. Functions + * are defined and exported from fg_structure.c file. + */ +void fgEnumWindows( FGCBWindowEnumerator enumCallback, SFG_Enumerator* enumerator ); +void fgEnumSubWindows( SFG_Window* window, FGCBWindowEnumerator enumCallback, + SFG_Enumerator* enumerator ); + +/* + * fgWindowByHandle returns a (SFG_Window *) value pointing to the + * first window in the queue matching the specified window handle. + * The function is defined in fg_structure.c file. + */ +SFG_Window* fgWindowByHandle( SFG_WindowHandleType hWindow ); + +/* + * This function is similar to the previous one, except it is + * looking for a specified (sub)window identifier. The function + * is defined in fg_structure.c file. + */ +SFG_Window* fgWindowByID( int windowID ); + +/* + * Looks up a menu given its ID. This is easier than fgWindowByXXX + * as all menus are placed in a single doubly linked list... + */ +SFG_Menu* fgMenuByID( int menuID ); + +/* + * Returns active menu, if any. Assumption: only one menu active throughout application at any one time. + * This is easier than fgWindowByXXX as all menus are placed in one doubly linked list... + */ +SFG_Menu* fgGetActiveMenu( ); + +/* + * The menu activation and deactivation the code. This is the meat + * of the menu user interface handling code... + */ +void fgUpdateMenuHighlight ( SFG_Menu *menu ); +GLboolean fgCheckActiveMenu ( SFG_Window *window, int button, GLboolean pressed, + int mouse_x, int mouse_y ); +void fgDeactivateMenu( SFG_Window *window ); + +/* + * This function gets called just before the buffers swap, so that + * freeglut can display the pull-down menus via OpenGL. The function + * is defined in fg_menu.c file. + */ +void fgDisplayMenu( void ); + +/* Elapsed time as per glutGet(GLUT_ELAPSED_TIME). */ +fg_time_t fgElapsedTime( void ); + +/* System time in milliseconds */ +fg_time_t fgSystemTime(void); + +/* List functions */ +void fgListInit(SFG_List *list); +void fgListAppend(SFG_List *list, SFG_Node *node); +void fgListRemove(SFG_List *list, SFG_Node *node); +int fgListLength(SFG_List *list); +void fgListInsert(SFG_List *list, SFG_Node *next, SFG_Node *node); + +/* Error Message functions */ +void fgError( const char *fmt, ... ); +void fgWarning( const char *fmt, ... ); + +SFG_Proc fgPlatformGetProcAddress( const char *procName ); + +/* pushing attribute/value pairs into an array */ +#define ATTRIB(a) attributes[where++]=(a) +#define ATTRIB_VAL(a,v) {ATTRIB(a); ATTRIB(v);} + +int fghMapBit( int mask, int from, int to ); +int fghIsLegacyContextRequested( SFG_Window *win ); +void fghContextCreationError( void ); +int fghNumberOfAuxBuffersRequested( void ); + +#endif /* FREEGLUT_INTERNAL_H */ + +/*** END OF FILE ***/ diff --git a/src/fg_joystick.c b/src/fg_joystick.c new file mode 100644 index 0000000..a85c5e1 --- /dev/null +++ b/src/fg_joystick.c @@ -0,0 +1,827 @@ +/* + * fg_joystick.c + * + * Joystick handling code + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Steve Baker, + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * FreeBSD port by Stephen Montgomery-Smith + * + * Redone by John Fay 2/4/04 with another look from the PLIB "js" library. + * Many thanks for Steve Baker for permission to pull from that library. + */ + +#include +#include "fg_internal.h" +#ifdef HAVE_SYS_PARAM_H +# include +#endif + +#define JS_TRUE 1 +#define JS_FALSE 0 + +/* + * Functions associated with the "jsJoystick" class in PLIB + */ +#if TARGET_HOST_MAC_OSX +#define K_NUM_DEVICES 32 +int numDevices; +io_object_t ioDevices[K_NUM_DEVICES]; + +static void fghJoystickFindDevices ( SFG_Joystick* joy, mach_port_t ); +static CFDictionaryRef fghJoystickGetCFProperties ( SFG_Joystick* joy, io_object_t ); + +static void fghJoystickEnumerateElements ( SFG_Joystick* joy, CFTypeRef element ); +/* callback for CFArrayApply */ +static void fghJoystickElementEnumerator ( SFG_Joystick* joy, void *element, void* vjs ); + +static void fghJoystickAddAxisElement ( SFG_Joystick* joy, CFDictionaryRef axis ); +static void fghJoystickAddButtonElement ( SFG_Joystick* joy, CFDictionaryRef button ); +static void fghJoystickAddHatElement ( SFG_Joystick* joy, CFDictionaryRef hat ); +#endif + + +/* External function declarations (mostly platform-specific) */ +extern void fgPlatformJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes ); +extern void fgPlatformJoystickOpen( SFG_Joystick* joy ); +extern void fgPlatformJoystickInit( SFG_Joystick *fgJoystick[], int ident ); +extern void fgPlatformJoystickClose ( int ident ); + +/* + * The static joystick structure pointer + */ +#define MAX_NUM_JOYSTICKS 2 +SFG_Joystick *fgJoystick [ MAX_NUM_JOYSTICKS ]; + +/* + * Read the raw joystick data + */ +void fgJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes ) +{ + int i; + + /* Defaults */ + if( buttons ) + *buttons = 0; + + if( axes ) + for( i = 0; i < joy->num_axes; i++ ) + axes[ i ] = 1500.0f; + + if( joy->error ) + return; + + fgPlatformJoystickRawRead ( joy, buttons, axes ); +} + +/* + * Correct the joystick axis data + */ +static float fghJoystickFudgeAxis( SFG_Joystick* joy, float value, int axis ) +{ + if( value < joy->center[ axis ] ) + { + float xx = ( value - joy->center[ axis ] ) / ( joy->center[ axis ] - + joy->min[ axis ] ); + + if( xx < -joy->saturate[ axis ] ) + return -1.0f; + + if( xx > -joy->dead_band [ axis ] ) + return 0.0f; + + xx = ( xx + joy->dead_band[ axis ] ) / ( joy->saturate[ axis ] - + joy->dead_band[ axis ] ); + + return ( xx < -1.0f ) ? -1.0f : xx; + } + else + { + float xx = ( value - joy->center [ axis ] ) / ( joy->max[ axis ] - + joy->center[ axis ] ); + + if( xx > joy->saturate[ axis ] ) + return 1.0f; + + if( xx < joy->dead_band[ axis ] ) + return 0.0f; + + xx = ( xx - joy->dead_band[ axis ] ) / ( joy->saturate[ axis ] - + joy->dead_band[ axis ] ); + + return ( xx > 1.0f ) ? 1.0f : xx; + } +} + +/* + * Read the corrected joystick data + */ +static void fghJoystickRead( SFG_Joystick* joy, int* buttons, float* axes ) +{ + float raw_axes[ _JS_MAX_AXES ]; + int i; + + if( joy->error ) + { + if( buttons ) + *buttons = 0; + + if( axes ) + for ( i=0; inum_axes; i++ ) + axes[ i ] = 0.0f; + } + + fgJoystickRawRead( joy, buttons, raw_axes ); + + if( axes ) + for( i=0; inum_axes; i++ ) + axes[ i ] = fghJoystickFudgeAxis( joy, raw_axes[ i ], i ); +} + +/* + * Happy happy happy joy joy joy (happy new year toudi :D) + */ + + +#if TARGET_HOST_MAC_OSX +/** open the IOKit connection, enumerate all the HID devices, add their +interface references to the static array. We then use the array index +as the device number when we come to open() the joystick. */ +static int fghJoystickFindDevices ( SFG_Joystick *joy, mach_port_t masterPort ) +{ + CFMutableDictionaryRef hidMatch = NULL; + IOReturn rv = kIOReturnSuccess; + + io_iterator_t hidIterator; + io_object_t ioDev; + + /* build a dictionary matching HID devices */ + hidMatch = IOServiceMatching(kIOHIDDeviceKey); + + rv = IOServiceGetMatchingServices(masterPort, hidMatch, &hidIterator); + if (rv != kIOReturnSuccess || !hidIterator) { + fgWarning( "no joystick (HID) devices found" ); + return; + } + + /* iterate */ + while ((ioDev = IOIteratorNext(hidIterator))) { + /* filter out keyboard and mouse devices */ + CFDictionaryRef properties = getCFProperties(ioDev); + long usage, page; + + CFTypeRef refPage = CFDictionaryGetValue (properties, CFSTR(kIOHIDPrimaryUsagePageKey)); + CFTypeRef refUsage = CFDictionaryGetValue (properties, CFSTR(kIOHIDPrimaryUsageKey)); + CFNumberGetValue((CFNumberRef) refUsage, kCFNumberLongType, &usage); + CFNumberGetValue((CFNumberRef) refPage, kCFNumberLongType, &page); + + /* keep only joystick devices */ + if ( ( page == kHIDPage_GenericDesktop ) && ( + (usage == kHIDUsage_GD_Joystick) + || (usage == kHIDUsage_GD_GamePad) + || (usage == kHIDUsage_GD_MultiAxisController) + || (usage == kHIDUsage_GD_Hatswitch) /* last two necessary ? */ + /* add it to the array */ + ioDevices[numDevices++] = ioDev; + } + + IOObjectRelease(hidIterator); +} + +static CFDictionaryRef fghJoystickGetCFProperties ( SFG_Joystick *joy, io_object_t ioDev ) +{ + IOReturn rv; + CFMutableDictionaryRef cfProperties; + +#if 0 + /* comment copied from darwin/SDL_sysjoystick.c */ + /* Mac OS X currently is not mirroring all USB properties to HID page so need to look at USB device page also + * get dictionary for usb properties: step up two levels and get CF dictionary for USB properties + */ + + io_registry_entry_t parent1, parent2; + + rv = IORegistryEntryGetParentEntry (ioDev, kIOServicePlane, &parent1); + if (rv != kIOReturnSuccess) { + fgWarning ( "error getting device entry parent"); + return NULL; + } + + rv = IORegistryEntryGetParentEntry (parent1, kIOServicePlane, &parent2); + if (rv != kIOReturnSuccess) { + fgWarning ( "error getting device entry parent 2"); + return NULL; + } +#endif + + rv = IORegistryEntryCreateCFProperties( ioDev /*parent2*/, + &cfProperties, kCFAllocatorDefault, kNilOptions); + if (rv != kIOReturnSuccess || !cfProperties) { + fgWarning ( "error getting device properties"); + return NULL; + } + + return cfProperties; +} + +static void fghJoystickElementEnumerator ( SFG_Joystick *joy, void *element, void* vjs ) +{ + if (CFGetTypeID((CFTypeRef) element) != CFDictionaryGetTypeID()) { + fgError ( "%s", "element enumerator passed non-dictionary value"); + return; + } + + static_cast(vjs)->parseElement ( (CFDictionaryRef) element ); +} + +/** element enumerator function : pass NULL for top-level*/ +static void fghJoystickEnumerateElements ( SFG_Joystick *joy, CFTypeRef element ) +{ + FREEGLUT_INTERNAL_ERROR_EXIT( (CFGetTypeID(element) == CFArrayGetTypeID(), + "Joystick element type mismatch", + "fghJoystickEnumerateElements" ); + + CFRange range = {0, CFArrayGetCount ((CFArrayRef)element)}; + CFArrayApplyFunction((CFArrayRef) element, range, + &fghJoystickElementEnumerator, joy ); +} + +static void fghJoystickAddAxisElement ( SFG_Joystick *joy, CFDictionaryRef axis ) +{ + long cookie, lmin, lmax; + int index = joy->num_axes++; + + CFNumberGetValue ((CFNumberRef) + CFDictionaryGetValue ( axis, CFSTR(kIOHIDElementCookieKey) ), + kCFNumberLongType, &cookie); + + joy->pJoystick.axisCookies[index] = (IOHIDElementCookie) cookie; + + CFNumberGetValue ((CFNumberRef) + CFDictionaryGetValue ( axis, CFSTR(kIOHIDElementMinKey) ), + kCFNumberLongType, &lmin); + + CFNumberGetValue ((CFNumberRef) + CFDictionaryGetValue ( axis, CFSTR(kIOHIDElementMaxKey) ), + kCFNumberLongType, &lmax); + + joy->min[index] = lmin; + joy->max[index] = lmax; + joy->dead_band[index] = 0.0; + joy->saturate[index] = 1.0; + joy->center[index] = (lmax + lmin) * 0.5; +} + +static void fghJoystickAddButtonElement ( SFG_Joystick *joy, CFDictionaryRef button ) +{ + long cookie; + CFNumberGetValue ((CFNumberRef) + CFDictionaryGetValue ( button, CFSTR(kIOHIDElementCookieKey) ), + kCFNumberLongType, &cookie); + + joy->pJoystick.buttonCookies[num_buttons++] = (IOHIDElementCookie) cookie; + /* anything else for buttons? */ +} + +static void fghJoystickAddHatElement ( SFG_Joystick *joy, CFDictionaryRef button ) +{ + /* hatCookies[num_hats++] = (IOHIDElementCookie) cookie; */ + /* do we map hats to axes or buttons? */ +} +#endif + +/* + * Platform-Specific Code + */ + +#if TARGET_HOST_MACINTOSH +void fgPlatformJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes ) +{ + int i; + + if ( buttons ) + { + *buttons = 0; + + for ( i = 0; i < joy->num_buttons; i++ ) + { + UInt32 state; + int err = ISpElement_GetSimpleState ( joy->pJoystick.isp_elem [ i + ISP_NUM_AXIS ], &state); + ISP_CHECK_ERR(err) + + *buttons |= state << i; + } + } + + if ( axes ) + { + for ( i = 0; i < joy->num_axes; i++ ) + { + UInt32 state; + int err = ISpElement_GetSimpleState ( joy->pJoystick.isp_elem [ i ], &state ); + ISP_CHECK_ERR(err) + + axes [i] = (float) state; + } + } +} + + +void fgPlatformJoystickOpen( SFG_Joystick* joy ) +{ + int i = 0; + OSStatus err; + + /* XXX FIXME: get joystick name in Mac */ + + err = ISpStartup( ); + + if( err == noErr ) + { +#define ISP_CHECK_ERR(x) if( x != noErr ) { joy->error = GL_TRUE; return; } + + joy->error = GL_TRUE; + + /* initialize the needs structure */ + ISpNeed temp_isp_needs[ ISP_NUM_NEEDS ] = + { + { "\pX-Axis", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, + { "\pY-Axis", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, + { "\pZ-Axis", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, + { "\pR-Axis", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, + { "\pAxis 4", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, + { "\pAxis 5", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, + { "\pAxis 6", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, + { "\pAxis 7", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, + { "\pAxis 8", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, + + { "\pButton 0", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 1", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 2", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 3", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 4", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 5", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 6", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 7", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 8", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 9", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 10", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 11", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 12", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 13", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 14", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 15", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 16", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 17", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 18", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 19", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 20", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 21", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 22", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 23", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 24", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 25", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 26", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 27", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 28", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 29", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 30", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 31", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + }; + + memcpy( joy->pJoystick.isp_needs, temp_isp_needs, sizeof (temp_isp_needs ) ); + + + /* next two calls allow keyboard and mouse to emulate other input + * devices (gamepads, joysticks, etc) + */ + /* + err = ISpDevices_ActivateClass ( kISpDeviceClass_Keyboard ); + ISP_CHECK_ERR(err) + + + err = ISpDevices_ActivateClass ( kISpDeviceClass_Mouse ); + ISP_CHECK_ERR(err) + */ + + err = ISpElement_NewVirtualFromNeeds( ISP_NUM_NEEDS, + joy->pJoystick.isp_needs, joy->pJoystick.isp_elem, + 0 ); + ISP_CHECK_ERR( err ) + + err = ISpInit( ISP_NUM_NEEDS, joy->pJoystick.isp_needs, joy->pJoystick.isp_elem, + 'freeglut', nil, 0, 128, 0 ); + ISP_CHECK_ERR( err ) + + joy->num_buttons = ISP_NUM_NEEDS - ISP_NUM_AXIS; + joy->num_axes = ISP_NUM_AXIS; + + for( i = 0; i < joy->num_axes; i++ ) + { + joy->dead_band[ i ] = 0; + joy->saturate [ i ] = 1; + joy->center [ i ] = kISpAxisMiddle; + joy->max [ i ] = kISpAxisMaximum; + joy->min [ i ] = kISpAxisMinimum; + } + + joy->error = GL_FALSE; + } + else + joy->num_buttons = joy->num_axes = 0; +} + + +void fgPlatformJoystickInit( SFG_Joystick *fgJoystick[], int ident ) +{ + fgJoystick[ ident ]->id = ident; + snprintf( fgJoystick[ ident ]->pJoystick.fname, sizeof(fgJoystick[ ident ]->pJoystick.fname), "/dev/js%d", ident ); /* FIXME */ + fgJoystick[ ident ]->error = GL_FALSE; +} + + +void fgPlatformJoystickClose ( int ident ) +{ + ISpSuspend( ); + ISpStop( ); + ISpShutdown( ); +} +#endif + +#if TARGET_HOST_MAC_OSX +void fgPlatformJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes ) +{ + int i; + + if ( buttons != NULL ) + { + *buttons = 0; + + for ( i = 0; i < joy->num_buttons; i++ ) + { + IOHIDEventStruct hidEvent; + (*(joy->pJoystick.hidDev))->getElementValue ( joy->pJoystick.hidDev, joy->pJoystick.buttonCookies[i], &hidEvent ); + if ( hidEvent.value ) + *buttons |= 1 << i; + } + } + + if ( axes != NULL ) + { + for ( i = 0; i < joy->num_axes; i++ ) + { + IOHIDEventStruct hidEvent; + (*(joy->pJoystick.hidDev))->getElementValue ( joy->pJoystick.hidDev, joy->pJoystick.axisCookies[i], &hidEvent ); + axes[i] = hidEvent.value; + } + } +} + + +void fgPlatformJoystickOpen( SFG_Joystick* joy ) +{ + IOReturn rv; + SInt32 score; + IOCFPlugInInterface **plugin; + + HRESULT pluginResult; + + CFDictionaryRef props; + CFTypeRef topLevelElement; + + if( joy->id >= numDevices ) + { + fgWarning( "device index out of range in fgJoystickOpen()" ); + return; + } + + /* create device interface */ + rv = IOCreatePlugInInterfaceForService( ioDevices[ joy->id ], + kIOHIDDeviceUserClientTypeID, + kIOCFPlugInInterfaceID, + &plugin, &score ); + + if( rv != kIOReturnSuccess ) + { + fgWarning( "error creating plugin for io device" ); + return; + } + + pluginResult = ( *plugin )->QueryInterface( + plugin, + CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), + &( LPVOID )joy->pJoystick.hidDev + ); + + if( pluginResult != S_OK ) + fgWarning ( "QI-ing IO plugin to HID Device interface failed" ); + + ( *plugin )->Release( plugin ); /* don't leak a ref */ + if( joy->pJoystick.hidDev == NULL ) + return; + + /* store the interface in this instance */ + rv = ( *( joy->pJoystick.hidDev ) )->open( joy->pJoystick.hidDev, 0 ); + if( rv != kIOReturnSuccess ) + { + fgWarning( "error opening device interface"); + return; + } + + props = getCFProperties( ioDevices[ joy->id ] ); + + /* recursively enumerate all the bits */ + CFTypeRef topLevelElement = + CFDictionaryGetValue( props, CFSTR( kIOHIDElementKey ) ); + enumerateElements( topLevelElement ); + + CFRelease( props ); +} + + +void fgPlatformJoystickInit( SFG_Joystick *fgJoystick[], int ident ) +{ + fgJoystick[ ident ]->id = ident; + fgJoystick[ ident ]->error = GL_FALSE; + fgJoystick[ ident ]->num_axes = 0; + fgJoystick[ ident ]->num_buttons = 0; + + if( numDevices < 0 ) + { + /* do first-time init (since we can't over-ride jsInit, hmm */ + numDevices = 0; + + mach_port_t masterPort; + IOReturn rv = IOMasterPort( bootstrap_port, &masterPort ); + if( rv != kIOReturnSuccess ) + { + fgWarning( "error getting master Mach port" ); + return; + } + fghJoystickFindDevices( masterPort ); + } + + if ( ident >= numDevices ) + { + fgJoystick[ ident ]->error = GL_TRUE; + return; + } + + /* get the name now too */ + CFDictionaryRef properties = getCFProperties( ioDevices[ ident ] ); + CFTypeRef ref = CFDictionaryGetValue( properties, + CFSTR( kIOHIDProductKey ) ); + if (!ref) + ref = CFDictionaryGetValue(properties, CFSTR( "USB Product Name" ) ); + + if( !ref || + !CFStringGetCString( ( CFStringRef )ref, name, 128, + CFStringGetSystemEncoding( ) ) ) + { + fgWarning( "error getting device name" ); + name[ 0 ] = '\0'; + } +} + + +void fgPlatformJoystickClose ( int ident ) +{ + ( *( fgJoystick[ ident ]->pJoystick.hidDev ) )-> + close( fgJoystick[ ident ]->pJoystick.hidDev ); +} +#endif + + + + +static void fghJoystickOpen( SFG_Joystick* joy ) +{ + /* + * Default values (for no joystick -- each conditional will reset the + * error flag) + */ + joy->error = TRUE; + joy->num_axes = joy->num_buttons = 0; + joy->name[ 0 ] = '\0'; + + fgPlatformJoystickOpen ( joy ); + +} + +/* + * This function replaces the constructor method in the JS library. + */ +static void fghJoystickInit( int ident ) +{ + if( ident >= MAX_NUM_JOYSTICKS ) + fgError( "Too large a joystick number: %d", ident ); + + if( fgJoystick[ ident ] ) + fgError( "illegal attempt to initialize joystick device again" ); + + fgJoystick[ ident ] = + ( SFG_Joystick * )calloc( sizeof( SFG_Joystick ), 1 ); + + /* Set defaults */ + fgJoystick[ ident ]->num_axes = fgJoystick[ ident ]->num_buttons = 0; + fgJoystick[ ident ]->error = GL_TRUE; + + fgPlatformJoystickInit( fgJoystick, ident ); + + fghJoystickOpen( fgJoystick[ ident ] ); +} + +/* + * Try initializing all the joysticks (well, both of them) + */ +void fgInitialiseJoysticks ( void ) +{ + if( !fgState.JoysticksInitialised ) + { + int ident ; + for ( ident = 0; ident < MAX_NUM_JOYSTICKS; ident++ ) + fghJoystickInit( ident ); + + fgState.JoysticksInitialised = GL_TRUE; + } +} + + +void fgJoystickClose( void ) +{ + int ident ; + for( ident = 0; ident < MAX_NUM_JOYSTICKS; ident++ ) + { + if( fgJoystick[ ident ] ) + { + fgPlatformJoystickClose ( ident ); + + free( fgJoystick[ ident ] ); + fgJoystick[ ident ] = NULL; + /* show joystick has been deinitialized */ + } + } +} + +/* + * Polls the joystick and executes the joystick callback hooked to the + * window specified in the function's parameter: + */ +void fgJoystickPollWindow( SFG_Window* window ) +{ + float axes[ _JS_MAX_AXES ]; + int buttons; + int ident; + + freeglut_return_if_fail( window ); + freeglut_return_if_fail( FETCH_WCB( *window, Joystick ) ); + + for( ident = 0; ident < MAX_NUM_JOYSTICKS; ident++ ) + { + if( fgJoystick[ident] ) + { + fghJoystickRead( fgJoystick[ident], &buttons, axes ); + + if( !fgJoystick[ident]->error ) + INVOKE_WCB( *window, Joystick, + ( buttons, + (int) ( axes[ 0 ] * 1000.0f ), + (int) ( axes[ 1 ] * 1000.0f ), + (int) ( axes[ 2 ] * 1000.0f ) ) + ); + } + } +} + +/* + * Implementation for glutDeviceGet(GLUT_HAS_JOYSTICK) + */ +int fgJoystickDetect( void ) +{ + int ident; + + fgInitialiseJoysticks (); + + if ( !fgState.JoysticksInitialised ) + return 0; + + for( ident=0; identerror ) + return 1; + + return 0; +} + +/* + * Joystick information, setup and execution functions + */ + +/* + * Forces the joystick callback to be executed + */ +void FGAPIENTRY glutForceJoystickFunc( void ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutForceJoystickFunc" ); +#if !defined(_WIN32_WCE) + freeglut_return_if_fail( fgStructure.CurrentWindow != NULL ); + freeglut_return_if_fail( FETCH_WCB( *( fgStructure.CurrentWindow ), Joystick ) ); + fgJoystickPollWindow( fgStructure.CurrentWindow ); +#endif /* !defined(_WIN32_WCE) */ +} +int glutJoystickGetNumAxes( int ident ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetNumAxes" ); + return fgJoystick[ ident ]->num_axes; +} +int glutJoystickGetNumButtons( int ident ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetNumButtons" ); + return fgJoystick[ ident ]->num_buttons; +} +int glutJoystickNotWorking( int ident ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickNotWorking" ); + return fgJoystick[ ident ]->error; +} + +float glutJoystickGetDeadBand( int ident, int axis ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetDeadBand" ); + return fgJoystick[ ident ]->dead_band [ axis ]; +} +void glutJoystickSetDeadBand( int ident, int axis, float db ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickSetDeadBand" ); + fgJoystick[ ident ]->dead_band[ axis ] = db; +} + +float glutJoystickGetSaturation( int ident, int axis ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetSaturation" ); + return fgJoystick[ ident ]->saturate[ axis ]; +} +void glutJoystickSetSaturation( int ident, int axis, float st ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickSetSaturation" ); + fgJoystick[ ident ]->saturate [ axis ] = st; +} + +void glutJoystickSetMinRange( int ident, float *axes ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickSetMinRange" ); + memcpy( fgJoystick[ ident ]->min, axes, + fgJoystick[ ident ]->num_axes * sizeof( float ) ); +} +void glutJoystickSetMaxRange( int ident, float *axes ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickSetMaxRange" ); + memcpy( fgJoystick[ ident ]->max, axes, + fgJoystick[ ident ]->num_axes * sizeof( float ) ); +} +void glutJoystickSetCenter( int ident, float *axes ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickSetCenter" ); + memcpy( fgJoystick[ ident ]->center, axes, + fgJoystick[ ident ]->num_axes * sizeof( float ) ); +} + +void glutJoystickGetMinRange( int ident, float *axes ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetMinRange" ); + memcpy( axes, fgJoystick[ ident ]->min, + fgJoystick[ ident ]->num_axes * sizeof( float ) ); +} +void glutJoystickGetMaxRange( int ident, float *axes ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetMaxRange" ); + memcpy( axes, fgJoystick[ ident ]->max, + fgJoystick[ ident ]->num_axes * sizeof( float ) ); +} +void glutJoystickGetCenter( int ident, float *axes ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetCenter" ); + memcpy( axes, fgJoystick[ ident ]->center, + fgJoystick[ ident ]->num_axes * sizeof( float ) ); +} + +/*** END OF FILE ***/ diff --git a/src/fg_main.c b/src/fg_main.c new file mode 100644 index 0000000..ff01110 --- /dev/null +++ b/src/fg_main.c @@ -0,0 +1,542 @@ +/* + * fg_main.c + * + * The windows message processing methods. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Fri Dec 3 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" +#include +#include + +/* + * Try to get the maximum value allowed for ints, falling back to the minimum + * guaranteed by ISO C99 if there is no suitable header. + */ +#ifdef HAVE_LIMITS_H +# include +#endif +#ifndef INT_MAX +# define INT_MAX 32767 +#endif + +#ifndef MIN +# define MIN(a,b) (((a)<(b)) ? (a) : (b)) +#endif + +extern void fgProcessWork ( SFG_Window *window ); +extern fg_time_t fgPlatformSystemTime ( void ); +extern void fgPlatformSleepForEvents( fg_time_t msec ); +extern void fgPlatformProcessSingleEvent ( void ); +extern void fgPlatformMainLoopPreliminaryWork ( void ); + +extern void fgPlatformInitWork(SFG_Window* window); +extern void fgPlatformPosResZordWork(SFG_Window* window, unsigned int workMask); +extern void fgPlatformVisibilityWork(SFG_Window* window); + + +/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ + +void fghOnReshapeNotify(SFG_Window *window, int width, int height, GLboolean forceNotify) +{ + GLboolean notify = GL_FALSE; + + if( width != window->State.Width || + height != window->State.Height ) + { + window->State.Width = width; + window->State.Height = height; + + notify = GL_TRUE; + } + + if (notify || forceNotify) + { + SFG_Window *saved_window = fgStructure.CurrentWindow; + + INVOKE_WCB( *window, Reshape, ( width, height ) ); + + /* + * Force a window redraw. In Windows at least this is only a partial + * solution: if the window is increasing in size in either dimension, + * the already-drawn part does not get drawn again and things look funny. + * But without this we get this bad behaviour whenever we resize the + * window. + * DN: Hmm.. the above sounds like a concern only in single buffered mode... + */ + window->State.WorkMask |= GLUT_DISPLAY_WORK; + if( window->IsMenu ) + fgSetWindow( saved_window ); + } +} + +void fghOnPositionNotify(SFG_Window *window, int x, int y, GLboolean forceNotify) +{ + GLboolean notify = GL_FALSE; + + if( x != window->State.Xpos || + y != window->State.Ypos ) + { + window->State.Xpos = x; + window->State.Ypos = y; + + notify = GL_TRUE; + } + + if (notify || forceNotify) + { + SFG_Window *saved_window = fgStructure.CurrentWindow; + INVOKE_WCB( *window, Position, ( x, y ) ); + fgSetWindow( saved_window ); + } +} + +/* + * Calls a window's redraw method. This is used when + * a redraw is forced by the incoming window messages, + * or if a redisplay is otherwise pending. + * this is lean and mean without checks as it is + * currently only called from fghcbDisplayWindow which + * only calls this if the window is visible and needs + * a redisplay. + * Note that the fgSetWindow call on Windows makes the + * right device context current on windows, allowing + * direct drawing without BeginPaint/EndPaint in the + * WM_PAINT handler. + */ +void fghRedrawWindow ( SFG_Window *window ) +{ + SFG_Window *current_window = fgStructure.CurrentWindow; + + fgSetWindow( window ); + INVOKE_WCB( *window, Display, ( ) ); + + fgSetWindow( current_window ); +} + +void fghRedrawWindowAndChildren ( SFG_Window *window ) +{ + SFG_Window* child; + + fghRedrawWindow(window); + + for( child = ( SFG_Window * )window->Children.First; + child; + child = ( SFG_Window * )child->Node.Next ) + { + fghRedrawWindowAndChildren(child); + } +} + + +static void fghcbProcessWork( SFG_Window *window, + SFG_Enumerator *enumerator ) +{ + if( window->State.WorkMask ) + fgProcessWork ( window ); + + fgEnumSubWindows( window, fghcbProcessWork, enumerator ); +} + +/* + * Make all windows process their work list + */ +static void fghProcessWork( void ) +{ + SFG_Enumerator enumerator; + + enumerator.found = GL_FALSE; + enumerator.data = NULL; + + fgEnumWindows( fghcbProcessWork, &enumerator ); +} + +/* + * Window enumerator callback to check for the joystick polling code + */ +static void fghcbCheckJoystickPolls( SFG_Window *window, + SFG_Enumerator *enumerator ) +{ + fg_time_t checkTime; + + if (window->State.JoystickPollRate > 0 && FETCH_WCB( *window, Joystick )) + { + /* This window has a joystick to be polled (if pollrate <= 0, user needs to poll manually with glutForceJoystickFunc */ + checkTime= fgElapsedTime( ); + + if( window->State.JoystickLastPoll + window->State.JoystickPollRate <= + checkTime ) + { +#if !defined(_WIN32_WCE) + fgJoystickPollWindow( window ); +#endif /* !defined(_WIN32_WCE) */ + window->State.JoystickLastPoll = checkTime; + } + } + + fgEnumSubWindows( window, fghcbCheckJoystickPolls, enumerator ); +} + +/* + * Check all windows for joystick polling + * + * The real way to do this is to make use of the glutTimer() API + * to more cleanly re-implement the joystick API. Then, this code + * and all other "joystick timer" code can be yanked. + */ +static void fghCheckJoystickPolls( void ) +{ + SFG_Enumerator enumerator; + + enumerator.found = GL_FALSE; + enumerator.data = NULL; + + fgEnumWindows( fghcbCheckJoystickPolls, &enumerator ); +} + +/* + * Check the global timers + */ +static void fghCheckTimers( void ) +{ + fg_time_t checkTime = fgElapsedTime( ); + + while( fgState.Timers.First ) + { + SFG_Timer *timer = fgState.Timers.First; + + if( timer->TriggerTime > checkTime ) + /* Timers are sorted by triggerTime */ + break; + + fgListRemove( &fgState.Timers, &timer->Node ); + fgListAppend( &fgState.FreeTimers, &timer->Node ); + + timer->Callback( timer->ID, timer->CallbackData ); + } +} + + +/* Platform-dependent time in milliseconds, as an unsigned 64-bit integer. + * This doesn't overflow in any reasonable time, so no need to worry about + * that. The GLUT API return value will however overflow after 49.7 days, + * which means you will still get in trouble when running the + * application for more than 49.7 days. + */ +fg_time_t fgSystemTime(void) +{ + return fgPlatformSystemTime(); +} + +/* + * Elapsed Time + */ +fg_time_t fgElapsedTime( void ) +{ + return fgSystemTime() - fgState.Time; +} + +/* + * Error Messages. + */ +void fgError( const char *fmt, ... ) +{ + va_list ap; + + if (fgState.ErrorFunc) { + + va_start( ap, fmt ); + + /* call user set error handler here */ + fgState.ErrorFunc(fmt, ap, fgState.ErrorFuncData); + + va_end( ap ); + + } else { +#ifdef FREEGLUT_PRINT_ERRORS + va_start( ap, fmt ); + + fprintf( stderr, "freeglut "); + if( fgState.ProgramName ) + fprintf( stderr, "(%s): ", fgState.ProgramName ); + vfprintf( stderr, fmt, ap ); + fprintf( stderr, "\n" ); + + va_end( ap ); +#endif + + if ( fgState.Initialised ) + fgDeinitialize (); + + exit( 1 ); + } +} + +void fgWarning( const char *fmt, ... ) +{ + va_list ap; + + if (fgState.WarningFunc) { + + va_start( ap, fmt ); + + /* call user set warning handler here */ + fgState.WarningFunc(fmt, ap, fgState.WarningFuncData); + + va_end( ap ); + + } else { +#ifdef FREEGLUT_PRINT_WARNINGS + va_start( ap, fmt ); + + fprintf( stderr, "freeglut "); + if( fgState.ProgramName ) + fprintf( stderr, "(%s): ", fgState.ProgramName ); + vfprintf( stderr, fmt, ap ); + fprintf( stderr, "\n" ); + + va_end( ap ); +#endif + } +} + + +/* + * Indicates whether work is pending for ANY window. + * + * The current mechanism is to walk all of the windows and ask if + * work is pending. We have a short-circuit early return if we find any. + */ +static void fghHavePendingWorkCallback( SFG_Window* w, SFG_Enumerator* e) +{ + if( w->State.WorkMask ) + { + e->found = GL_TRUE; + e->data = w; + return; + } + fgEnumSubWindows( w, fghHavePendingWorkCallback, e ); +} +static int fghHavePendingWork (void) +{ + SFG_Enumerator enumerator; + + enumerator.found = GL_FALSE; + enumerator.data = NULL; + fgEnumWindows( fghHavePendingWorkCallback, &enumerator ); + return !!enumerator.data; +} + +/* + * Returns the number of GLUT ticks (milliseconds) till the next timer event. + */ +static fg_time_t fghNextTimer( void ) +{ + fg_time_t currentTime; + SFG_Timer *timer = fgState.Timers.First; /* timers are sorted by trigger time, so only have to check the first */ + + if( !timer ) + return INT_MAX; + + currentTime = fgElapsedTime(); + if( timer->TriggerTime < currentTime ) + return 0; + else + return timer->TriggerTime - currentTime; +} + +static void fghSleepForEvents( void ) +{ + fg_time_t msec; + + if( fghHavePendingWork( ) ) + return; + + msec = fghNextTimer( ); + /* XXX Should use GLUT timers for joysticks... */ + /* XXX Dumb; forces granularity to .01sec */ + if( fgState.NumActiveJoysticks>0 && ( msec > 10 ) ) + msec = 10; + + fgPlatformSleepForEvents ( msec ); +} + + +/* Step through the work list */ +void fgProcessWork(SFG_Window *window) +{ + unsigned int workMask = window->State.WorkMask; + /* Now clear it so that any callback generated by the actions below can set work again */ + window->State.WorkMask = 0; + + if (workMask&~GLUT_DISPLAY_WORK) /* Display work is the common case, skip all the below at once */ + { + if (workMask & GLUT_INIT_WORK) + { + /* This is before the first display callback: if needed for the platform, + * call a few callbacks to inform user of window size, position, etc + */ + fgPlatformInitWork(window); + + /* Call init context callback */ + INVOKE_WCB( *window, InitContext, ( ) ); + + /* Lastly, check if we have a display callback, error out if not + * This is the right place to do it, as the redisplay will be + * next right after we exit this function, so there is no more + * opportunity for the user to register a callback for this window. + */ + if (!FETCH_WCB(*window, Display)) + fgError ( "ERROR: No display callback registered for window %d\n", window->ID ); + } + + /* On windows we can position, resize and change z order at the same time */ + if (workMask & (GLUT_POSITION_WORK|GLUT_SIZE_WORK|GLUT_ZORDER_WORK|GLUT_FULL_SCREEN_WORK)) + { + fgPlatformPosResZordWork(window,workMask); + } + + if (workMask & GLUT_VISIBILITY_WORK) + { + fgPlatformVisibilityWork(window); + } + } + + /* check window state's workmask as well as some of the above callbacks might have generated redisplay requests. We can deal with those right now instead of wait for the next mainloop iteration. */ + if (workMask & GLUT_DISPLAY_WORK || window->State.WorkMask & GLUT_DISPLAY_WORK) + { + if( window->State.Visible ) + { + /* Strip out display work from the work list */ + /* NB: do this before the display callback is called as user might call postredisplay in his display callback */ + window->State.WorkMask &= ~GLUT_DISPLAY_WORK; + + fghRedrawWindow ( window ); + } + } +} + + +/* -- INTERFACE FUNCTIONS -------------------------------------------------- */ + +/* + * Executes a single iteration in the freeglut processing loop. + */ +void FGAPIENTRY glutMainLoopEvent( void ) +{ + /* Process input */ + fgPlatformProcessSingleEvent (); + + if( fgState.Timers.First ) + fghCheckTimers( ); + if (fgState.NumActiveJoysticks>0) /* If zero, don't poll joysticks */ + fghCheckJoystickPolls( ); + + /* Perform work on the window (position, reshape, display, etc) */ + fghProcessWork( ); + + /* Check OpenGL error state if requested. + * Don't call if no more open windows (can happen if user closes window from + * title bar), would lead to infinite error loop in glutReportErrors + */ + if (fgState.GLDebugSwitch && fgStructure.CurrentWindow) + glutReportErrors( ); + + fgCloseWindows( ); +} + +/* + * Enters the freeglut processing loop. + * Stays until the "ExecState" changes to "GLUT_EXEC_STATE_STOP". + */ +void FGAPIENTRY glutMainLoop( void ) +{ + int action; + + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMainLoop" ); + + if (!fgStructure.Windows.First) + fgError(" ERROR: glutMainLoop called with no windows created."); + + fgPlatformMainLoopPreliminaryWork (); + + fgState.ExecState = GLUT_EXEC_STATE_RUNNING ; + for(;;) + { + SFG_Window *window; + + glutMainLoopEvent( ); + if( fgState.ExecState != GLUT_EXEC_STATE_RUNNING ) + break; + /* + * Step through the list of windows, seeing if there are any + * that are not menus + */ + for( window = ( SFG_Window * )fgStructure.Windows.First; + window; + window = ( SFG_Window * )window->Node.Next ) + if ( ! ( window->IsMenu ) ) + break; + + if( ! window ) + fgState.ExecState = GLUT_EXEC_STATE_STOP; + else + { + if( fgState.IdleCallback ) + { + if( fgStructure.CurrentWindow && + fgStructure.CurrentWindow->IsMenu ) + /* fail safe */ + fgSetWindow( window ); + fgState.IdleCallback( fgState.IdleCallbackData ); + } + else + fghSleepForEvents( ); + } + } + + /* + * When this loop terminates, destroy the display, state and structure + * of a freeglut session, so that another glutInit() call can happen + * + * Save the "ActionOnWindowClose" because "fgDeinitialize" resets it. + */ + action = fgState.ActionOnWindowClose; + fgDeinitialize( ); + if( action == GLUT_ACTION_EXIT ) + exit( 0 ); +} + +/* + * Leaves the freeglut processing loop. + */ +void FGAPIENTRY glutLeaveMainLoop( void ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutLeaveMainLoop" ); + fgState.ExecState = GLUT_EXEC_STATE_STOP ; +} + + + +/*** END OF FILE ***/ diff --git a/src/fg_menu.c b/src/fg_menu.c new file mode 100644 index 0000000..53112dc --- /dev/null +++ b/src/fg_menu.c @@ -0,0 +1,1075 @@ +/* + * fg_menu.c + * + * Pull-down menu creation and handling. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Thu Dec 16 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#define FREEGLUT_BUILDING_LIB +#include +#include "fg_internal.h" + + +/* -- DEFINITIONS ---------------------------------------------------------- */ + +/* + * FREEGLUT_MENU_FONT can be any freeglut bitmapped font. + * (Stroked fonts would not be out of the question, but we'd need to alter + * code, since GLUT (hence freeglut) does not quite unify stroked and + * bitmapped font handling.) + * Old UNIX/X11 GLUT (BSD, UNIX, IRIX, LINUX, HPUX, ...) used a system + * font best approximated by an 18-pixel HELVETICA, I think. MS-WINDOWS + * GLUT used something closest to the 8x13 fixed-width font. (Old + * GLUT apparently uses host-system menus rather than building its own. + * freeglut is building its own menus from scratch.) + * + * FREEGLUT_MENUENTRY_HEIGHT gives the height of ONE menu box. This should + * be the distances between two adjacent menu entries. It should scale + * automatically with the font choice, so you needn't alter it---unless you + * use a stroked font. + * + * FREEGLUT_MENU_BORDER says how many pixels to allow around the edge of a + * menu. (It also seems to be the same as the number of pixels used as + * a border around *items* to separate them from neighbors. John says + * that that wasn't the original intent...if not, perhaps we need another + * symbolic constant, FREEGLUT_MENU_ITEM_BORDER, or such.) + */ +/* See platform-specific header files for menu font and color definitions */ + +#define FREEGLUT_MENUENTRY_HEIGHT(font) (glutBitmapHeight(font) + \ + FREEGLUT_MENU_BORDER) +#define FREEGLUT_MENU_BORDER 2 + + +/* + * These variables are for rendering the freeglut menu items. + * + * The choices are fore- and background, with and without h for Highlighting. + * Old GLUT appeared to be system-dependent for its colors (sigh) so we are + * too. These variables should be stuffed into global state and initialized + * via the glutInit*() system. + */ +static float menu_pen_fore [4] = FREEGLUT_MENU_PEN_FORE_COLORS ; +static float menu_pen_back [4] = FREEGLUT_MENU_PEN_BACK_COLORS ; +static float menu_pen_hfore [4] = FREEGLUT_MENU_PEN_HFORE_COLORS; +static float menu_pen_hback [4] = FREEGLUT_MENU_PEN_HBACK_COLORS; + + +extern GLvoid fgPlatformGetGameModeVMaxExtent( SFG_Window* window, int* x, int* y ); +extern void fghPlatformGetCursorPos(const SFG_Window *window, GLboolean client, SFG_XYUse *mouse_pos); +extern SFG_Font* fghFontByID( void* font ); +extern void fgPlatformHideWindow( SFG_Window* window ); + +/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ + +/* + * Private function to find a menu entry by index + */ +static SFG_MenuEntry *fghFindMenuEntry( SFG_Menu* menu, int index ) +{ + SFG_MenuEntry *entry; + int i = 1; + + for( entry = (SFG_MenuEntry *)menu->Entries.First; + entry; + entry = (SFG_MenuEntry *)entry->Node.Next ) + { + if( i == index ) + break; + ++i; + } + + return entry; +} + +/* + * Deactivates a menu pointed by the function argument. + */ +static void fghDeactivateSubMenu( SFG_MenuEntry *menuEntry ) +{ + SFG_MenuEntry *subMenuIter; + /* Hide the present menu's window */ + fgPlatformHideWindow( menuEntry->SubMenu->Window ); + + /* Forget about having that menu active anymore, now: */ + menuEntry->SubMenu->Window->ActiveMenu = NULL; + menuEntry->SubMenu->IsActive = GL_FALSE; + menuEntry->SubMenu->ActiveEntry = NULL; + + /* Hide all submenu windows, and the root menu's window. */ + for ( subMenuIter = (SFG_MenuEntry *)menuEntry->SubMenu->Entries.First; + subMenuIter; + subMenuIter = (SFG_MenuEntry *)subMenuIter->Node.Next ) + { + subMenuIter->IsActive = GL_FALSE; + + /* Is that an active submenu by any case? */ + if( subMenuIter->SubMenu ) + fghDeactivateSubMenu( subMenuIter ); + } +} + +/* + * Private function to get the virtual maximum screen extent + */ +static GLvoid fghGetVMaxExtent( SFG_Window* window, int* x, int* y ) +{ + if( fgStructure.GameModeWindow ) + fgPlatformGetGameModeVMaxExtent ( window, x, y ); + else + { + *x = fgDisplay.ScreenWidth; + *y = fgDisplay.ScreenHeight; + } +} + +/* + * Private function to check for the current menu/sub menu activity state + */ +static GLboolean fghCheckMenuStatus( SFG_Menu* menu ) +{ + SFG_MenuEntry* menuEntry; + int x, y; + + /* First of all check any of the active sub menus... */ + for( menuEntry = (SFG_MenuEntry *)menu->Entries.First; + menuEntry; + menuEntry = (SFG_MenuEntry *)menuEntry->Node.Next ) + { + if( menuEntry->SubMenu && menuEntry->IsActive ) + { + /* + * OK, have the sub-menu checked, too. If it returns GL_TRUE, it + * will mean that it caught the mouse cursor and we do not need + * to regenerate the activity list, and so our parents do... + */ + GLboolean return_status; + + menuEntry->SubMenu->Window->State.MouseX = + menu->Window->State.MouseX + menu->X - menuEntry->SubMenu->X; + menuEntry->SubMenu->Window->State.MouseY = + menu->Window->State.MouseY + menu->Y - menuEntry->SubMenu->Y; + return_status = fghCheckMenuStatus( menuEntry->SubMenu ); + + if ( return_status ) + return GL_TRUE; + } + } + + /* That much about our sub menus, let's get to checking the current menu: */ + x = menu->Window->State.MouseX; + y = menu->Window->State.MouseY; + + /* Check if the mouse cursor is contained within the current menu box */ + if( ( x >= FREEGLUT_MENU_BORDER ) && + ( x < menu->Width - FREEGLUT_MENU_BORDER ) && + ( y >= FREEGLUT_MENU_BORDER ) && + ( y < menu->Height - FREEGLUT_MENU_BORDER ) ) + { + int menuID = ( y - FREEGLUT_MENU_BORDER ) / FREEGLUT_MENUENTRY_HEIGHT(menu->Font); + + /* The mouse cursor is somewhere over our box, check it out. */ + menuEntry = fghFindMenuEntry( menu, menuID + 1 ); + FREEGLUT_INTERNAL_ERROR_EXIT( menuEntry, "Cannot find menu entry", + "fghCheckMenuStatus" ); + + menuEntry->IsActive = GL_TRUE; + menuEntry->Ordinal = menuID; + + /* + * If this is not the same as the last active menu entry, deactivate + * the previous entry. Specifically, if the previous active entry + * was a submenu then deactivate it. + */ + if( menu->ActiveEntry && ( menuEntry != menu->ActiveEntry ) ) + if( menu->ActiveEntry->SubMenu ) + fghDeactivateSubMenu( menu->ActiveEntry ); + + if( menuEntry != menu->ActiveEntry ) + { + menu->Window->State.WorkMask |= GLUT_DISPLAY_WORK; + if( menu->ActiveEntry ) + menu->ActiveEntry->IsActive = GL_FALSE; + } + + menu->ActiveEntry = menuEntry; + menu->IsActive = GL_TRUE; + + /* + * OK, we have marked that entry as active, but it would be also + * nice to have its contents updated, in case it's a sub menu. + * Also, ignore the return value of the check function: + */ + if( menuEntry->SubMenu ) + { + if ( ! menuEntry->SubMenu->IsActive ) + { + int max_x, max_y; + SFG_Window *current_window = fgStructure.CurrentWindow; + + /* Set up the initial menu position now... */ + menuEntry->SubMenu->IsActive = GL_TRUE; + + /* Set up the initial submenu position now: */ + fghGetVMaxExtent(menu->ParentWindow, &max_x, &max_y); + menuEntry->SubMenu->X = menu->X + menu->Width; + menuEntry->SubMenu->Y = menu->Y + + menuEntry->Ordinal * FREEGLUT_MENUENTRY_HEIGHT(menu->Font); + + if( menuEntry->SubMenu->X + menuEntry->SubMenu->Width > max_x ) + menuEntry->SubMenu->X = menu->X - menuEntry->SubMenu->Width; + + if( menuEntry->SubMenu->Y + menuEntry->SubMenu->Height > max_y ) + { + menuEntry->SubMenu->Y -= ( menuEntry->SubMenu->Height - + FREEGLUT_MENUENTRY_HEIGHT(menu->Font) - + 2 * FREEGLUT_MENU_BORDER ); + if( menuEntry->SubMenu->Y < 0 ) + menuEntry->SubMenu->Y = 0; + } + + fgSetWindow( menuEntry->SubMenu->Window ); + glutPositionWindow( menuEntry->SubMenu->X, + menuEntry->SubMenu->Y ); + glutReshapeWindow( menuEntry->SubMenu->Width, + menuEntry->SubMenu->Height ); + glutPopWindow( ); + glutShowWindow( ); + menuEntry->SubMenu->Window->ActiveMenu = menuEntry->SubMenu; + fgSetWindow( current_window ); + menuEntry->SubMenu->Window->State.MouseX = + x + menu->X - menuEntry->SubMenu->X; + menuEntry->SubMenu->Window->State.MouseY = + y + menu->Y - menuEntry->SubMenu->Y; + fghCheckMenuStatus( menuEntry->SubMenu ); + } + + /* Activate it because its parent entry is active */ + menuEntry->SubMenu->IsActive = GL_TRUE; + } + + /* Report back that we have caught the menu cursor */ + return GL_TRUE; + } + + /* Looks like the menu cursor is somewhere else... */ + if( menu->ActiveEntry && menu->ActiveEntry->IsActive && + ( !menu->ActiveEntry->SubMenu || + !menu->ActiveEntry->SubMenu->IsActive ) ) + { + menu->Window->State.WorkMask |= GLUT_DISPLAY_WORK; + menu->ActiveEntry->IsActive = GL_FALSE; + menu->ActiveEntry = NULL; + } + + return GL_FALSE; +} + +/* + * Displays a menu box and all of its submenus (if they are active) + */ +static void fghDisplayMenuBox( SFG_Menu* menu ) +{ + SFG_MenuEntry *menuEntry; + int i; + int border = FREEGLUT_MENU_BORDER; + + /* + * Have the menu box drawn first. The +- values are + * here just to make it more nice-looking... + */ + /* a non-black dark version of the below. */ + glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); + glBegin( GL_QUAD_STRIP ); + glVertex2i( menu->Width , 0 ); + glVertex2i( menu->Width - border, border); + glVertex2i( 0 , 0 ); + glVertex2i( border, border); + glVertex2i( 0 , menu->Height ); + glVertex2i( border, menu->Height - border); + glEnd( ); + + /* a non-black dark version of the below. */ + glColor4f( 0.5f, 0.5f, 0.5f, 1.0f ); + glBegin( GL_QUAD_STRIP ); + glVertex2i( 0 , menu->Height ); + glVertex2i( border, menu->Height - border); + glVertex2i( menu->Width , menu->Height ); + glVertex2i( menu->Width - border, menu->Height - border); + glVertex2i( menu->Width , 0 ); + glVertex2i( menu->Width - border, border); + glEnd( ); + + glColor4fv( menu_pen_back ); + glBegin( GL_QUADS ); + glVertex2i( border, border); + glVertex2i( menu->Width - border, border); + glVertex2i( menu->Width - border, menu->Height - border); + glVertex2i( border, menu->Height - border); + glEnd( ); + + /* Check if any of the submenus is currently active... */ + for( menuEntry = (SFG_MenuEntry *)menu->Entries.First; + menuEntry; + menuEntry = (SFG_MenuEntry *)menuEntry->Node.Next ) + { + /* Has the menu been marked as active, maybe? */ + if( menuEntry->IsActive ) + { + /* + * That's truly right, and we need to have it highlighted. + * There is an assumption that mouse cursor didn't move + * since the last check of menu activity state: + */ + int menuID = menuEntry->Ordinal; + + /* So have the highlight drawn... */ + glColor4fv( menu_pen_hback ); + glBegin( GL_QUADS ); + glVertex2i( border, + (menuID + 0)*FREEGLUT_MENUENTRY_HEIGHT(menu->Font) + border ); + glVertex2i( menu->Width - border, + (menuID + 0)*FREEGLUT_MENUENTRY_HEIGHT(menu->Font) + border ); + glVertex2i( menu->Width - border, + (menuID + 1)*FREEGLUT_MENUENTRY_HEIGHT(menu->Font) + border ); + glVertex2i( border, + (menuID + 1)*FREEGLUT_MENUENTRY_HEIGHT(menu->Font) + border ); + glEnd( ); + } + } + + /* Print the menu entries now... */ + + glColor4fv( menu_pen_fore ); + + for( menuEntry = (SFG_MenuEntry *)menu->Entries.First, i = 0; + menuEntry; + menuEntry = (SFG_MenuEntry *)menuEntry->Node.Next, ++i ) + { + /* If the menu entry is active, set the color to white */ + if( menuEntry->IsActive ) + glColor4fv( menu_pen_hfore ); + + /* Move the raster into position... */ + /* Try to center the text - JCJ 31 July 2003*/ + glRasterPos2i( + 2 * border, + ( i + 1 )*FREEGLUT_MENUENTRY_HEIGHT(menu->Font) - + ( int )( FREEGLUT_MENUENTRY_HEIGHT(menu->Font)*0.3 - border ) + ); + + /* Have the label drawn, character after character: */ + glutBitmapString( menu->Font, + (unsigned char *)menuEntry->Text); + + /* If it's a submenu, draw a right arrow */ + if( menuEntry->SubMenu ) + { + int width = glutBitmapWidth( menu->Font, '_' ); + int x_base = menu->Width - 2 - width; + int y_base = i*FREEGLUT_MENUENTRY_HEIGHT(menu->Font) + border; + glBegin( GL_TRIANGLES ); + glVertex2i( x_base, y_base + 2*border); + glVertex2i( menu->Width - 2, y_base + + ( FREEGLUT_MENUENTRY_HEIGHT(menu->Font) + border) / 2 ); + glVertex2i( x_base, y_base + FREEGLUT_MENUENTRY_HEIGHT(menu->Font) - border ); + glEnd( ); + } + + /* If the menu entry is active, reset the color */ + if( menuEntry->IsActive ) + glColor4fv( menu_pen_fore ); + } +} + +/* + * Private static function to set the parent window of a submenu and all + * of its submenus. + */ +static void fghSetMenuParentWindow( SFG_Window *window, SFG_Menu *menu ) +{ + SFG_MenuEntry *menuEntry; + + menu->ParentWindow = window; + + for( menuEntry = ( SFG_MenuEntry * )menu->Entries.First; + menuEntry; + menuEntry = ( SFG_MenuEntry * )menuEntry->Node.Next ) + if( menuEntry->SubMenu ) + fghSetMenuParentWindow( window, menuEntry->SubMenu ); +} + + +/* + * Displays the currently active menu for the current window + */ +void fgDisplayMenu( void ) +{ + SFG_Window* window = fgStructure.CurrentWindow; + SFG_Menu* menu = NULL; + + FREEGLUT_INTERNAL_ERROR_EXIT ( fgStructure.CurrentWindow, "Displaying menu in nonexistent window", + "fgDisplayMenu" ); + + /* Check if there is an active menu attached to this window... */ + menu = window->ActiveMenu; + freeglut_return_if_fail( menu ); + + fgSetWindow( menu->Window ); + + glPushAttrib( GL_DEPTH_BUFFER_BIT | GL_TEXTURE_BIT | GL_LIGHTING_BIT | + GL_POLYGON_BIT ); + + glDisable( GL_DEPTH_TEST ); + glDisable( GL_TEXTURE_2D ); + glDisable( GL_LIGHTING ); + glDisable( GL_CULL_FACE ); + + glMatrixMode( GL_PROJECTION ); + glPushMatrix( ); + glLoadIdentity( ); + glOrtho( + 0, glutGet( GLUT_WINDOW_WIDTH ), + glutGet( GLUT_WINDOW_HEIGHT ), 0, + -1, 1 + ); + + glMatrixMode( GL_MODELVIEW ); + glPushMatrix( ); + glLoadIdentity( ); + + fghDisplayMenuBox( menu ); + + glPopAttrib( ); + + glMatrixMode( GL_PROJECTION ); + glPopMatrix( ); + glMatrixMode( GL_MODELVIEW ); + glPopMatrix( ); + + glutSwapBuffers( ); + + fgSetWindow ( window ); +} + +/* + * Activates a menu pointed by the function argument + */ +static void fghActivateMenu( SFG_Window* window, int button ) +{ + int max_x, max_y; + SFG_XYUse mouse_pos; + + /* We'll be referencing this menu a lot, so remember its address: */ + SFG_Menu* menu = window->Menu[ button ]; + SFG_Window* current_window = fgStructure.CurrentWindow; + + /* If the menu is already active in another window, deactivate it (and any submenus) there */ + if ( menu->ParentWindow ) + fgDeactivateMenu(menu->ParentWindow); + + /* Mark the menu as active, so that it gets displayed: */ + window->ActiveMenu = menu; + menu->IsActive = GL_TRUE; + fghSetMenuParentWindow ( window, menu ); + fgState.ActiveMenus++; + + /* Set up the initial menu position now: */ + fghGetVMaxExtent(menu->ParentWindow, &max_x, &max_y); + fgSetWindow( window ); + /* get mouse position on screen (window->State.MouseX and window->State.MouseY + * are relative to client area origin), and not easy to correct given that + * glutGet( GLUT_WINDOW_X ) and glutGet( GLUT_WINDOW_Y ) return relative to parent + * origin when looking at a child window + * for parent windows: window->State.MouseX + glutGet( GLUT_WINDOW_X ) == mouse_pos.X + */ + fghPlatformGetCursorPos(NULL, GL_FALSE, &mouse_pos); + menu->X = mouse_pos.X; + menu->Y = mouse_pos.Y; + + /* Make sure the whole menu is on the screen */ + if( menu->X + menu->Width > max_x ) + menu->X -=menu->Width; + + if( menu->Y + menu->Height > max_y ) + { + menu->Y -=menu->Height; + if( menu->Y < 0 ) + menu->Y = 0; + } + + /* Set position of mouse relative to top-left menu in menu's window state (could as well set 0 at creation time...) */ + menu->Window->State.MouseX = mouse_pos.X - menu->X; + menu->Window->State.MouseY = mouse_pos.Y - menu->Y; + + /* Menu status callback */ + if (fgState.MenuStateCallback || fgState.MenuStatusCallback) + { + fgStructure.CurrentMenu = menu; + fgStructure.CurrentWindow = window; + if (fgState.MenuStateCallback) + fgState.MenuStateCallback(GLUT_MENU_IN_USE); + if (fgState.MenuStatusCallback) + /* window->State.MouseX and window->State.MouseY are relative to client area origin, as needed */ + fgState.MenuStatusCallback(GLUT_MENU_IN_USE, window->State.MouseX, window->State.MouseY, fgState.MenuStatusCallbackData); + } + + fgSetWindow( menu->Window ); + glutPositionWindow( menu->X, menu->Y ); + glutReshapeWindow( menu->Width, menu->Height ); + glutPopWindow( ); + glutShowWindow( ); + menu->Window->ActiveMenu = menu; + fghCheckMenuStatus( menu ); + fgSetWindow( current_window ); +} + +/* + * Update Highlight states of the menu + * NB: Current mouse position is in menu->Window->State.MouseX/Y + */ +void fgUpdateMenuHighlight ( SFG_Menu *menu ) +{ + fghCheckMenuStatus( menu ); +} + +/* + * Check whether an active menu absorbs a mouse click + */ +GLboolean fgCheckActiveMenu ( SFG_Window *window, int button, GLboolean pressed, + int mouse_x, int mouse_y ) +{ + GLboolean is_handled = GL_FALSE; + GLboolean is_clicked = GL_FALSE; + /* + * Near as I can tell, this is the menu behaviour: + * - Down-click the menu button, menu not active: activate + * the menu with its upper left-hand corner at the mouse + * location. + * - Down-click any button outside the menu, menu active: + * deactivate the menu, and potentially activate a new menu + * at the new mouse location. This includes clicks in + * different windows of course + * - Down-click any button inside the menu, menu active: + * select the menu entry and deactivate the menu + * - Up-click the menu button, menu not active: nothing happens + * - Up-click the menu button outside the menu, menu active: + * nothing happens + * - Up-click the menu button inside the menu, menu active: + * select the menu entry and deactivate the menu + * Since menus can have submenus, we need to check this recursively. + */ + if( window->ActiveMenu ) + { + if( window == window->ActiveMenu->ParentWindow ) + { + window->ActiveMenu->Window->State.MouseX = + mouse_x - window->ActiveMenu->X; + window->ActiveMenu->Window->State.MouseY = + mouse_y - window->ActiveMenu->Y; + } + + /* In the menu, deactivate the menu and invoke the callback */ + if( fghCheckMenuStatus( window->ActiveMenu ) ) + { + /* + * Save the current window and menu and set the current + * window to the window whose menu this is + */ + SFG_Window *save_window = fgStructure.CurrentWindow; + SFG_Menu *save_menu = fgStructure.CurrentMenu, *active_menu = window->ActiveMenu; /* active menu is always the one with the mouse in it, due to fghCheckMenuStatus */ + SFG_MenuEntry *active_entry = active_menu->ActiveEntry; /* currently highlighted item -> must be the one that was just clicked */ + SFG_Window *parent_window = window->ActiveMenu->ParentWindow; + + /* ignore clicks on the submenu entry */ + if (!active_entry->SubMenu) + { + fgSetWindow( parent_window ); + fgStructure.CurrentMenu = active_menu; + + /* Deactivate menu and then call callback (we don't want menu to stay in view while callback is executing, and user should be able to change menus in callback) */ + fgDeactivateMenu( parent_window ); + active_menu->Callback( active_entry->ID, active_menu->CallbackData ); + + /* Restore the current window and menu */ + fgSetWindow( save_window ); + fgStructure.CurrentMenu = save_menu; + } + + is_clicked = GL_TRUE; /* Don't reopen... */ + } + else if( pressed ) + /* + * Outside the menu, deactivate if it's a downclick + * + * A downclick outside of the interior of our freeglut windows + * is dealt with in the WM_KILLFOCUS handler of fgPlatformWindowProc + */ + { + fgDeactivateMenu( window->ActiveMenu->ParentWindow ); + /* Could reopen again in different location, as is_clicked remains false */ + } + + is_handled = GL_TRUE; + } + else if ( fgState.ActiveMenus ) /* Don't have to check whether this was a downpress or an uppress, there is no way to get an uppress in another window before a downpress... */ + { + /* if another window than the one clicked in has an open menu, close it */ + SFG_Menu *menu = fgGetActiveMenu(); + if ( menu ) /* any open menu? */ + fgDeactivateMenu( menu->ParentWindow ); + + /* Leave is_handled to false, we didn't do anything relevant from the perspective of the window that was clicked */ + } + + /* No active menu, let's check whether we need to activate one. */ + if( !is_clicked && + ( 0 <= button ) && + ( FREEGLUT_MAX_MENUS > button ) && + ( window->Menu[ button ] ) && + pressed ) + { + /* If mouseclick was outside the parent window, ignore. This can + * happen when another mouse button is already depressed and the + * window thus has mouse capture + */ + if (window->State.MouseX>0 && window->State.MouseY>0 && + window->State.MouseXState.Width && window->State.MouseYState.Height) + { + fghActivateMenu( window, button ); + is_handled = GL_TRUE; + } + } + + return is_handled; +} + +/* + * Deactivates a menu pointed by the function argument. + */ +static SFG_Menu* menuDeactivating = NULL; +void fgDeactivateMenu( SFG_Window *window ) +{ + SFG_Window *parent_window = NULL; + SFG_Menu* menu; + SFG_MenuEntry *menuEntry; + + /* Did we find an active window? */ + freeglut_return_if_fail( window ); + /* Check if there is an active menu attached to this window... */ + menu = window->ActiveMenu; + freeglut_return_if_fail( menu ); + /* Check if we are already deactivating this menu, abort in that case (glutHideWindow below can cause this function to be called again on the same menu..) */ + if (menu==menuDeactivating) + return; + menuDeactivating = menu; + + parent_window = menu->ParentWindow; + + /* Hide the present menu's window */ + fgPlatformHideWindow( menu->Window ); + + /* Forget about having that menu active anymore, now: */ + menu->Window->ActiveMenu = NULL; + menu->ParentWindow->ActiveMenu = NULL; + fghSetMenuParentWindow ( NULL, menu ); + menu->IsActive = GL_FALSE; + menu->ActiveEntry = NULL; + + fgState.ActiveMenus--; + + /* Hide all submenu windows, and the root menu's window. */ + for ( menuEntry = ( SFG_MenuEntry * )menu->Entries.First; + menuEntry; + menuEntry = ( SFG_MenuEntry * )menuEntry->Node.Next ) + { + menuEntry->IsActive = GL_FALSE; + + /* Is that an active submenu by any chance? */ + if( menuEntry->SubMenu ) + fghDeactivateSubMenu( menuEntry ); + } + /* Done deactivating menu */ + menuDeactivating = NULL; + + /* Menu status callback */ + if (fgState.MenuStateCallback || fgState.MenuStatusCallback) + { + fgStructure.CurrentMenu = menu; + fgStructure.CurrentWindow = parent_window; + if (fgState.MenuStateCallback) + fgState.MenuStateCallback(GLUT_MENU_NOT_IN_USE); + if (fgState.MenuStatusCallback) + { + /* Get cursor position relative to parent_window's client area */ + SFG_XYUse mouse_pos; + fghPlatformGetCursorPos(parent_window, GL_TRUE, &mouse_pos); + + fgState.MenuStatusCallback(GLUT_MENU_NOT_IN_USE, mouse_pos.X, mouse_pos.Y, fgState.MenuStatusCallbackData); + } + } +} + +/* + * Recalculates current menu's box size + */ +void fghCalculateMenuBoxSize( void ) +{ + SFG_MenuEntry* menuEntry; + int width = 0, height = 0; + + /* Make sure there is a current menu set */ + freeglut_return_if_fail( fgStructure.CurrentMenu ); + + /* The menu's box size depends on the menu entries: */ + for( menuEntry = ( SFG_MenuEntry * )fgStructure.CurrentMenu->Entries.First; + menuEntry; + menuEntry = ( SFG_MenuEntry * )menuEntry->Node.Next ) + { + /* Update the menu entry's width value */ + menuEntry->Width = glutBitmapLength( + fgStructure.CurrentMenu->Font, + (unsigned char *)menuEntry->Text + ); + + /* + * If the entry is a submenu, then it needs to be wider to + * accommodate the arrow. + */ + if (menuEntry->SubMenu) + menuEntry->Width += glutBitmapLength( + fgStructure.CurrentMenu->Font, + (unsigned char *)"_" + ); + + /* Check if it's the biggest we've found */ + if( menuEntry->Width > width ) + width = menuEntry->Width; + + height += FREEGLUT_MENUENTRY_HEIGHT(fgStructure.CurrentMenu->Font); + } + + /* Store the menu's box size now: */ + fgStructure.CurrentMenu->Height = height + 2 * FREEGLUT_MENU_BORDER; + fgStructure.CurrentMenu->Width = width + 4 * FREEGLUT_MENU_BORDER; +} + + +/* -- INTERFACE FUNCTIONS -------------------------------------------------- */ + +/* + * Creates a new menu object, adding it to the freeglut structure + */ +int FGAPIENTRY glutCreateMenuUcall( FGCBMenuUC callback, FGCBUserData userData ) +{ + /* The menu object creation code resides in fg_structure.c */ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateMenuUcall" ); + if (fgState.ActiveMenus) + { + fgError( "Menu manipulation not allowed while menus in use." ); + } + + return fgCreateMenu( callback, userData )->ID; +} + +/* Standard glutCreateMenu */ +static void fghCreateMenuCallback( int menu, FGCBUserData userData ) +{ + FGCBMenu* callback = (FGCBMenu*)&userData; + (*callback)( menu ); +} + +int FGAPIENTRY glutCreateMenu( FGCBMenu callback ) +{ + FGCBMenu* reference; + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateMenu" ); + if (!callback) + { + return glutCreateMenuUcall( NULL, NULL ); + } + reference = &callback; + return glutCreateMenuUcall( fghCreateMenuCallback, *((FGCBUserData*)reference) ); +} + +/* + * Destroys a menu object, removing all references to it + */ +void FGAPIENTRY glutDestroyMenu( int menuID ) +{ + SFG_Menu* menu; + + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDestroyMenu" ); + menu = fgMenuByID( menuID ); + + freeglut_return_if_fail( menu ); + if (fgState.ActiveMenus) + fgError("Menu manipulation not allowed while menus in use."); + + /* The menu object destruction code resides in fg_structure.c */ + fgDestroyMenu( menu ); +} + +/* + * Returns the ID number of the currently active menu + */ +int FGAPIENTRY glutGetMenu( void ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGetMenu" ); + + if( fgStructure.CurrentMenu ) + return fgStructure.CurrentMenu->ID; + + return 0; +} + +/* + * Sets the current menu given its menu ID + */ +void FGAPIENTRY glutSetMenu( int menuID ) +{ + SFG_Menu* menu; + + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetMenu" ); + menu = fgMenuByID( menuID ); + + freeglut_return_if_fail( menu ); + + fgStructure.CurrentMenu = menu; +} + +/* + * Adds a menu entry to the bottom of the current menu + */ +void FGAPIENTRY glutAddMenuEntry( const char* label, int value ) +{ + SFG_MenuEntry* menuEntry; + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutAddMenuEntry" ); + menuEntry = (SFG_MenuEntry *)calloc( sizeof(SFG_MenuEntry), 1 ); + + freeglut_return_if_fail( fgStructure.CurrentMenu ); + if (fgState.ActiveMenus) + fgError("Menu manipulation not allowed while menus in use."); + + menuEntry->Text = strdup( label ); + menuEntry->ID = value; + + /* Have the new menu entry attached to the current menu */ + fgListAppend( &fgStructure.CurrentMenu->Entries, &menuEntry->Node ); + + fghCalculateMenuBoxSize( ); +} + +/* + * Add a sub menu to the bottom of the current menu + */ +void FGAPIENTRY glutAddSubMenu( const char *label, int subMenuID ) +{ + SFG_MenuEntry *menuEntry; + SFG_Menu *subMenu; + + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutAddSubMenu" ); + menuEntry = ( SFG_MenuEntry * )calloc( sizeof( SFG_MenuEntry ), 1 ); + subMenu = fgMenuByID( subMenuID ); + + freeglut_return_if_fail( fgStructure.CurrentMenu ); + if (fgState.ActiveMenus) + fgError("Menu manipulation not allowed while menus in use."); + + freeglut_return_if_fail( subMenu ); + + menuEntry->Text = strdup( label ); + menuEntry->SubMenu = subMenu; + menuEntry->ID = -1; + + fgListAppend( &fgStructure.CurrentMenu->Entries, &menuEntry->Node ); + fghCalculateMenuBoxSize( ); +} + +/* + * Changes the current menu's font + */ +void FGAPIENTRY glutSetMenuFont( int menuID, void* fontID ) +{ + SFG_Font* font; + SFG_Menu* menu; + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetMenuFont" ); + menu = fgMenuByID( menuID ); + freeglut_return_if_fail( menu ); + + if (fgState.ActiveMenus) + fgError("Menu manipulation not allowed while menus in use."); + + font = fghFontByID( fontID ); + if (!font) + { + fgWarning("glutChangeMenuFont: bitmap font 0x%08x not found. Make sure you're not passing a stroke font. Ignoring...\n",fontID); + return; + } + + fgStructure.CurrentMenu->Font = fontID; + fghCalculateMenuBoxSize( ); +} + +/* + * Changes the specified menu item in the current menu into a menu entry + */ +void FGAPIENTRY glutChangeToMenuEntry( int item, const char* label, int value ) +{ + SFG_MenuEntry* menuEntry = NULL; + + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutChangeToMenuEntry" ); + + freeglut_return_if_fail( fgStructure.CurrentMenu ); + if (fgState.ActiveMenus) + fgError("Menu manipulation not allowed while menus in use."); + + /* Get n-th menu entry in the current menu, starting from one: */ + menuEntry = fghFindMenuEntry( fgStructure.CurrentMenu, item ); + + freeglut_return_if_fail( menuEntry ); + + /* We want it to become a normal menu entry, so: */ + if( menuEntry->Text ) + free( menuEntry->Text ); + + menuEntry->Text = strdup( label ); + menuEntry->ID = value; + menuEntry->SubMenu = NULL; + fghCalculateMenuBoxSize( ); +} + +/* + * Changes the specified menu item in the current menu into a sub-menu trigger. + */ +void FGAPIENTRY glutChangeToSubMenu( int item, const char* label, + int subMenuID ) +{ + SFG_Menu* subMenu; + SFG_MenuEntry* menuEntry; + + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutChangeToSubMenu" ); + + freeglut_return_if_fail( fgStructure.CurrentMenu ); + if (fgState.ActiveMenus) + fgError("Menu manipulation not allowed while menus in use."); + + /* Get handle to sub menu */ + subMenu = fgMenuByID( subMenuID ); + menuEntry = NULL; + freeglut_return_if_fail( subMenu ); + + /* Get n-th menu entry in the current menu, starting from one: */ + menuEntry = fghFindMenuEntry( fgStructure.CurrentMenu, item ); + + freeglut_return_if_fail( menuEntry ); + + /* We want it to become a sub menu entry, so: */ + if( menuEntry->Text ) + free( menuEntry->Text ); + + menuEntry->Text = strdup( label ); + menuEntry->SubMenu = subMenu; + menuEntry->ID = -1; + fghCalculateMenuBoxSize( ); +} + +/* + * Removes the specified menu item from the current menu + */ +void FGAPIENTRY glutRemoveMenuItem( int item ) +{ + SFG_MenuEntry* menuEntry; + + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutRemoveMenuItem" ); + + freeglut_return_if_fail( fgStructure.CurrentMenu ); + if (fgState.ActiveMenus) + fgError("Menu manipulation not allowed while menus in use."); + + /* Get n-th menu entry in the current menu, starting from one: */ + menuEntry = fghFindMenuEntry( fgStructure.CurrentMenu, item ); + + freeglut_return_if_fail( menuEntry ); + + fgListRemove( &fgStructure.CurrentMenu->Entries, &menuEntry->Node ); + if ( menuEntry->Text ) + free( menuEntry->Text ); + + free( menuEntry ); + fghCalculateMenuBoxSize( ); +} + +/* + * Attaches a menu to the current window + */ +void FGAPIENTRY glutAttachMenu( int button ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutAttachMenu" ); + + freeglut_return_if_fail( fgStructure.CurrentWindow ); + + freeglut_return_if_fail( fgStructure.CurrentMenu ); + if (fgState.ActiveMenus) + fgError("Menu manipulation not allowed while menus in use."); + + freeglut_return_if_fail( button >= 0 ); + freeglut_return_if_fail( button < FREEGLUT_MAX_MENUS ); + + fgStructure.CurrentWindow->Menu[ button ] = fgStructure.CurrentMenu; +} + +/* + * Detaches a menu from the current window + */ +void FGAPIENTRY glutDetachMenu( int button ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDetachMenu" ); + + freeglut_return_if_fail( fgStructure.CurrentWindow ); + + freeglut_return_if_fail( fgStructure.CurrentMenu ); + if (fgState.ActiveMenus) + fgError("Menu manipulation not allowed while menus in use."); + + freeglut_return_if_fail( button >= 0 ); + freeglut_return_if_fail( button < FREEGLUT_MAX_MENUS ); + + fgStructure.CurrentWindow->Menu[ button ] = NULL; +} + +/* + * A.Donev: Set and retrieve the menu's user data + */ +void* FGAPIENTRY glutGetMenuData( void ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGetMenuData" ); + return fgStructure.CurrentMenu->UserData; +} + +void FGAPIENTRY glutSetMenuData(void* data) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetMenuData" ); + fgStructure.CurrentMenu->UserData=data; +} + +/*** END OF FILE ***/ diff --git a/src/fg_misc.c b/src/fg_misc.c new file mode 100644 index 0000000..6698772 --- /dev/null +++ b/src/fg_misc.c @@ -0,0 +1,200 @@ +/* + * fg_misc.c + * + * Functions that didn't fit anywhere else... + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Thu Dec 9 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" + + +/* platform-specific colormap functions */ +void fgPlatformSetColor(int idx, float r, float g, float b); +float fgPlatformGetColor(int idx, int comp); +void fgPlatformCopyColormap(int win); + + +/* -- INTERFACE FUNCTIONS -------------------------------------------------- */ + +/* + * This functions checks if an OpenGL extension is supported or not + * + * XXX Wouldn't this be simpler and clearer if we used strtok()? + */ +int FGAPIENTRY glutExtensionSupported( const char* extension ) +{ + const char *extensions, *start; + const size_t len = strlen( extension ); + + /* Make sure there is a current window, and thus a current context available */ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutExtensionSupported" ); + freeglut_return_val_if_fail( fgStructure.CurrentWindow != NULL, 0 ); + + if (strchr(extension, ' ')) + return 0; + start = extensions = (const char *) glGetString(GL_EXTENSIONS); + + /* XXX consider printing a warning to stderr that there's no current + * rendering context. + */ + freeglut_return_val_if_fail( extensions != NULL, 0 ); + + while (1) { + const char *p = strstr(extensions, extension); + if (!p) + return 0; /* not found */ + /* check that the match isn't a super string */ + if ((p == start || p[-1] == ' ') && (p[len] == ' ' || p[len] == 0)) + return 1; + /* skip the false match and continue */ + extensions = p + len; + } + + return 0 ; +} + +#ifndef GL_INVALID_FRAMEBUFFER_OPERATION +#ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT +#define GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_EXT +#else +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +#endif +#endif + +#ifndef GL_TABLE_TOO_LARGE +#ifdef GL_TABLE_TOO_LARGE_EXT +#define GL_TABLE_TOO_LARGE GL_TABLE_TOO_LARGE_EXT +#else +#define GL_TABLE_TOO_LARGE 0x8031 +#endif +#endif + +#ifndef GL_TEXTURE_TOO_LARGE +#ifdef GL_TEXTURE_TOO_LARGE_EXT +#define GL_TEXTURE_TOO_LARGE GL_TEXTURE_TOO_LARGE_EXT +#else +#define GL_TEXTURE_TOO_LARGE 0x8065 +#endif +#endif + +/* + * A cut-down local version of gluErrorString to avoid depending on GLU. + */ +static const char* fghErrorString( GLenum error ) +{ + switch ( error ) { + case GL_INVALID_ENUM: return "invalid enumerant"; + case GL_INVALID_VALUE: return "invalid value"; + case GL_INVALID_OPERATION: return "invalid operation"; +#ifndef GL_ES_VERSION_2_0 + case GL_STACK_OVERFLOW: return "stack overflow"; + case GL_STACK_UNDERFLOW: return "stack underflow"; +#endif + case GL_OUT_OF_MEMORY: return "out of memory"; + case GL_TABLE_TOO_LARGE: return "table too large"; + case GL_INVALID_FRAMEBUFFER_OPERATION: return "invalid framebuffer operation"; + case GL_TEXTURE_TOO_LARGE: return "texture too large"; + default: return "unknown GL error"; + } +} + +/* + * This function reports all the OpenGL errors that happened till now + */ +void FGAPIENTRY glutReportErrors( void ) +{ + GLenum error; + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReportErrors" ); + while( ( error = glGetError() ) != GL_NO_ERROR ) + fgWarning( "GL error: %s", fghErrorString( error ) ); +} + +/* + * Control the auto-repeat of keystrokes to the current window + */ +void FGAPIENTRY glutIgnoreKeyRepeat( int ignore ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIgnoreKeyRepeat" ); + FREEGLUT_EXIT_IF_NO_WINDOW ( "glutIgnoreKeyRepeat" ); + + fgStructure.CurrentWindow->State.IgnoreKeyRepeat = ignore ? GL_TRUE : GL_FALSE; +} + +/* + * Set global auto-repeat of keystrokes + * + * RepeatMode should be any of: + * GLUT_KEY_REPEAT_OFF + * GLUT_KEY_REPEAT_ON + * GLUT_KEY_REPEAT_DEFAULT + */ +void FGAPIENTRY glutSetKeyRepeat( int repeatMode ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetKeyRepeat" ); + + switch( repeatMode ) + { + case GLUT_KEY_REPEAT_OFF: + fgState.KeyRepeat = GLUT_KEY_REPEAT_OFF; + break; + + case GLUT_KEY_REPEAT_ON: + case GLUT_KEY_REPEAT_DEFAULT: + fgState.KeyRepeat = GLUT_KEY_REPEAT_ON; + break; + + default: + fgError ("Invalid glutSetKeyRepeat mode: %d", repeatMode); + break; + } +} + +/* + * + */ +void FGAPIENTRY glutSetColor(int idx, GLfloat r, GLfloat g, GLfloat b) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetColor" ); + fgPlatformSetColor(idx, r, g, b); +} + +/* + * + */ +GLfloat FGAPIENTRY glutGetColor(int idx, int component) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGetColor" ); + return fgPlatformGetColor(idx, component); +} + +/* + * + */ +void FGAPIENTRY glutCopyColormap(int window) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCopyColormap" ); + fgPlatformCopyColormap(window); +} + +/*** END OF FILE ***/ diff --git a/src/fg_overlay.c b/src/fg_overlay.c new file mode 100644 index 0000000..dacdea6 --- /dev/null +++ b/src/fg_overlay.c @@ -0,0 +1,45 @@ +/* + * fg_overlay.c + * + * Overlay management functions (as defined by GLUT API) + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Thu Dec 16 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" + +/* + * NOTE: functions declared in this file probably will not be implemented. + */ + +/* -- INTERFACE FUNCTIONS -------------------------------------------------- */ + +void FGAPIENTRY glutEstablishOverlay( void ) { /* Not implemented */ } +void FGAPIENTRY glutRemoveOverlay( void ) { /* Not implemented */ } +void FGAPIENTRY glutUseLayer( GLenum layer ) { /* Not implemented */ } +void FGAPIENTRY glutPostOverlayRedisplay( void ) { /* Not implemented */ } +void FGAPIENTRY glutPostWindowOverlayRedisplay( int ID ) { /* Not implemented */ } +void FGAPIENTRY glutShowOverlay( void ) { /* Not implemented */ } +void FGAPIENTRY glutHideOverlay( void ) { /* Not implemented */ } + +/*** END OF FILE ***/ diff --git a/src/fg_spaceball.c b/src/fg_spaceball.c new file mode 100644 index 0000000..93727a1 --- /dev/null +++ b/src/fg_spaceball.c @@ -0,0 +1,103 @@ +/* Spaceball support for Linux. + * Written by John Tsiombikas + * + * This code supports 3Dconnexion's 6-dof space-whatever devices. + * It can communicate with either the proprietary 3Dconnexion daemon (3dxsrv) + * free spacenavd (http://spacenav.sourceforge.net), through the "standard" + * magellan X-based protocol. + */ + + +#include +#include "fg_internal.h" + +#if( !_WIN32 || _WIN32_WINNT >= 0x0501) + +/* -- PRIVATE FUNCTIONS --------------------------------------------------- */ + +extern void fgPlatformInitializeSpaceball(void); +extern void fgPlatformSpaceballClose(void); +extern int fgPlatformHasSpaceball(void); +extern int fgPlatformSpaceballNumButtons(void); +extern void fgPlatformSpaceballSetWindow(SFG_Window *window); + + +int fg_sball_initialized = 0; + +void fgInitialiseSpaceball(void) +{ + if(fg_sball_initialized != 0) { + return; + } + + fgPlatformInitializeSpaceball(); +} + +void fgSpaceballClose(void) +{ + fgPlatformSpaceballClose(); +} + +int fgHasSpaceball(void) +{ + if(fg_sball_initialized == 0) { + fgInitialiseSpaceball(); + if(fg_sball_initialized != 1) { + fgWarning("fgInitialiseSpaceball failed\n"); + return 0; + } + } + + return fgPlatformHasSpaceball(); +} + +int fgSpaceballNumButtons(void) +{ + if(fg_sball_initialized == 0) { + fgInitialiseSpaceball(); + if(fg_sball_initialized != 1) { + fgWarning("fgInitialiseSpaceball failed\n"); + return 0; + } + } + + return fgPlatformSpaceballNumButtons(); +} + +void fgSpaceballSetWindow(SFG_Window *window) +{ + if(fg_sball_initialized == 0) { + fgInitialiseSpaceball(); + if(fg_sball_initialized != 1) { + return; + } + } + + fgPlatformSpaceballSetWindow(window); +} + +#else + +void fgInitialiseSpaceball(void) +{ +} + +void fgSpaceballClose(void) +{ +} + +int fgHasSpaceball(void) +{ + return 0; +} + +int fgSpaceballNumButtons(void) +{ + return 0; +} + +void fgSpaceballSetWindow(SFG_Window *window) +{ +} + +#endif diff --git a/src/fg_state.c b/src/fg_state.c new file mode 100644 index 0000000..4165daa --- /dev/null +++ b/src/fg_state.c @@ -0,0 +1,376 @@ +/* + * fg_state.c + * + * Freeglut state query methods. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Thu Dec 16 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" + +/* + * TODO BEFORE THE STABLE RELEASE: + * + * glutGet() -- X11 tests passed, but check if all enums + * handled (what about Win32?) + * glutDeviceGet() -- X11 tests passed, but check if all enums + * handled (what about Win32?) + * glutGetModifiers() -- OK, but could also remove the limitation + * glutLayerGet() -- what about GLUT_NORMAL_DAMAGED? + * + * The fail-on-call policy will help adding the most needed things imho. + */ + +extern int fgPlatformGlutGet ( GLenum eWhat ); +extern int fgPlatformGlutDeviceGet ( GLenum eWhat ); +extern int *fgPlatformGlutGetModeValues(GLenum eWhat, int *size); +extern SFG_Font* fghFontByID( void* font ); + + +/* -- LOCAL DEFINITIONS ---------------------------------------------------- */ + +/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ + + +/* -- INTERFACE FUNCTIONS -------------------------------------------------- */ + +/* + * General settings assignment method + */ +void FGAPIENTRY glutSetOption( GLenum eWhat, int value ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetOption" ); + + switch( eWhat ) + { + case GLUT_INIT_WINDOW_X: + fgState.Position.X = (GLint)value; + break; + + case GLUT_INIT_WINDOW_Y: + fgState.Position.Y = (GLint)value; + break; + + case GLUT_INIT_WINDOW_WIDTH: + fgState.Size.X = (GLint)value; + break; + + case GLUT_INIT_WINDOW_HEIGHT: + fgState.Size.Y = (GLint)value; + break; + + case GLUT_INIT_DISPLAY_MODE: + fgState.DisplayMode = (unsigned int)value; + break; + + case GLUT_ACTION_ON_WINDOW_CLOSE: + fgState.ActionOnWindowClose = value; + break; + + case GLUT_RENDERING_CONTEXT: + fgState.UseCurrentContext = + ( value == GLUT_USE_CURRENT_CONTEXT ) ? GL_TRUE : GL_FALSE; + break; + + case GLUT_DIRECT_RENDERING: + fgState.DirectContext = value; + break; + + case GLUT_WINDOW_CURSOR: + if( fgStructure.CurrentWindow != NULL ) + fgStructure.CurrentWindow->State.Cursor = value; + break; + + case GLUT_AUX: + fgState.AuxiliaryBufferNumber = value; + break; + + case GLUT_MULTISAMPLE: + fgState.SampleNumber = value; + break; + + case GLUT_SKIP_STALE_MOTION_EVENTS: + fgState.SkipStaleMotion = !!value; + break; + + case GLUT_GEOMETRY_VISUALIZE_NORMALS: + if( fgStructure.CurrentWindow != NULL ) + fgStructure.CurrentWindow->State.VisualizeNormals = !!value; + break; + + case GLUT_STROKE_FONT_DRAW_JOIN_DOTS: + fgState.StrokeFontDrawJoinDots = !!value; + break; + + case GLUT_ALLOW_NEGATIVE_WINDOW_POSITION: + fgState.AllowNegativeWindowPosition = !!value; + break; + + default: + fgWarning( "glutSetOption(): missing enum handle %d", eWhat ); + break; + } +} + +/* + * General settings query method + */ +int FGAPIENTRY glutGet( GLenum eWhat ) +{ + switch (eWhat) + { + case GLUT_INIT_STATE: + return fgState.Initialised; + + /* Although internally the time store is 64bits wide, the return value + * here still wraps every 49.7 days. Integer overflows cancel however + * when subtracting an initial start time, unless the total time exceeds + * 32-bit, so you can still work with this. + * XXX: a glutGet64 to return the time might be an idea... + */ + case GLUT_ELAPSED_TIME: + return (int) fgElapsedTime(); + } + + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGet" ); + + switch( eWhat ) + { + /* Following values are stored in fgState and fgDisplay global structures */ + case GLUT_SCREEN_WIDTH: return fgDisplay.ScreenWidth ; + case GLUT_SCREEN_HEIGHT: return fgDisplay.ScreenHeight ; + case GLUT_SCREEN_WIDTH_MM: return fgDisplay.ScreenWidthMM ; + case GLUT_SCREEN_HEIGHT_MM: return fgDisplay.ScreenHeightMM; + case GLUT_INIT_WINDOW_X: return fgState.Position.Use ? + fgState.Position.X : -1 ; + case GLUT_INIT_WINDOW_Y: return fgState.Position.Use ? + fgState.Position.Y : -1 ; + case GLUT_INIT_WINDOW_WIDTH: return fgState.Size.Use ? + fgState.Size.X : -1 ; + case GLUT_INIT_WINDOW_HEIGHT: return fgState.Size.Use ? + fgState.Size.Y : -1 ; + case GLUT_INIT_DISPLAY_MODE: return fgState.DisplayMode ; + case GLUT_INIT_MAJOR_VERSION: return fgState.MajorVersion ; + case GLUT_INIT_MINOR_VERSION: return fgState.MinorVersion ; + case GLUT_INIT_FLAGS: return fgState.ContextFlags ; + case GLUT_INIT_PROFILE: return fgState.ContextProfile ; + + /* The window structure queries */ + case GLUT_WINDOW_PARENT: + if( fgStructure.CurrentWindow == NULL ) return 0; + if( fgStructure.CurrentWindow->Parent == NULL ) return 0; + return fgStructure.CurrentWindow->Parent->ID; + + case GLUT_WINDOW_NUM_CHILDREN: + if( fgStructure.CurrentWindow == NULL ) + return 0; + return fgListLength( &fgStructure.CurrentWindow->Children ); + + case GLUT_WINDOW_CURSOR: + if( fgStructure.CurrentWindow == NULL ) + return 0; + return fgStructure.CurrentWindow->State.Cursor; + + case GLUT_MENU_NUM_ITEMS: + if( fgStructure.CurrentMenu == NULL ) + return 0; + return fgListLength( &fgStructure.CurrentMenu->Entries ); + + case GLUT_ACTION_ON_WINDOW_CLOSE: + return fgState.ActionOnWindowClose; + + case GLUT_VERSION : + return VERSION_MAJOR * 10000 + VERSION_MINOR * 100 + VERSION_PATCH; + + case GLUT_RENDERING_CONTEXT: + return fgState.UseCurrentContext ? GLUT_USE_CURRENT_CONTEXT + : GLUT_CREATE_NEW_CONTEXT; + + case GLUT_DIRECT_RENDERING: + return fgState.DirectContext; + + case GLUT_FULL_SCREEN: + return fgStructure.CurrentWindow->State.IsFullscreen; + + case GLUT_AUX: + return fgState.AuxiliaryBufferNumber; + + case GLUT_MULTISAMPLE: + return fgState.SampleNumber; + + case GLUT_SKIP_STALE_MOTION_EVENTS: + return fgState.SkipStaleMotion; + + case GLUT_GEOMETRY_VISUALIZE_NORMALS: + if( fgStructure.CurrentWindow == NULL ) + return GL_FALSE; + return fgStructure.CurrentWindow->State.VisualizeNormals; + + case GLUT_STROKE_FONT_DRAW_JOIN_DOTS: + return fgState.StrokeFontDrawJoinDots; + + case GLUT_ALLOW_NEGATIVE_WINDOW_POSITION: + return fgState.AllowNegativeWindowPosition; + + default: + return fgPlatformGlutGet ( eWhat ); + break; + } +} + +/* + * Returns various device information. + */ +int FGAPIENTRY glutDeviceGet( GLenum eWhat ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDeviceGet" ); + + /* XXX WARNING: we are mostly lying in this function. */ + switch( eWhat ) + { + case GLUT_HAS_JOYSTICK: + return fgJoystickDetect (); + + case GLUT_OWNS_JOYSTICK: + return fgState.JoysticksInitialised; + + case GLUT_JOYSTICK_POLL_RATE: + return fgStructure.CurrentWindow ? fgStructure.CurrentWindow->State.JoystickPollRate : 0; + + /* XXX The following two are only for Joystick 0 but this is an improvement */ + case GLUT_JOYSTICK_BUTTONS: + return glutJoystickGetNumButtons ( 0 ); + + case GLUT_JOYSTICK_AXES: + return glutJoystickGetNumAxes ( 0 ); + + case GLUT_HAS_DIAL_AND_BUTTON_BOX: + return fgInputDeviceDetect (); + + case GLUT_NUM_DIALS: + if ( fgState.InputDevsInitialised ) return 8; + return 0; + + case GLUT_NUM_BUTTON_BOX_BUTTONS: + return 0; + + case GLUT_HAS_SPACEBALL: + return fgHasSpaceball(); + + case GLUT_HAS_TABLET: + return 0; + + case GLUT_NUM_SPACEBALL_BUTTONS: + return fgSpaceballNumButtons(); + + case GLUT_NUM_TABLET_BUTTONS: + return 0; + + case GLUT_DEVICE_IGNORE_KEY_REPEAT: + return fgStructure.CurrentWindow ? fgStructure.CurrentWindow->State.IgnoreKeyRepeat : 0; + + case GLUT_DEVICE_KEY_REPEAT: + return fgState.KeyRepeat; + + default: + return fgPlatformGlutDeviceGet ( eWhat ); + } +} + +/* + * This should return the current state of ALT, SHIFT and CTRL keys. + */ +int FGAPIENTRY glutGetModifiers( void ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGetModifiers" ); + if( fgState.Modifiers == INVALID_MODIFIERS ) + { + fgWarning( "glutGetModifiers() called outside an input callback" ); + return 0; + } + + return fgState.Modifiers; +} + +/* + * Return the state of the GLUT API overlay subsystem. A misery ;-) + */ +int FGAPIENTRY glutLayerGet( GLenum eWhat ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutLayerGet" ); + + /* + * This is easy as layers are not implemented and + * overlay support is not planned. E.g. on Windows, + * overlay requests in PFDs are ignored + * (see iLayerType at http://msdn.microsoft.com/en-us/library/dd368826(v=vs.85).aspx) + */ + switch( eWhat ) + { + + case GLUT_OVERLAY_POSSIBLE: + return 0 ; + + case GLUT_LAYER_IN_USE: + return GLUT_NORMAL; + + case GLUT_HAS_OVERLAY: + return 0; + + case GLUT_TRANSPARENT_INDEX: + /* + * Return just anything, which is always defined as zero + * + * XXX HUH? + */ + return 0; + + case GLUT_NORMAL_DAMAGED: + /* XXX Actually I do not know. Maybe. */ + return 0; + + case GLUT_OVERLAY_DAMAGED: + return -1; + + default: + fgWarning( "glutLayerGet(): missing enum handle %d", eWhat ); + break; + } + + /* And fail. That's good. Programs do love failing. */ + return -1; +} + +int * FGAPIENTRY glutGetModeValues(GLenum eWhat, int *size) +{ + int *array; + + FREEGLUT_EXIT_IF_NOT_INITIALISED("glutGetModeValues"); + + *size = 0; + array = fgPlatformGlutGetModeValues ( eWhat, size ); + + return array; +} + +/*** END OF FILE ***/ diff --git a/src/fg_stroke_mono_roman.c b/src/fg_stroke_mono_roman.c new file mode 100644 index 0000000..c36419e --- /dev/null +++ b/src/fg_stroke_mono_roman.c @@ -0,0 +1,2849 @@ +/* + * fg_stroke_mono_roman.c + * + * freeglut Monospace Roman stroke font definition + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Thu Dec 16 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* This file has been automatically generated by the genstroke utility. */ + +#include +#include "fg_internal.h" + +/* char: 0x20 */ + +static const SFG_StrokeStrip StrokeMonoRoman_ch32st[] = +{ + { 0, NULL } +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch32 = {104.762f,0,StrokeMonoRoman_ch32st}; + +/* char: 0x21 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch33st0[] = +{ + {52.381f,100.0f}, + {52.381f,33.3333f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch33st1[] = +{ + {52.381f,9.5238f}, + {47.6191f,4.7619f}, + {52.381f,0.0f}, + {57.1429f,4.7619f}, + {52.381f,9.5238f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch33st[] = +{ + {2,StrokeMonoRoman_ch33st0}, + {5,StrokeMonoRoman_ch33st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch33 = {104.762f,2,StrokeMonoRoman_ch33st}; + +/* char: 0x22 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch34st0[] = +{ + {33.3334f,100.0f}, + {33.3334f,66.6667f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch34st1[] = +{ + {71.4286f,100.0f}, + {71.4286f,66.6667f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch34st[] = +{ + {2,StrokeMonoRoman_ch34st0}, + {2,StrokeMonoRoman_ch34st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch34 = {104.762f,2,StrokeMonoRoman_ch34st}; + +/* char: 0x23 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch35st0[] = +{ + {54.7619f,119.048f}, + {21.4286f,-33.3333f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch35st1[] = +{ + {83.3334f,119.048f}, + {50.0f,-33.3333f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch35st2[] = +{ + {21.4286f,57.1429f}, + {88.0952f,57.1429f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch35st3[] = +{ + {16.6667f,28.5714f}, + {83.3334f,28.5714f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch35st[] = +{ + {2,StrokeMonoRoman_ch35st0}, + {2,StrokeMonoRoman_ch35st1}, + {2,StrokeMonoRoman_ch35st2}, + {2,StrokeMonoRoman_ch35st3} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch35 = {104.762f,4,StrokeMonoRoman_ch35st}; + +/* char: 0x24 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch36st0[] = +{ + {42.8571f,119.048f}, + {42.8571f,-19.0476f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch36st1[] = +{ + {61.9047f,119.048f}, + {61.9047f,-19.0476f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch36st2[] = +{ + {85.7143f,85.7143f}, + {76.1905f,95.2381f}, + {61.9047f,100.0f}, + {42.8571f,100.0f}, + {28.5714f,95.2381f}, + {19.0476f,85.7143f}, + {19.0476f,76.1905f}, + {23.8095f,66.6667f}, + {28.5714f,61.9048f}, + {38.0952f,57.1429f}, + {66.6666f,47.619f}, + {76.1905f,42.8571f}, + {80.9524f,38.0952f}, + {85.7143f,28.5714f}, + {85.7143f,14.2857f}, + {76.1905f,4.7619f}, + {61.9047f,0.0f}, + {42.8571f,0.0f}, + {28.5714f,4.7619f}, + {19.0476f,14.2857f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch36st[] = +{ + {2,StrokeMonoRoman_ch36st0}, + {2,StrokeMonoRoman_ch36st1}, + {20,StrokeMonoRoman_ch36st2} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch36 = {104.762f,3,StrokeMonoRoman_ch36st}; + +/* char: 0x25 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch37st0[] = +{ + {95.2381f,100.0f}, + {9.5238f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch37st1[] = +{ + {33.3333f,100.0f}, + {42.8571f,90.4762f}, + {42.8571f,80.9524f}, + {38.0952f,71.4286f}, + {28.5714f,66.6667f}, + {19.0476f,66.6667f}, + {9.5238f,76.1905f}, + {9.5238f,85.7143f}, + {14.2857f,95.2381f}, + {23.8095f,100.0f}, + {33.3333f,100.0f}, + {42.8571f,95.2381f}, + {57.1428f,90.4762f}, + {71.4286f,90.4762f}, + {85.7143f,95.2381f}, + {95.2381f,100.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch37st2[] = +{ + {76.1905f,33.3333f}, + {66.6667f,28.5714f}, + {61.9048f,19.0476f}, + {61.9048f,9.5238f}, + {71.4286f,0.0f}, + {80.9524f,0.0f}, + {90.4762f,4.7619f}, + {95.2381f,14.2857f}, + {95.2381f,23.8095f}, + {85.7143f,33.3333f}, + {76.1905f,33.3333f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch37st[] = +{ + {2,StrokeMonoRoman_ch37st0}, + {16,StrokeMonoRoman_ch37st1}, + {11,StrokeMonoRoman_ch37st2} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch37 = {104.762f,3,StrokeMonoRoman_ch37st}; + +/* char: 0x26 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch38st0[] = +{ + {100.0f,57.1429f}, + {100.0f,61.9048f}, + {95.2381f,66.6667f}, + {90.4762f,66.6667f}, + {85.7143f,61.9048f}, + {80.9524f,52.381f}, + {71.4286f,28.5714f}, + {61.9048f,14.2857f}, + {52.3809f,4.7619f}, + {42.8571f,0.0f}, + {23.8095f,0.0f}, + {14.2857f,4.7619f}, + {9.5238f,9.5238f}, + {4.7619f,19.0476f}, + {4.7619f,28.5714f}, + {9.5238f,38.0952f}, + {14.2857f,42.8571f}, + {47.619f,61.9048f}, + {52.3809f,66.6667f}, + {57.1429f,76.1905f}, + {57.1429f,85.7143f}, + {52.3809f,95.2381f}, + {42.8571f,100.0f}, + {33.3333f,95.2381f}, + {28.5714f,85.7143f}, + {28.5714f,76.1905f}, + {33.3333f,61.9048f}, + {42.8571f,47.619f}, + {66.6667f,14.2857f}, + {76.1905f,4.7619f}, + {85.7143f,0.0f}, + {95.2381f,0.0f}, + {100.0f,4.7619f}, + {100.0f,9.5238f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch38st[] = +{ + {34,StrokeMonoRoman_ch38st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch38 = {104.762f,1,StrokeMonoRoman_ch38st}; + +/* char: 0x27 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch39st0[] = +{ + {52.381f,100.0f}, + {52.381f,66.6667f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch39st[] = +{ + {2,StrokeMonoRoman_ch39st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch39 = {104.762f,1,StrokeMonoRoman_ch39st}; + +/* char: 0x28 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch40st0[] = +{ + {69.0476f,119.048f}, + {59.5238f,109.524f}, + {50.0f,95.2381f}, + {40.4762f,76.1905f}, + {35.7143f,52.381f}, + {35.7143f,33.3333f}, + {40.4762f,9.5238f}, + {50.0f,-9.5238f}, + {59.5238f,-23.8095f}, + {69.0476f,-33.3333f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch40st[] = +{ + {10,StrokeMonoRoman_ch40st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch40 = {104.762f,1,StrokeMonoRoman_ch40st}; + +/* char: 0x29 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch41st0[] = +{ + {35.7143f,119.048f}, + {45.2381f,109.524f}, + {54.7619f,95.2381f}, + {64.2857f,76.1905f}, + {69.0476f,52.381f}, + {69.0476f,33.3333f}, + {64.2857f,9.5238f}, + {54.7619f,-9.5238f}, + {45.2381f,-23.8095f}, + {35.7143f,-33.3333f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch41st[] = +{ + {10,StrokeMonoRoman_ch41st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch41 = {104.762f,1,StrokeMonoRoman_ch41st}; + +/* char: 0x2a */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch42st0[] = +{ + {52.381f,71.4286f}, + {52.381f,14.2857f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch42st1[] = +{ + {28.5715f,57.1429f}, + {76.1905f,28.5714f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch42st2[] = +{ + {76.1905f,57.1429f}, + {28.5715f,28.5714f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch42st[] = +{ + {2,StrokeMonoRoman_ch42st0}, + {2,StrokeMonoRoman_ch42st1}, + {2,StrokeMonoRoman_ch42st2} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch42 = {104.762f,3,StrokeMonoRoman_ch42st}; + +/* char: 0x2b */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch43st0[] = +{ + {52.3809f,85.7143f}, + {52.3809f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch43st1[] = +{ + {9.5238f,42.8571f}, + {95.2381f,42.8571f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch43st[] = +{ + {2,StrokeMonoRoman_ch43st0}, + {2,StrokeMonoRoman_ch43st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch43 = {104.762f,2,StrokeMonoRoman_ch43st}; + +/* char: 0x2c */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch44st0[] = +{ + {57.1429f,4.7619f}, + {52.381f,0.0f}, + {47.6191f,4.7619f}, + {52.381f,9.5238f}, + {57.1429f,4.7619f}, + {57.1429f,-4.7619f}, + {52.381f,-14.2857f}, + {47.6191f,-19.0476f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch44st[] = +{ + {8,StrokeMonoRoman_ch44st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch44 = {104.762f,1,StrokeMonoRoman_ch44st}; + +/* char: 0x2d */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch45st0[] = +{ + {9.5238f,42.8571f}, + {95.2381f,42.8571f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch45st[] = +{ + {2,StrokeMonoRoman_ch45st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch45 = {104.762f,1,StrokeMonoRoman_ch45st}; + +/* char: 0x2e */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch46st0[] = +{ + {52.381f,9.5238f}, + {47.6191f,4.7619f}, + {52.381f,0.0f}, + {57.1429f,4.7619f}, + {52.381f,9.5238f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch46st[] = +{ + {5,StrokeMonoRoman_ch46st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch46 = {104.762f,1,StrokeMonoRoman_ch46st}; + +/* char: 0x2f */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch47st0[] = +{ + {19.0476f,-14.2857f}, + {85.7143f,100.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch47st[] = +{ + {2,StrokeMonoRoman_ch47st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch47 = {104.762f,1,StrokeMonoRoman_ch47st}; + +/* char: 0x30 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch48st0[] = +{ + {47.619f,100.0f}, + {33.3333f,95.2381f}, + {23.8095f,80.9524f}, + {19.0476f,57.1429f}, + {19.0476f,42.8571f}, + {23.8095f,19.0476f}, + {33.3333f,4.7619f}, + {47.619f,0.0f}, + {57.1428f,0.0f}, + {71.4286f,4.7619f}, + {80.9524f,19.0476f}, + {85.7143f,42.8571f}, + {85.7143f,57.1429f}, + {80.9524f,80.9524f}, + {71.4286f,95.2381f}, + {57.1428f,100.0f}, + {47.619f,100.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch48st[] = +{ + {17,StrokeMonoRoman_ch48st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch48 = {104.762f,1,StrokeMonoRoman_ch48st}; + +/* char: 0x31 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch49st0[] = +{ + {40.4762f,80.9524f}, + {50.0f,85.7143f}, + {64.2857f,100.0f}, + {64.2857f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch49st[] = +{ + {4,StrokeMonoRoman_ch49st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch49 = {104.762f,1,StrokeMonoRoman_ch49st}; + +/* char: 0x32 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch50st0[] = +{ + {23.8095f,76.1905f}, + {23.8095f,80.9524f}, + {28.5714f,90.4762f}, + {33.3333f,95.2381f}, + {42.8571f,100.0f}, + {61.9047f,100.0f}, + {71.4286f,95.2381f}, + {76.1905f,90.4762f}, + {80.9524f,80.9524f}, + {80.9524f,71.4286f}, + {76.1905f,61.9048f}, + {66.6666f,47.619f}, + {19.0476f,0.0f}, + {85.7143f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch50st[] = +{ + {14,StrokeMonoRoman_ch50st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch50 = {104.762f,1,StrokeMonoRoman_ch50st}; + +/* char: 0x33 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch51st0[] = +{ + {28.5714f,100.0f}, + {80.9524f,100.0f}, + {52.3809f,61.9048f}, + {66.6666f,61.9048f}, + {76.1905f,57.1429f}, + {80.9524f,52.381f}, + {85.7143f,38.0952f}, + {85.7143f,28.5714f}, + {80.9524f,14.2857f}, + {71.4286f,4.7619f}, + {57.1428f,0.0f}, + {42.8571f,0.0f}, + {28.5714f,4.7619f}, + {23.8095f,9.5238f}, + {19.0476f,19.0476f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch51st[] = +{ + {15,StrokeMonoRoman_ch51st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch51 = {104.762f,1,StrokeMonoRoman_ch51st}; + +/* char: 0x34 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch52st0[] = +{ + {64.2857f,100.0f}, + {16.6667f,33.3333f}, + {88.0952f,33.3333f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch52st1[] = +{ + {64.2857f,100.0f}, + {64.2857f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch52st[] = +{ + {3,StrokeMonoRoman_ch52st0}, + {2,StrokeMonoRoman_ch52st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch52 = {104.762f,2,StrokeMonoRoman_ch52st}; + +/* char: 0x35 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch53st0[] = +{ + {76.1905f,100.0f}, + {28.5714f,100.0f}, + {23.8095f,57.1429f}, + {28.5714f,61.9048f}, + {42.8571f,66.6667f}, + {57.1428f,66.6667f}, + {71.4286f,61.9048f}, + {80.9524f,52.381f}, + {85.7143f,38.0952f}, + {85.7143f,28.5714f}, + {80.9524f,14.2857f}, + {71.4286f,4.7619f}, + {57.1428f,0.0f}, + {42.8571f,0.0f}, + {28.5714f,4.7619f}, + {23.8095f,9.5238f}, + {19.0476f,19.0476f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch53st[] = +{ + {17,StrokeMonoRoman_ch53st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch53 = {104.762f,1,StrokeMonoRoman_ch53st}; + +/* char: 0x36 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch54st0[] = +{ + {78.5714f,85.7143f}, + {73.8096f,95.2381f}, + {59.5238f,100.0f}, + {50.0f,100.0f}, + {35.7143f,95.2381f}, + {26.1905f,80.9524f}, + {21.4286f,57.1429f}, + {21.4286f,33.3333f}, + {26.1905f,14.2857f}, + {35.7143f,4.7619f}, + {50.0f,0.0f}, + {54.7619f,0.0f}, + {69.0476f,4.7619f}, + {78.5714f,14.2857f}, + {83.3334f,28.5714f}, + {83.3334f,33.3333f}, + {78.5714f,47.619f}, + {69.0476f,57.1429f}, + {54.7619f,61.9048f}, + {50.0f,61.9048f}, + {35.7143f,57.1429f}, + {26.1905f,47.619f}, + {21.4286f,33.3333f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch54st[] = +{ + {23,StrokeMonoRoman_ch54st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch54 = {104.762f,1,StrokeMonoRoman_ch54st}; + +/* char: 0x37 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch55st0[] = +{ + {85.7143f,100.0f}, + {38.0952f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch55st1[] = +{ + {19.0476f,100.0f}, + {85.7143f,100.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch55st[] = +{ + {2,StrokeMonoRoman_ch55st0}, + {2,StrokeMonoRoman_ch55st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch55 = {104.762f,2,StrokeMonoRoman_ch55st}; + +/* char: 0x38 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch56st0[] = +{ + {42.8571f,100.0f}, + {28.5714f,95.2381f}, + {23.8095f,85.7143f}, + {23.8095f,76.1905f}, + {28.5714f,66.6667f}, + {38.0952f,61.9048f}, + {57.1428f,57.1429f}, + {71.4286f,52.381f}, + {80.9524f,42.8571f}, + {85.7143f,33.3333f}, + {85.7143f,19.0476f}, + {80.9524f,9.5238f}, + {76.1905f,4.7619f}, + {61.9047f,0.0f}, + {42.8571f,0.0f}, + {28.5714f,4.7619f}, + {23.8095f,9.5238f}, + {19.0476f,19.0476f}, + {19.0476f,33.3333f}, + {23.8095f,42.8571f}, + {33.3333f,52.381f}, + {47.619f,57.1429f}, + {66.6666f,61.9048f}, + {76.1905f,66.6667f}, + {80.9524f,76.1905f}, + {80.9524f,85.7143f}, + {76.1905f,95.2381f}, + {61.9047f,100.0f}, + {42.8571f,100.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch56st[] = +{ + {29,StrokeMonoRoman_ch56st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch56 = {104.762f,1,StrokeMonoRoman_ch56st}; + +/* char: 0x39 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch57st0[] = +{ + {83.3334f,66.6667f}, + {78.5714f,52.381f}, + {69.0476f,42.8571f}, + {54.7619f,38.0952f}, + {50.0f,38.0952f}, + {35.7143f,42.8571f}, + {26.1905f,52.381f}, + {21.4286f,66.6667f}, + {21.4286f,71.4286f}, + {26.1905f,85.7143f}, + {35.7143f,95.2381f}, + {50.0f,100.0f}, + {54.7619f,100.0f}, + {69.0476f,95.2381f}, + {78.5714f,85.7143f}, + {83.3334f,66.6667f}, + {83.3334f,42.8571f}, + {78.5714f,19.0476f}, + {69.0476f,4.7619f}, + {54.7619f,0.0f}, + {45.2381f,0.0f}, + {30.9524f,4.7619f}, + {26.1905f,14.2857f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch57st[] = +{ + {23,StrokeMonoRoman_ch57st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch57 = {104.762f,1,StrokeMonoRoman_ch57st}; + +/* char: 0x3a */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch58st0[] = +{ + {52.381f,66.6667f}, + {47.6191f,61.9048f}, + {52.381f,57.1429f}, + {57.1429f,61.9048f}, + {52.381f,66.6667f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch58st1[] = +{ + {52.381f,9.5238f}, + {47.6191f,4.7619f}, + {52.381f,0.0f}, + {57.1429f,4.7619f}, + {52.381f,9.5238f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch58st[] = +{ + {5,StrokeMonoRoman_ch58st0}, + {5,StrokeMonoRoman_ch58st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch58 = {104.762f,2,StrokeMonoRoman_ch58st}; + +/* char: 0x3b */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch59st0[] = +{ + {52.381f,66.6667f}, + {47.6191f,61.9048f}, + {52.381f,57.1429f}, + {57.1429f,61.9048f}, + {52.381f,66.6667f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch59st1[] = +{ + {57.1429f,4.7619f}, + {52.381f,0.0f}, + {47.6191f,4.7619f}, + {52.381f,9.5238f}, + {57.1429f,4.7619f}, + {57.1429f,-4.7619f}, + {52.381f,-14.2857f}, + {47.6191f,-19.0476f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch59st[] = +{ + {5,StrokeMonoRoman_ch59st0}, + {8,StrokeMonoRoman_ch59st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch59 = {104.762f,2,StrokeMonoRoman_ch59st}; + +/* char: 0x3c */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch60st0[] = +{ + {90.4762f,85.7143f}, + {14.2857f,42.8571f}, + {90.4762f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch60st[] = +{ + {3,StrokeMonoRoman_ch60st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch60 = {104.762f,1,StrokeMonoRoman_ch60st}; + +/* char: 0x3d */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch61st0[] = +{ + {9.5238f,57.1429f}, + {95.2381f,57.1429f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch61st1[] = +{ + {9.5238f,28.5714f}, + {95.2381f,28.5714f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch61st[] = +{ + {2,StrokeMonoRoman_ch61st0}, + {2,StrokeMonoRoman_ch61st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch61 = {104.762f,2,StrokeMonoRoman_ch61st}; + +/* char: 0x3e */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch62st0[] = +{ + {14.2857f,85.7143f}, + {90.4762f,42.8571f}, + {14.2857f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch62st[] = +{ + {3,StrokeMonoRoman_ch62st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch62 = {104.762f,1,StrokeMonoRoman_ch62st}; + +/* char: 0x3f */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch63st0[] = +{ + {23.8095f,76.1905f}, + {23.8095f,80.9524f}, + {28.5714f,90.4762f}, + {33.3333f,95.2381f}, + {42.8571f,100.0f}, + {61.9047f,100.0f}, + {71.4285f,95.2381f}, + {76.1905f,90.4762f}, + {80.9524f,80.9524f}, + {80.9524f,71.4286f}, + {76.1905f,61.9048f}, + {71.4285f,57.1429f}, + {52.3809f,47.619f}, + {52.3809f,33.3333f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch63st1[] = +{ + {52.3809f,9.5238f}, + {47.619f,4.7619f}, + {52.3809f,0.0f}, + {57.1428f,4.7619f}, + {52.3809f,9.5238f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch63st[] = +{ + {14,StrokeMonoRoman_ch63st0}, + {5,StrokeMonoRoman_ch63st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch63 = {104.762f,2,StrokeMonoRoman_ch63st}; + +/* char: 0x40 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch64st0[] = +{ + {64.2857f,52.381f}, + {54.7619f,57.1429f}, + {45.2381f,57.1429f}, + {40.4762f,47.619f}, + {40.4762f,42.8571f}, + {45.2381f,33.3333f}, + {54.7619f,33.3333f}, + {64.2857f,38.0952f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch64st1[] = +{ + {64.2857f,57.1429f}, + {64.2857f,38.0952f}, + {69.0476f,33.3333f}, + {78.5714f,33.3333f}, + {83.3334f,42.8571f}, + {83.3334f,47.619f}, + {78.5714f,61.9048f}, + {69.0476f,71.4286f}, + {54.7619f,76.1905f}, + {50.0f,76.1905f}, + {35.7143f,71.4286f}, + {26.1905f,61.9048f}, + {21.4286f,47.619f}, + {21.4286f,42.8571f}, + {26.1905f,28.5714f}, + {35.7143f,19.0476f}, + {50.0f,14.2857f}, + {54.7619f,14.2857f}, + {69.0476f,19.0476f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch64st[] = +{ + {8,StrokeMonoRoman_ch64st0}, + {19,StrokeMonoRoman_ch64st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch64 = {104.762f,2,StrokeMonoRoman_ch64st}; + +/* char: 0x41 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch65st0[] = +{ + {52.3809f,100.0f}, + {14.2857f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch65st1[] = +{ + {52.3809f,100.0f}, + {90.4762f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch65st2[] = +{ + {28.5714f,33.3333f}, + {76.1905f,33.3333f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch65st[] = +{ + {2,StrokeMonoRoman_ch65st0}, + {2,StrokeMonoRoman_ch65st1}, + {2,StrokeMonoRoman_ch65st2} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch65 = {104.762f,3,StrokeMonoRoman_ch65st}; + +/* char: 0x42 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch66st0[] = +{ + {19.0476f,100.0f}, + {19.0476f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch66st1[] = +{ + {19.0476f,100.0f}, + {61.9047f,100.0f}, + {76.1905f,95.2381f}, + {80.9524f,90.4762f}, + {85.7143f,80.9524f}, + {85.7143f,71.4286f}, + {80.9524f,61.9048f}, + {76.1905f,57.1429f}, + {61.9047f,52.381f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch66st2[] = +{ + {19.0476f,52.381f}, + {61.9047f,52.381f}, + {76.1905f,47.619f}, + {80.9524f,42.8571f}, + {85.7143f,33.3333f}, + {85.7143f,19.0476f}, + {80.9524f,9.5238f}, + {76.1905f,4.7619f}, + {61.9047f,0.0f}, + {19.0476f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch66st[] = +{ + {2,StrokeMonoRoman_ch66st0}, + {9,StrokeMonoRoman_ch66st1}, + {10,StrokeMonoRoman_ch66st2} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch66 = {104.762f,3,StrokeMonoRoman_ch66st}; + +/* char: 0x43 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch67st0[] = +{ + {88.0952f,76.1905f}, + {83.3334f,85.7143f}, + {73.8096f,95.2381f}, + {64.2857f,100.0f}, + {45.2381f,100.0f}, + {35.7143f,95.2381f}, + {26.1905f,85.7143f}, + {21.4286f,76.1905f}, + {16.6667f,61.9048f}, + {16.6667f,38.0952f}, + {21.4286f,23.8095f}, + {26.1905f,14.2857f}, + {35.7143f,4.7619f}, + {45.2381f,0.0f}, + {64.2857f,0.0f}, + {73.8096f,4.7619f}, + {83.3334f,14.2857f}, + {88.0952f,23.8095f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch67st[] = +{ + {18,StrokeMonoRoman_ch67st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch67 = {104.762f,1,StrokeMonoRoman_ch67st}; + +/* char: 0x44 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch68st0[] = +{ + {19.0476f,100.0f}, + {19.0476f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch68st1[] = +{ + {19.0476f,100.0f}, + {52.3809f,100.0f}, + {66.6666f,95.2381f}, + {76.1905f,85.7143f}, + {80.9524f,76.1905f}, + {85.7143f,61.9048f}, + {85.7143f,38.0952f}, + {80.9524f,23.8095f}, + {76.1905f,14.2857f}, + {66.6666f,4.7619f}, + {52.3809f,0.0f}, + {19.0476f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch68st[] = +{ + {2,StrokeMonoRoman_ch68st0}, + {12,StrokeMonoRoman_ch68st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch68 = {104.762f,2,StrokeMonoRoman_ch68st}; + +/* char: 0x45 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch69st0[] = +{ + {21.4286f,100.0f}, + {21.4286f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch69st1[] = +{ + {21.4286f,100.0f}, + {83.3334f,100.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch69st2[] = +{ + {21.4286f,52.381f}, + {59.5238f,52.381f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch69st3[] = +{ + {21.4286f,0.0f}, + {83.3334f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch69st[] = +{ + {2,StrokeMonoRoman_ch69st0}, + {2,StrokeMonoRoman_ch69st1}, + {2,StrokeMonoRoman_ch69st2}, + {2,StrokeMonoRoman_ch69st3} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch69 = {104.762f,4,StrokeMonoRoman_ch69st}; + +/* char: 0x46 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch70st0[] = +{ + {21.4286f,100.0f}, + {21.4286f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch70st1[] = +{ + {21.4286f,100.0f}, + {83.3334f,100.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch70st2[] = +{ + {21.4286f,52.381f}, + {59.5238f,52.381f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch70st[] = +{ + {2,StrokeMonoRoman_ch70st0}, + {2,StrokeMonoRoman_ch70st1}, + {2,StrokeMonoRoman_ch70st2} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch70 = {104.762f,3,StrokeMonoRoman_ch70st}; + +/* char: 0x47 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch71st0[] = +{ + {88.0952f,76.1905f}, + {83.3334f,85.7143f}, + {73.8096f,95.2381f}, + {64.2857f,100.0f}, + {45.2381f,100.0f}, + {35.7143f,95.2381f}, + {26.1905f,85.7143f}, + {21.4286f,76.1905f}, + {16.6667f,61.9048f}, + {16.6667f,38.0952f}, + {21.4286f,23.8095f}, + {26.1905f,14.2857f}, + {35.7143f,4.7619f}, + {45.2381f,0.0f}, + {64.2857f,0.0f}, + {73.8096f,4.7619f}, + {83.3334f,14.2857f}, + {88.0952f,23.8095f}, + {88.0952f,38.0952f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch71st1[] = +{ + {64.2857f,38.0952f}, + {88.0952f,38.0952f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch71st[] = +{ + {19,StrokeMonoRoman_ch71st0}, + {2,StrokeMonoRoman_ch71st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch71 = {104.762f,2,StrokeMonoRoman_ch71st}; + +/* char: 0x48 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch72st0[] = +{ + {19.0476f,100.0f}, + {19.0476f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch72st1[] = +{ + {85.7143f,100.0f}, + {85.7143f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch72st2[] = +{ + {19.0476f,52.381f}, + {85.7143f,52.381f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch72st[] = +{ + {2,StrokeMonoRoman_ch72st0}, + {2,StrokeMonoRoman_ch72st1}, + {2,StrokeMonoRoman_ch72st2} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch72 = {104.762f,3,StrokeMonoRoman_ch72st}; + +/* char: 0x49 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch73st0[] = +{ + {52.381f,100.0f}, + {52.381f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch73st[] = +{ + {2,StrokeMonoRoman_ch73st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch73 = {104.762f,1,StrokeMonoRoman_ch73st}; + +/* char: 0x4a */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch74st0[] = +{ + {76.1905f,100.0f}, + {76.1905f,23.8095f}, + {71.4286f,9.5238f}, + {66.6667f,4.7619f}, + {57.1429f,0.0f}, + {47.6191f,0.0f}, + {38.0953f,4.7619f}, + {33.3334f,9.5238f}, + {28.5715f,23.8095f}, + {28.5715f,33.3333f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch74st[] = +{ + {10,StrokeMonoRoman_ch74st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch74 = {104.762f,1,StrokeMonoRoman_ch74st}; + +/* char: 0x4b */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch75st0[] = +{ + {19.0476f,100.0f}, + {19.0476f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch75st1[] = +{ + {85.7143f,100.0f}, + {19.0476f,33.3333f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch75st2[] = +{ + {42.8571f,57.1429f}, + {85.7143f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch75st[] = +{ + {2,StrokeMonoRoman_ch75st0}, + {2,StrokeMonoRoman_ch75st1}, + {2,StrokeMonoRoman_ch75st2} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch75 = {104.762f,3,StrokeMonoRoman_ch75st}; + +/* char: 0x4c */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch76st0[] = +{ + {23.8095f,100.0f}, + {23.8095f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch76st1[] = +{ + {23.8095f,0.0f}, + {80.9524f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch76st[] = +{ + {2,StrokeMonoRoman_ch76st0}, + {2,StrokeMonoRoman_ch76st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch76 = {104.762f,2,StrokeMonoRoman_ch76st}; + +/* char: 0x4d */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch77st0[] = +{ + {14.2857f,100.0f}, + {14.2857f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch77st1[] = +{ + {14.2857f,100.0f}, + {52.3809f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch77st2[] = +{ + {90.4762f,100.0f}, + {52.3809f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch77st3[] = +{ + {90.4762f,100.0f}, + {90.4762f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch77st[] = +{ + {2,StrokeMonoRoman_ch77st0}, + {2,StrokeMonoRoman_ch77st1}, + {2,StrokeMonoRoman_ch77st2}, + {2,StrokeMonoRoman_ch77st3} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch77 = {104.762f,4,StrokeMonoRoman_ch77st}; + +/* char: 0x4e */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch78st0[] = +{ + {19.0476f,100.0f}, + {19.0476f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch78st1[] = +{ + {19.0476f,100.0f}, + {85.7143f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch78st2[] = +{ + {85.7143f,100.0f}, + {85.7143f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch78st[] = +{ + {2,StrokeMonoRoman_ch78st0}, + {2,StrokeMonoRoman_ch78st1}, + {2,StrokeMonoRoman_ch78st2} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch78 = {104.762f,3,StrokeMonoRoman_ch78st}; + +/* char: 0x4f */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch79st0[] = +{ + {42.8571f,100.0f}, + {33.3333f,95.2381f}, + {23.8095f,85.7143f}, + {19.0476f,76.1905f}, + {14.2857f,61.9048f}, + {14.2857f,38.0952f}, + {19.0476f,23.8095f}, + {23.8095f,14.2857f}, + {33.3333f,4.7619f}, + {42.8571f,0.0f}, + {61.9047f,0.0f}, + {71.4286f,4.7619f}, + {80.9524f,14.2857f}, + {85.7143f,23.8095f}, + {90.4762f,38.0952f}, + {90.4762f,61.9048f}, + {85.7143f,76.1905f}, + {80.9524f,85.7143f}, + {71.4286f,95.2381f}, + {61.9047f,100.0f}, + {42.8571f,100.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch79st[] = +{ + {21,StrokeMonoRoman_ch79st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch79 = {104.762f,1,StrokeMonoRoman_ch79st}; + +/* char: 0x50 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch80st0[] = +{ + {19.0476f,100.0f}, + {19.0476f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch80st1[] = +{ + {19.0476f,100.0f}, + {61.9047f,100.0f}, + {76.1905f,95.2381f}, + {80.9524f,90.4762f}, + {85.7143f,80.9524f}, + {85.7143f,66.6667f}, + {80.9524f,57.1429f}, + {76.1905f,52.381f}, + {61.9047f,47.619f}, + {19.0476f,47.619f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch80st[] = +{ + {2,StrokeMonoRoman_ch80st0}, + {10,StrokeMonoRoman_ch80st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch80 = {104.762f,2,StrokeMonoRoman_ch80st}; + +/* char: 0x51 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch81st0[] = +{ + {42.8571f,100.0f}, + {33.3333f,95.2381f}, + {23.8095f,85.7143f}, + {19.0476f,76.1905f}, + {14.2857f,61.9048f}, + {14.2857f,38.0952f}, + {19.0476f,23.8095f}, + {23.8095f,14.2857f}, + {33.3333f,4.7619f}, + {42.8571f,0.0f}, + {61.9047f,0.0f}, + {71.4286f,4.7619f}, + {80.9524f,14.2857f}, + {85.7143f,23.8095f}, + {90.4762f,38.0952f}, + {90.4762f,61.9048f}, + {85.7143f,76.1905f}, + {80.9524f,85.7143f}, + {71.4286f,95.2381f}, + {61.9047f,100.0f}, + {42.8571f,100.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch81st1[] = +{ + {57.1428f,19.0476f}, + {85.7143f,-9.5238f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch81st[] = +{ + {21,StrokeMonoRoman_ch81st0}, + {2,StrokeMonoRoman_ch81st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch81 = {104.762f,2,StrokeMonoRoman_ch81st}; + +/* char: 0x52 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch82st0[] = +{ + {19.0476f,100.0f}, + {19.0476f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch82st1[] = +{ + {19.0476f,100.0f}, + {61.9047f,100.0f}, + {76.1905f,95.2381f}, + {80.9524f,90.4762f}, + {85.7143f,80.9524f}, + {85.7143f,71.4286f}, + {80.9524f,61.9048f}, + {76.1905f,57.1429f}, + {61.9047f,52.381f}, + {19.0476f,52.381f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch82st2[] = +{ + {52.3809f,52.381f}, + {85.7143f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch82st[] = +{ + {2,StrokeMonoRoman_ch82st0}, + {10,StrokeMonoRoman_ch82st1}, + {2,StrokeMonoRoman_ch82st2} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch82 = {104.762f,3,StrokeMonoRoman_ch82st}; + +/* char: 0x53 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch83st0[] = +{ + {85.7143f,85.7143f}, + {76.1905f,95.2381f}, + {61.9047f,100.0f}, + {42.8571f,100.0f}, + {28.5714f,95.2381f}, + {19.0476f,85.7143f}, + {19.0476f,76.1905f}, + {23.8095f,66.6667f}, + {28.5714f,61.9048f}, + {38.0952f,57.1429f}, + {66.6666f,47.619f}, + {76.1905f,42.8571f}, + {80.9524f,38.0952f}, + {85.7143f,28.5714f}, + {85.7143f,14.2857f}, + {76.1905f,4.7619f}, + {61.9047f,0.0f}, + {42.8571f,0.0f}, + {28.5714f,4.7619f}, + {19.0476f,14.2857f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch83st[] = +{ + {20,StrokeMonoRoman_ch83st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch83 = {104.762f,1,StrokeMonoRoman_ch83st}; + +/* char: 0x54 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch84st0[] = +{ + {52.3809f,100.0f}, + {52.3809f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch84st1[] = +{ + {19.0476f,100.0f}, + {85.7143f,100.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch84st[] = +{ + {2,StrokeMonoRoman_ch84st0}, + {2,StrokeMonoRoman_ch84st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch84 = {104.762f,2,StrokeMonoRoman_ch84st}; + +/* char: 0x55 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch85st0[] = +{ + {19.0476f,100.0f}, + {19.0476f,28.5714f}, + {23.8095f,14.2857f}, + {33.3333f,4.7619f}, + {47.619f,0.0f}, + {57.1428f,0.0f}, + {71.4286f,4.7619f}, + {80.9524f,14.2857f}, + {85.7143f,28.5714f}, + {85.7143f,100.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch85st[] = +{ + {10,StrokeMonoRoman_ch85st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch85 = {104.762f,1,StrokeMonoRoman_ch85st}; + +/* char: 0x56 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch86st0[] = +{ + {14.2857f,100.0f}, + {52.3809f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch86st1[] = +{ + {90.4762f,100.0f}, + {52.3809f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch86st[] = +{ + {2,StrokeMonoRoman_ch86st0}, + {2,StrokeMonoRoman_ch86st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch86 = {104.762f,2,StrokeMonoRoman_ch86st}; + +/* char: 0x57 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch87st0[] = +{ + {4.7619f,100.0f}, + {28.5714f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch87st1[] = +{ + {52.3809f,100.0f}, + {28.5714f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch87st2[] = +{ + {52.3809f,100.0f}, + {76.1905f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch87st3[] = +{ + {100.0f,100.0f}, + {76.1905f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch87st[] = +{ + {2,StrokeMonoRoman_ch87st0}, + {2,StrokeMonoRoman_ch87st1}, + {2,StrokeMonoRoman_ch87st2}, + {2,StrokeMonoRoman_ch87st3} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch87 = {104.762f,4,StrokeMonoRoman_ch87st}; + +/* char: 0x58 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch88st0[] = +{ + {19.0476f,100.0f}, + {85.7143f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch88st1[] = +{ + {85.7143f,100.0f}, + {19.0476f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch88st[] = +{ + {2,StrokeMonoRoman_ch88st0}, + {2,StrokeMonoRoman_ch88st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch88 = {104.762f,2,StrokeMonoRoman_ch88st}; + +/* char: 0x59 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch89st0[] = +{ + {14.2857f,100.0f}, + {52.3809f,52.381f}, + {52.3809f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch89st1[] = +{ + {90.4762f,100.0f}, + {52.3809f,52.381f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch89st[] = +{ + {3,StrokeMonoRoman_ch89st0}, + {2,StrokeMonoRoman_ch89st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch89 = {104.762f,2,StrokeMonoRoman_ch89st}; + +/* char: 0x5a */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch90st0[] = +{ + {85.7143f,100.0f}, + {19.0476f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch90st1[] = +{ + {19.0476f,100.0f}, + {85.7143f,100.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch90st2[] = +{ + {19.0476f,0.0f}, + {85.7143f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch90st[] = +{ + {2,StrokeMonoRoman_ch90st0}, + {2,StrokeMonoRoman_ch90st1}, + {2,StrokeMonoRoman_ch90st2} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch90 = {104.762f,3,StrokeMonoRoman_ch90st}; + +/* char: 0x5b */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch91st0[] = +{ + {35.7143f,119.048f}, + {35.7143f,-33.3333f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch91st1[] = +{ + {40.4762f,119.048f}, + {40.4762f,-33.3333f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch91st2[] = +{ + {35.7143f,119.048f}, + {69.0476f,119.048f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch91st3[] = +{ + {35.7143f,-33.3333f}, + {69.0476f,-33.3333f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch91st[] = +{ + {2,StrokeMonoRoman_ch91st0}, + {2,StrokeMonoRoman_ch91st1}, + {2,StrokeMonoRoman_ch91st2}, + {2,StrokeMonoRoman_ch91st3} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch91 = {104.762f,4,StrokeMonoRoman_ch91st}; + +/* char: 0x5c */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch92st0[] = +{ + {19.0476f,100.0f}, + {85.7143f,-14.2857f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch92st[] = +{ + {2,StrokeMonoRoman_ch92st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch92 = {104.762f,1,StrokeMonoRoman_ch92st}; + +/* char: 0x5d */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch93st0[] = +{ + {64.2857f,119.048f}, + {64.2857f,-33.3333f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch93st1[] = +{ + {69.0476f,119.048f}, + {69.0476f,-33.3333f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch93st2[] = +{ + {35.7143f,119.048f}, + {69.0476f,119.048f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch93st3[] = +{ + {35.7143f,-33.3333f}, + {69.0476f,-33.3333f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch93st[] = +{ + {2,StrokeMonoRoman_ch93st0}, + {2,StrokeMonoRoman_ch93st1}, + {2,StrokeMonoRoman_ch93st2}, + {2,StrokeMonoRoman_ch93st3} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch93 = {104.762f,4,StrokeMonoRoman_ch93st}; + +/* char: 0x5e */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch94st0[] = +{ + {52.3809f,109.524f}, + {14.2857f,42.8571f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch94st1[] = +{ + {52.3809f,109.524f}, + {90.4762f,42.8571f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch94st[] = +{ + {2,StrokeMonoRoman_ch94st0}, + {2,StrokeMonoRoman_ch94st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch94 = {104.762f,2,StrokeMonoRoman_ch94st}; + +/* char: 0x5f */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch95st0[] = +{ + {0,-33.3333f}, + {104.762f,-33.3333f}, + {104.762f,-28.5714f}, + {0,-28.5714f}, + {0,-33.3333f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch95st[] = +{ + {5,StrokeMonoRoman_ch95st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch95 = {104.762f,1,StrokeMonoRoman_ch95st}; + +/* char: 0x60 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch96st0[] = +{ + {42.8572f,100.0f}, + {66.6667f,71.4286f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch96st1[] = +{ + {42.8572f,100.0f}, + {38.0953f,95.2381f}, + {66.6667f,71.4286f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch96st[] = +{ + {2,StrokeMonoRoman_ch96st0}, + {3,StrokeMonoRoman_ch96st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch96 = {104.762f,2,StrokeMonoRoman_ch96st}; + +/* char: 0x61 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch97st0[] = +{ + {80.9524f,66.6667f}, + {80.9524f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch97st1[] = +{ + {80.9524f,52.381f}, + {71.4285f,61.9048f}, + {61.9047f,66.6667f}, + {47.619f,66.6667f}, + {38.0952f,61.9048f}, + {28.5714f,52.381f}, + {23.8095f,38.0952f}, + {23.8095f,28.5714f}, + {28.5714f,14.2857f}, + {38.0952f,4.7619f}, + {47.619f,0.0f}, + {61.9047f,0.0f}, + {71.4285f,4.7619f}, + {80.9524f,14.2857f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch97st[] = +{ + {2,StrokeMonoRoman_ch97st0}, + {14,StrokeMonoRoman_ch97st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch97 = {104.762f,2,StrokeMonoRoman_ch97st}; + +/* char: 0x62 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch98st0[] = +{ + {23.8095f,100.0f}, + {23.8095f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch98st1[] = +{ + {23.8095f,52.381f}, + {33.3333f,61.9048f}, + {42.8571f,66.6667f}, + {57.1428f,66.6667f}, + {66.6666f,61.9048f}, + {76.1905f,52.381f}, + {80.9524f,38.0952f}, + {80.9524f,28.5714f}, + {76.1905f,14.2857f}, + {66.6666f,4.7619f}, + {57.1428f,0.0f}, + {42.8571f,0.0f}, + {33.3333f,4.7619f}, + {23.8095f,14.2857f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch98st[] = +{ + {2,StrokeMonoRoman_ch98st0}, + {14,StrokeMonoRoman_ch98st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch98 = {104.762f,2,StrokeMonoRoman_ch98st}; + +/* char: 0x63 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch99st0[] = +{ + {80.9524f,52.381f}, + {71.4285f,61.9048f}, + {61.9047f,66.6667f}, + {47.619f,66.6667f}, + {38.0952f,61.9048f}, + {28.5714f,52.381f}, + {23.8095f,38.0952f}, + {23.8095f,28.5714f}, + {28.5714f,14.2857f}, + {38.0952f,4.7619f}, + {47.619f,0.0f}, + {61.9047f,0.0f}, + {71.4285f,4.7619f}, + {80.9524f,14.2857f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch99st[] = +{ + {14,StrokeMonoRoman_ch99st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch99 = {104.762f,1,StrokeMonoRoman_ch99st}; + +/* char: 0x64 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch100st0[] = +{ + {80.9524f,100.0f}, + {80.9524f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch100st1[] = +{ + {80.9524f,52.381f}, + {71.4285f,61.9048f}, + {61.9047f,66.6667f}, + {47.619f,66.6667f}, + {38.0952f,61.9048f}, + {28.5714f,52.381f}, + {23.8095f,38.0952f}, + {23.8095f,28.5714f}, + {28.5714f,14.2857f}, + {38.0952f,4.7619f}, + {47.619f,0.0f}, + {61.9047f,0.0f}, + {71.4285f,4.7619f}, + {80.9524f,14.2857f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch100st[] = +{ + {2,StrokeMonoRoman_ch100st0}, + {14,StrokeMonoRoman_ch100st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch100 = {104.762f,2,StrokeMonoRoman_ch100st}; + +/* char: 0x65 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch101st0[] = +{ + {23.8095f,38.0952f}, + {80.9524f,38.0952f}, + {80.9524f,47.619f}, + {76.1905f,57.1429f}, + {71.4285f,61.9048f}, + {61.9047f,66.6667f}, + {47.619f,66.6667f}, + {38.0952f,61.9048f}, + {28.5714f,52.381f}, + {23.8095f,38.0952f}, + {23.8095f,28.5714f}, + {28.5714f,14.2857f}, + {38.0952f,4.7619f}, + {47.619f,0.0f}, + {61.9047f,0.0f}, + {71.4285f,4.7619f}, + {80.9524f,14.2857f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch101st[] = +{ + {17,StrokeMonoRoman_ch101st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch101 = {104.762f,1,StrokeMonoRoman_ch101st}; + +/* char: 0x66 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch102st0[] = +{ + {71.4286f,100.0f}, + {61.9048f,100.0f}, + {52.381f,95.2381f}, + {47.6191f,80.9524f}, + {47.6191f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch102st1[] = +{ + {33.3334f,66.6667f}, + {66.6667f,66.6667f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch102st[] = +{ + {5,StrokeMonoRoman_ch102st0}, + {2,StrokeMonoRoman_ch102st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch102 = {104.762f,2,StrokeMonoRoman_ch102st}; + +/* char: 0x67 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch103st0[] = +{ + {80.9524f,66.6667f}, + {80.9524f,-9.5238f}, + {76.1905f,-23.8095f}, + {71.4285f,-28.5714f}, + {61.9047f,-33.3333f}, + {47.619f,-33.3333f}, + {38.0952f,-28.5714f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch103st1[] = +{ + {80.9524f,52.381f}, + {71.4285f,61.9048f}, + {61.9047f,66.6667f}, + {47.619f,66.6667f}, + {38.0952f,61.9048f}, + {28.5714f,52.381f}, + {23.8095f,38.0952f}, + {23.8095f,28.5714f}, + {28.5714f,14.2857f}, + {38.0952f,4.7619f}, + {47.619f,0.0f}, + {61.9047f,0.0f}, + {71.4285f,4.7619f}, + {80.9524f,14.2857f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch103st[] = +{ + {7,StrokeMonoRoman_ch103st0}, + {14,StrokeMonoRoman_ch103st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch103 = {104.762f,2,StrokeMonoRoman_ch103st}; + +/* char: 0x68 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch104st0[] = +{ + {26.1905f,100.0f}, + {26.1905f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch104st1[] = +{ + {26.1905f,47.619f}, + {40.4762f,61.9048f}, + {50.0f,66.6667f}, + {64.2857f,66.6667f}, + {73.8095f,61.9048f}, + {78.5715f,47.619f}, + {78.5715f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch104st[] = +{ + {2,StrokeMonoRoman_ch104st0}, + {7,StrokeMonoRoman_ch104st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch104 = {104.762f,2,StrokeMonoRoman_ch104st}; + +/* char: 0x69 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch105st0[] = +{ + {47.6191f,100.0f}, + {52.381f,95.2381f}, + {57.1429f,100.0f}, + {52.381f,104.762f}, + {47.6191f,100.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch105st1[] = +{ + {52.381f,66.6667f}, + {52.381f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch105st[] = +{ + {5,StrokeMonoRoman_ch105st0}, + {2,StrokeMonoRoman_ch105st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch105 = {104.762f,2,StrokeMonoRoman_ch105st}; + +/* char: 0x6a */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch106st0[] = +{ + {57.1429f,100.0f}, + {61.9048f,95.2381f}, + {66.6667f,100.0f}, + {61.9048f,104.762f}, + {57.1429f,100.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch106st1[] = +{ + {61.9048f,66.6667f}, + {61.9048f,-14.2857f}, + {57.1429f,-28.5714f}, + {47.6191f,-33.3333f}, + {38.0953f,-33.3333f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch106st[] = +{ + {5,StrokeMonoRoman_ch106st0}, + {5,StrokeMonoRoman_ch106st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch106 = {104.762f,2,StrokeMonoRoman_ch106st}; + +/* char: 0x6b */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch107st0[] = +{ + {26.1905f,100.0f}, + {26.1905f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch107st1[] = +{ + {73.8095f,66.6667f}, + {26.1905f,19.0476f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch107st2[] = +{ + {45.2381f,38.0952f}, + {78.5715f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch107st[] = +{ + {2,StrokeMonoRoman_ch107st0}, + {2,StrokeMonoRoman_ch107st1}, + {2,StrokeMonoRoman_ch107st2} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch107 = {104.762f,3,StrokeMonoRoman_ch107st}; + +/* char: 0x6c */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch108st0[] = +{ + {52.381f,100.0f}, + {52.381f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch108st[] = +{ + {2,StrokeMonoRoman_ch108st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch108 = {104.762f,1,StrokeMonoRoman_ch108st}; + +/* char: 0x6d */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch109st0[] = +{ + {0,66.6667f}, + {0,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch109st1[] = +{ + {0,47.619f}, + {14.2857f,61.9048f}, + {23.8095f,66.6667f}, + {38.0952f,66.6667f}, + {47.619f,61.9048f}, + {52.381f,47.619f}, + {52.381f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch109st2[] = +{ + {52.381f,47.619f}, + {66.6667f,61.9048f}, + {76.1905f,66.6667f}, + {90.4762f,66.6667f}, + {100.0f,61.9048f}, + {104.762f,47.619f}, + {104.762f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch109st[] = +{ + {2,StrokeMonoRoman_ch109st0}, + {7,StrokeMonoRoman_ch109st1}, + {7,StrokeMonoRoman_ch109st2} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch109 = {104.762f,3,StrokeMonoRoman_ch109st}; + +/* char: 0x6e */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch110st0[] = +{ + {26.1905f,66.6667f}, + {26.1905f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch110st1[] = +{ + {26.1905f,47.619f}, + {40.4762f,61.9048f}, + {50.0f,66.6667f}, + {64.2857f,66.6667f}, + {73.8095f,61.9048f}, + {78.5715f,47.619f}, + {78.5715f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch110st[] = +{ + {2,StrokeMonoRoman_ch110st0}, + {7,StrokeMonoRoman_ch110st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch110 = {104.762f,2,StrokeMonoRoman_ch110st}; + +/* char: 0x6f */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch111st0[] = +{ + {45.2381f,66.6667f}, + {35.7143f,61.9048f}, + {26.1905f,52.381f}, + {21.4286f,38.0952f}, + {21.4286f,28.5714f}, + {26.1905f,14.2857f}, + {35.7143f,4.7619f}, + {45.2381f,0.0f}, + {59.5238f,0.0f}, + {69.0476f,4.7619f}, + {78.5714f,14.2857f}, + {83.3334f,28.5714f}, + {83.3334f,38.0952f}, + {78.5714f,52.381f}, + {69.0476f,61.9048f}, + {59.5238f,66.6667f}, + {45.2381f,66.6667f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch111st[] = +{ + {17,StrokeMonoRoman_ch111st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch111 = {104.762f,1,StrokeMonoRoman_ch111st}; + +/* char: 0x70 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch112st0[] = +{ + {23.8095f,66.6667f}, + {23.8095f,-33.3333f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch112st1[] = +{ + {23.8095f,52.381f}, + {33.3333f,61.9048f}, + {42.8571f,66.6667f}, + {57.1428f,66.6667f}, + {66.6666f,61.9048f}, + {76.1905f,52.381f}, + {80.9524f,38.0952f}, + {80.9524f,28.5714f}, + {76.1905f,14.2857f}, + {66.6666f,4.7619f}, + {57.1428f,0.0f}, + {42.8571f,0.0f}, + {33.3333f,4.7619f}, + {23.8095f,14.2857f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch112st[] = +{ + {2,StrokeMonoRoman_ch112st0}, + {14,StrokeMonoRoman_ch112st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch112 = {104.762f,2,StrokeMonoRoman_ch112st}; + +/* char: 0x71 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch113st0[] = +{ + {80.9524f,66.6667f}, + {80.9524f,-33.3333f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch113st1[] = +{ + {80.9524f,52.381f}, + {71.4285f,61.9048f}, + {61.9047f,66.6667f}, + {47.619f,66.6667f}, + {38.0952f,61.9048f}, + {28.5714f,52.381f}, + {23.8095f,38.0952f}, + {23.8095f,28.5714f}, + {28.5714f,14.2857f}, + {38.0952f,4.7619f}, + {47.619f,0.0f}, + {61.9047f,0.0f}, + {71.4285f,4.7619f}, + {80.9524f,14.2857f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch113st[] = +{ + {2,StrokeMonoRoman_ch113st0}, + {14,StrokeMonoRoman_ch113st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch113 = {104.762f,2,StrokeMonoRoman_ch113st}; + +/* char: 0x72 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch114st0[] = +{ + {33.3334f,66.6667f}, + {33.3334f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch114st1[] = +{ + {33.3334f,38.0952f}, + {38.0953f,52.381f}, + {47.6191f,61.9048f}, + {57.1429f,66.6667f}, + {71.4286f,66.6667f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch114st[] = +{ + {2,StrokeMonoRoman_ch114st0}, + {5,StrokeMonoRoman_ch114st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch114 = {104.762f,2,StrokeMonoRoman_ch114st}; + +/* char: 0x73 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch115st0[] = +{ + {78.5715f,52.381f}, + {73.8095f,61.9048f}, + {59.5238f,66.6667f}, + {45.2381f,66.6667f}, + {30.9524f,61.9048f}, + {26.1905f,52.381f}, + {30.9524f,42.8571f}, + {40.4762f,38.0952f}, + {64.2857f,33.3333f}, + {73.8095f,28.5714f}, + {78.5715f,19.0476f}, + {78.5715f,14.2857f}, + {73.8095f,4.7619f}, + {59.5238f,0.0f}, + {45.2381f,0.0f}, + {30.9524f,4.7619f}, + {26.1905f,14.2857f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch115st[] = +{ + {17,StrokeMonoRoman_ch115st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch115 = {104.762f,1,StrokeMonoRoman_ch115st}; + +/* char: 0x74 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch116st0[] = +{ + {47.6191f,100.0f}, + {47.6191f,19.0476f}, + {52.381f,4.7619f}, + {61.9048f,0.0f}, + {71.4286f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch116st1[] = +{ + {33.3334f,66.6667f}, + {66.6667f,66.6667f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch116st[] = +{ + {5,StrokeMonoRoman_ch116st0}, + {2,StrokeMonoRoman_ch116st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch116 = {104.762f,2,StrokeMonoRoman_ch116st}; + +/* char: 0x75 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch117st0[] = +{ + {26.1905f,66.6667f}, + {26.1905f,19.0476f}, + {30.9524f,4.7619f}, + {40.4762f,0.0f}, + {54.7619f,0.0f}, + {64.2857f,4.7619f}, + {78.5715f,19.0476f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch117st1[] = +{ + {78.5715f,66.6667f}, + {78.5715f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch117st[] = +{ + {7,StrokeMonoRoman_ch117st0}, + {2,StrokeMonoRoman_ch117st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch117 = {104.762f,2,StrokeMonoRoman_ch117st}; + +/* char: 0x76 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch118st0[] = +{ + {23.8095f,66.6667f}, + {52.3809f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch118st1[] = +{ + {80.9524f,66.6667f}, + {52.3809f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch118st[] = +{ + {2,StrokeMonoRoman_ch118st0}, + {2,StrokeMonoRoman_ch118st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch118 = {104.762f,2,StrokeMonoRoman_ch118st}; + +/* char: 0x77 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch119st0[] = +{ + {14.2857f,66.6667f}, + {33.3333f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch119st1[] = +{ + {52.3809f,66.6667f}, + {33.3333f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch119st2[] = +{ + {52.3809f,66.6667f}, + {71.4286f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch119st3[] = +{ + {90.4762f,66.6667f}, + {71.4286f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch119st[] = +{ + {2,StrokeMonoRoman_ch119st0}, + {2,StrokeMonoRoman_ch119st1}, + {2,StrokeMonoRoman_ch119st2}, + {2,StrokeMonoRoman_ch119st3} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch119 = {104.762f,4,StrokeMonoRoman_ch119st}; + +/* char: 0x78 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch120st0[] = +{ + {26.1905f,66.6667f}, + {78.5715f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch120st1[] = +{ + {78.5715f,66.6667f}, + {26.1905f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch120st[] = +{ + {2,StrokeMonoRoman_ch120st0}, + {2,StrokeMonoRoman_ch120st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch120 = {104.762f,2,StrokeMonoRoman_ch120st}; + +/* char: 0x79 */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch121st0[] = +{ + {26.1905f,66.6667f}, + {54.7619f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch121st1[] = +{ + {83.3334f,66.6667f}, + {54.7619f,0.0f}, + {45.2381f,-19.0476f}, + {35.7143f,-28.5714f}, + {26.1905f,-33.3333f}, + {21.4286f,-33.3333f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch121st[] = +{ + {2,StrokeMonoRoman_ch121st0}, + {6,StrokeMonoRoman_ch121st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch121 = {104.762f,2,StrokeMonoRoman_ch121st}; + +/* char: 0x7a */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch122st0[] = +{ + {78.5715f,66.6667f}, + {26.1905f,0.0f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch122st1[] = +{ + {26.1905f,66.6667f}, + {78.5715f,66.6667f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch122st2[] = +{ + {26.1905f,0.0f}, + {78.5715f,0.0f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch122st[] = +{ + {2,StrokeMonoRoman_ch122st0}, + {2,StrokeMonoRoman_ch122st1}, + {2,StrokeMonoRoman_ch122st2} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch122 = {104.762f,3,StrokeMonoRoman_ch122st}; + +/* char: 0x7b */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch123st0[] = +{ + {64.2857f,119.048f}, + {54.7619f,114.286f}, + {50.0f,109.524f}, + {45.2381f,100.0f}, + {45.2381f,90.4762f}, + {50.0f,80.9524f}, + {54.7619f,76.1905f}, + {59.5238f,66.6667f}, + {59.5238f,57.1429f}, + {50.0f,47.619f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch123st1[] = +{ + {54.7619f,114.286f}, + {50.0f,104.762f}, + {50.0f,95.2381f}, + {54.7619f,85.7143f}, + {59.5238f,80.9524f}, + {64.2857f,71.4286f}, + {64.2857f,61.9048f}, + {59.5238f,52.381f}, + {40.4762f,42.8571f}, + {59.5238f,33.3333f}, + {64.2857f,23.8095f}, + {64.2857f,14.2857f}, + {59.5238f,4.7619f}, + {54.7619f,0.0f}, + {50.0f,-9.5238f}, + {50.0f,-19.0476f}, + {54.7619f,-28.5714f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch123st2[] = +{ + {50.0f,38.0952f}, + {59.5238f,28.5714f}, + {59.5238f,19.0476f}, + {54.7619f,9.5238f}, + {50.0f,4.7619f}, + {45.2381f,-4.7619f}, + {45.2381f,-14.2857f}, + {50.0f,-23.8095f}, + {54.7619f,-28.5714f}, + {64.2857f,-33.3333f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch123st[] = +{ + {10,StrokeMonoRoman_ch123st0}, + {17,StrokeMonoRoman_ch123st1}, + {10,StrokeMonoRoman_ch123st2} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch123 = {104.762f,3,StrokeMonoRoman_ch123st}; + +/* char: 0x7c */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch124st0[] = +{ + {52.381f,119.048f}, + {52.381f,-33.3333f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch124st[] = +{ + {2,StrokeMonoRoman_ch124st0} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch124 = {104.762f,1,StrokeMonoRoman_ch124st}; + +/* char: 0x7d */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch125st0[] = +{ + {40.4762f,119.048f}, + {50.0f,114.286f}, + {54.7619f,109.524f}, + {59.5238f,100.0f}, + {59.5238f,90.4762f}, + {54.7619f,80.9524f}, + {50.0f,76.1905f}, + {45.2381f,66.6667f}, + {45.2381f,57.1429f}, + {54.7619f,47.619f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch125st1[] = +{ + {50.0f,114.286f}, + {54.7619f,104.762f}, + {54.7619f,95.2381f}, + {50.0f,85.7143f}, + {45.2381f,80.9524f}, + {40.4762f,71.4286f}, + {40.4762f,61.9048f}, + {45.2381f,52.381f}, + {64.2857f,42.8571f}, + {45.2381f,33.3333f}, + {40.4762f,23.8095f}, + {40.4762f,14.2857f}, + {45.2381f,4.7619f}, + {50.0f,0.0f}, + {54.7619f,-9.5238f}, + {54.7619f,-19.0476f}, + {50.0f,-28.5714f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch125st2[] = +{ + {54.7619f,38.0952f}, + {45.2381f,28.5714f}, + {45.2381f,19.0476f}, + {50.0f,9.5238f}, + {54.7619f,4.7619f}, + {59.5238f,-4.7619f}, + {59.5238f,-14.2857f}, + {54.7619f,-23.8095f}, + {50.0f,-28.5714f}, + {40.4762f,-33.3333f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch125st[] = +{ + {10,StrokeMonoRoman_ch125st0}, + {17,StrokeMonoRoman_ch125st1}, + {10,StrokeMonoRoman_ch125st2} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch125 = {104.762f,3,StrokeMonoRoman_ch125st}; + +/* char: 0x7e */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch126st0[] = +{ + {9.5238f,28.5714f}, + {9.5238f,38.0952f}, + {14.2857f,52.381f}, + {23.8095f,57.1429f}, + {33.3333f,57.1429f}, + {42.8571f,52.381f}, + {61.9048f,38.0952f}, + {71.4286f,33.3333f}, + {80.9524f,33.3333f}, + {90.4762f,38.0952f}, + {95.2381f,47.619f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch126st1[] = +{ + {9.5238f,38.0952f}, + {14.2857f,47.619f}, + {23.8095f,52.381f}, + {33.3333f,52.381f}, + {42.8571f,47.619f}, + {61.9048f,33.3333f}, + {71.4286f,28.5714f}, + {80.9524f,28.5714f}, + {90.4762f,33.3333f}, + {95.2381f,47.619f}, + {95.2381f,57.1429f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch126st[] = +{ + {11,StrokeMonoRoman_ch126st0}, + {11,StrokeMonoRoman_ch126st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch126 = {104.762f,2,StrokeMonoRoman_ch126st}; + +/* char: 0x7f */ + +static const SFG_StrokeVertex StrokeMonoRoman_ch127st0[] = +{ + {71.4286f,100.0f}, + {33.3333f,-33.3333f} +}; + +static const SFG_StrokeVertex StrokeMonoRoman_ch127st1[] = +{ + {47.619f,66.6667f}, + {33.3333f,61.9048f}, + {23.8095f,52.381f}, + {19.0476f,38.0952f}, + {19.0476f,23.8095f}, + {23.8095f,14.2857f}, + {33.3333f,4.7619f}, + {47.619f,0.0f}, + {57.1428f,0.0f}, + {71.4286f,4.7619f}, + {80.9524f,14.2857f}, + {85.7143f,28.5714f}, + {85.7143f,42.8571f}, + {80.9524f,52.381f}, + {71.4286f,61.9048f}, + {57.1428f,66.6667f}, + {47.619f,66.6667f} +}; + +static const SFG_StrokeStrip StrokeMonoRoman_ch127st[] = +{ + {2,StrokeMonoRoman_ch127st0}, + {17,StrokeMonoRoman_ch127st1} +}; + +static const SFG_StrokeChar StrokeMonoRoman_ch127 = {104.762f,2,StrokeMonoRoman_ch127st}; + +static const SFG_StrokeChar *StrokeMonoRoman_chars[] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + &StrokeMonoRoman_ch32, &StrokeMonoRoman_ch33, &StrokeMonoRoman_ch34, &StrokeMonoRoman_ch35, &StrokeMonoRoman_ch36, &StrokeMonoRoman_ch37, &StrokeMonoRoman_ch38, &StrokeMonoRoman_ch39, + &StrokeMonoRoman_ch40, &StrokeMonoRoman_ch41, &StrokeMonoRoman_ch42, &StrokeMonoRoman_ch43, &StrokeMonoRoman_ch44, &StrokeMonoRoman_ch45, &StrokeMonoRoman_ch46, &StrokeMonoRoman_ch47, + &StrokeMonoRoman_ch48, &StrokeMonoRoman_ch49, &StrokeMonoRoman_ch50, &StrokeMonoRoman_ch51, &StrokeMonoRoman_ch52, &StrokeMonoRoman_ch53, &StrokeMonoRoman_ch54, &StrokeMonoRoman_ch55, + &StrokeMonoRoman_ch56, &StrokeMonoRoman_ch57, &StrokeMonoRoman_ch58, &StrokeMonoRoman_ch59, &StrokeMonoRoman_ch60, &StrokeMonoRoman_ch61, &StrokeMonoRoman_ch62, &StrokeMonoRoman_ch63, + &StrokeMonoRoman_ch64, &StrokeMonoRoman_ch65, &StrokeMonoRoman_ch66, &StrokeMonoRoman_ch67, &StrokeMonoRoman_ch68, &StrokeMonoRoman_ch69, &StrokeMonoRoman_ch70, &StrokeMonoRoman_ch71, + &StrokeMonoRoman_ch72, &StrokeMonoRoman_ch73, &StrokeMonoRoman_ch74, &StrokeMonoRoman_ch75, &StrokeMonoRoman_ch76, &StrokeMonoRoman_ch77, &StrokeMonoRoman_ch78, &StrokeMonoRoman_ch79, + &StrokeMonoRoman_ch80, &StrokeMonoRoman_ch81, &StrokeMonoRoman_ch82, &StrokeMonoRoman_ch83, &StrokeMonoRoman_ch84, &StrokeMonoRoman_ch85, &StrokeMonoRoman_ch86, &StrokeMonoRoman_ch87, + &StrokeMonoRoman_ch88, &StrokeMonoRoman_ch89, &StrokeMonoRoman_ch90, &StrokeMonoRoman_ch91, &StrokeMonoRoman_ch92, &StrokeMonoRoman_ch93, &StrokeMonoRoman_ch94, &StrokeMonoRoman_ch95, + &StrokeMonoRoman_ch96, &StrokeMonoRoman_ch97, &StrokeMonoRoman_ch98, &StrokeMonoRoman_ch99, &StrokeMonoRoman_ch100, &StrokeMonoRoman_ch101, &StrokeMonoRoman_ch102, &StrokeMonoRoman_ch103, + &StrokeMonoRoman_ch104, &StrokeMonoRoman_ch105, &StrokeMonoRoman_ch106, &StrokeMonoRoman_ch107, &StrokeMonoRoman_ch108, &StrokeMonoRoman_ch109, &StrokeMonoRoman_ch110, &StrokeMonoRoman_ch111, + &StrokeMonoRoman_ch112, &StrokeMonoRoman_ch113, &StrokeMonoRoman_ch114, &StrokeMonoRoman_ch115, &StrokeMonoRoman_ch116, &StrokeMonoRoman_ch117, &StrokeMonoRoman_ch118, &StrokeMonoRoman_ch119, + &StrokeMonoRoman_ch120, &StrokeMonoRoman_ch121, &StrokeMonoRoman_ch122, &StrokeMonoRoman_ch123, &StrokeMonoRoman_ch124, &StrokeMonoRoman_ch125, &StrokeMonoRoman_ch126, &StrokeMonoRoman_ch127 +}; + +SFG_StrokeFont fgStrokeMonoRoman = {"MonoRoman",128,152.381f,StrokeMonoRoman_chars}; diff --git a/src/fg_stroke_roman.c b/src/fg_stroke_roman.c new file mode 100644 index 0000000..340d0c8 --- /dev/null +++ b/src/fg_stroke_roman.c @@ -0,0 +1,2849 @@ +/* + * fg_stroke_roman.c + * + * freeglut Roman stroke font definition + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Thu Dec 16 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* This file has been automatically generated by the genstroke utility. */ + +#include +#include "fg_internal.h" + +/* char: 0x20 */ + +static const SFG_StrokeStrip StrokeRoman_ch32st[] = +{ + { 0, NULL } +}; + +static const SFG_StrokeChar StrokeRoman_ch32 = {104.762f,0,StrokeRoman_ch32st}; + +/* char: 0x21 */ + +static const SFG_StrokeVertex StrokeRoman_ch33st0[] = +{ + {13.3819f,100.0f}, + {13.3819f,33.3333f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch33st1[] = +{ + {13.3819f,9.5238f}, + {8.62f,4.7619f}, + {13.3819f,0.0f}, + {18.1438f,4.7619f}, + {13.3819f,9.5238f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch33st[] = +{ + {2,StrokeRoman_ch33st0}, + {5,StrokeRoman_ch33st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch33 = {26.6238f,2,StrokeRoman_ch33st}; + +/* char: 0x22 */ + +static const SFG_StrokeVertex StrokeRoman_ch34st0[] = +{ + {4.02f,100.0f}, + {4.02f,66.6667f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch34st1[] = +{ + {42.1152f,100.0f}, + {42.1152f,66.6667f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch34st[] = +{ + {2,StrokeRoman_ch34st0}, + {2,StrokeRoman_ch34st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch34 = {51.4352f,2,StrokeRoman_ch34st}; + +/* char: 0x23 */ + +static const SFG_StrokeVertex StrokeRoman_ch35st0[] = +{ + {41.2952f,119.048f}, + {7.9619f,-33.3333f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch35st1[] = +{ + {69.8667f,119.048f}, + {36.5333f,-33.3333f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch35st2[] = +{ + {7.9619f,57.1429f}, + {74.6286f,57.1429f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch35st3[] = +{ + {3.2f,28.5714f}, + {69.8667f,28.5714f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch35st[] = +{ + {2,StrokeRoman_ch35st0}, + {2,StrokeRoman_ch35st1}, + {2,StrokeRoman_ch35st2}, + {2,StrokeRoman_ch35st3} +}; + +static const SFG_StrokeChar StrokeRoman_ch35 = {79.4886f,4,StrokeRoman_ch35st}; + +/* char: 0x24 */ + +static const SFG_StrokeVertex StrokeRoman_ch36st0[] = +{ + {28.6295f,119.048f}, + {28.6295f,-19.0476f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch36st1[] = +{ + {47.6771f,119.048f}, + {47.6771f,-19.0476f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch36st2[] = +{ + {71.4867f,85.7143f}, + {61.9629f,95.2381f}, + {47.6771f,100.0f}, + {28.6295f,100.0f}, + {14.3438f,95.2381f}, + {4.82f,85.7143f}, + {4.82f,76.1905f}, + {9.5819f,66.6667f}, + {14.3438f,61.9048f}, + {23.8676f,57.1429f}, + {52.439f,47.619f}, + {61.9629f,42.8571f}, + {66.7248f,38.0952f}, + {71.4867f,28.5714f}, + {71.4867f,14.2857f}, + {61.9629f,4.7619f}, + {47.6771f,0.0f}, + {28.6295f,0.0f}, + {14.3438f,4.7619f}, + {4.82f,14.2857f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch36st[] = +{ + {2,StrokeRoman_ch36st0}, + {2,StrokeRoman_ch36st1}, + {20,StrokeRoman_ch36st2} +}; + +static const SFG_StrokeChar StrokeRoman_ch36 = {76.2067f,3,StrokeRoman_ch36st}; + +/* char: 0x25 */ + +static const SFG_StrokeVertex StrokeRoman_ch37st0[] = +{ + {92.0743f,100.0f}, + {6.36f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch37st1[] = +{ + {30.1695f,100.0f}, + {39.6933f,90.4762f}, + {39.6933f,80.9524f}, + {34.9314f,71.4286f}, + {25.4076f,66.6667f}, + {15.8838f,66.6667f}, + {6.36f,76.1905f}, + {6.36f,85.7143f}, + {11.1219f,95.2381f}, + {20.6457f,100.0f}, + {30.1695f,100.0f}, + {39.6933f,95.2381f}, + {53.979f,90.4762f}, + {68.2648f,90.4762f}, + {82.5505f,95.2381f}, + {92.0743f,100.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch37st2[] = +{ + {73.0267f,33.3333f}, + {63.5029f,28.5714f}, + {58.741f,19.0476f}, + {58.741f,9.5238f}, + {68.2648f,0.0f}, + {77.7886f,0.0f}, + {87.3124f,4.7619f}, + {92.0743f,14.2857f}, + {92.0743f,23.8095f}, + {82.5505f,33.3333f}, + {73.0267f,33.3333f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch37st[] = +{ + {2,StrokeRoman_ch37st0}, + {16,StrokeRoman_ch37st1}, + {11,StrokeRoman_ch37st2} +}; + +static const SFG_StrokeChar StrokeRoman_ch37 = {96.5743f,3,StrokeRoman_ch37st}; + +/* char: 0x26 */ + +static const SFG_StrokeVertex StrokeRoman_ch38st0[] = +{ + {101.218f,57.1429f}, + {101.218f,61.9048f}, + {96.4562f,66.6667f}, + {91.6943f,66.6667f}, + {86.9324f,61.9048f}, + {82.1705f,52.381f}, + {72.6467f,28.5714f}, + {63.1229f,14.2857f}, + {53.599f,4.7619f}, + {44.0752f,0.0f}, + {25.0276f,0.0f}, + {15.5038f,4.7619f}, + {10.7419f,9.5238f}, + {5.98f,19.0476f}, + {5.98f,28.5714f}, + {10.7419f,38.0952f}, + {15.5038f,42.8571f}, + {48.8371f,61.9048f}, + {53.599f,66.6667f}, + {58.361f,76.1905f}, + {58.361f,85.7143f}, + {53.599f,95.2381f}, + {44.0752f,100.0f}, + {34.5514f,95.2381f}, + {29.7895f,85.7143f}, + {29.7895f,76.1905f}, + {34.5514f,61.9048f}, + {44.0752f,47.619f}, + {67.8848f,14.2857f}, + {77.4086f,4.7619f}, + {86.9324f,0.0f}, + {96.4562f,0.0f}, + {101.218f,4.7619f}, + {101.218f,9.5238f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch38st[] = +{ + {34,StrokeRoman_ch38st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch38 = {101.758f,1,StrokeRoman_ch38st}; + +/* char: 0x27 */ + +static const SFG_StrokeVertex StrokeRoman_ch39st0[] = +{ + {4.44f,100.0f}, + {4.44f,66.6667f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch39st[] = +{ + {2,StrokeRoman_ch39st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch39 = {13.62f,1,StrokeRoman_ch39st}; + +/* char: 0x28 */ + +static const SFG_StrokeVertex StrokeRoman_ch40st0[] = +{ + {40.9133f,119.048f}, + {31.3895f,109.524f}, + {21.8657f,95.2381f}, + {12.3419f,76.1905f}, + {7.58f,52.381f}, + {7.58f,33.3333f}, + {12.3419f,9.5238f}, + {21.8657f,-9.5238f}, + {31.3895f,-23.8095f}, + {40.9133f,-33.3333f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch40st[] = +{ + {10,StrokeRoman_ch40st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch40 = {47.1733f,1,StrokeRoman_ch40st}; + +/* char: 0x29 */ + +static const SFG_StrokeVertex StrokeRoman_ch41st0[] = +{ + {5.28f,119.048f}, + {14.8038f,109.524f}, + {24.3276f,95.2381f}, + {33.8514f,76.1905f}, + {38.6133f,52.381f}, + {38.6133f,33.3333f}, + {33.8514f,9.5238f}, + {24.3276f,-9.5238f}, + {14.8038f,-23.8095f}, + {5.28f,-33.3333f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch41st[] = +{ + {10,StrokeRoman_ch41st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch41 = {47.5333f,1,StrokeRoman_ch41st}; + +/* char: 0x2a */ + +static const SFG_StrokeVertex StrokeRoman_ch42st0[] = +{ + {30.7695f,71.4286f}, + {30.7695f,14.2857f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch42st1[] = +{ + {6.96f,57.1429f}, + {54.579f,28.5714f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch42st2[] = +{ + {54.579f,57.1429f}, + {6.96f,28.5714f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch42st[] = +{ + {2,StrokeRoman_ch42st0}, + {2,StrokeRoman_ch42st1}, + {2,StrokeRoman_ch42st2} +}; + +static const SFG_StrokeChar StrokeRoman_ch42 = {59.439f,3,StrokeRoman_ch42st}; + +/* char: 0x2b */ + +static const SFG_StrokeVertex StrokeRoman_ch43st0[] = +{ + {48.8371f,85.7143f}, + {48.8371f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch43st1[] = +{ + {5.98f,42.8571f}, + {91.6943f,42.8571f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch43st[] = +{ + {2,StrokeRoman_ch43st0}, + {2,StrokeRoman_ch43st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch43 = {97.2543f,2,StrokeRoman_ch43st}; + +/* char: 0x2c */ + +static const SFG_StrokeVertex StrokeRoman_ch44st0[] = +{ + {18.2838f,4.7619f}, + {13.5219f,0.0f}, + {8.76f,4.7619f}, + {13.5219f,9.5238f}, + {18.2838f,4.7619f}, + {18.2838f,-4.7619f}, + {13.5219f,-14.2857f}, + {8.76f,-19.0476f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch44st[] = +{ + {8,StrokeRoman_ch44st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch44 = {26.0638f,1,StrokeRoman_ch44st}; + +/* char: 0x2d */ + +static const SFG_StrokeVertex StrokeRoman_ch45st0[] = +{ + {7.38f,42.8571f}, + {93.0943f,42.8571f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch45st[] = +{ + {2,StrokeRoman_ch45st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch45 = {100.754f,1,StrokeRoman_ch45st}; + +/* char: 0x2e */ + +static const SFG_StrokeVertex StrokeRoman_ch46st0[] = +{ + {13.1019f,9.5238f}, + {8.34f,4.7619f}, + {13.1019f,0.0f}, + {17.8638f,4.7619f}, + {13.1019f,9.5238f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch46st[] = +{ + {5,StrokeRoman_ch46st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch46 = {26.4838f,1,StrokeRoman_ch46st}; + +/* char: 0x2f */ + +static const SFG_StrokeVertex StrokeRoman_ch47st0[] = +{ + {7.24f,-14.2857f}, + {73.9067f,100.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch47st[] = +{ + {2,StrokeRoman_ch47st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch47 = {82.1067f,1,StrokeRoman_ch47st}; + +/* char: 0x30 */ + +static const SFG_StrokeVertex StrokeRoman_ch48st0[] = +{ + {33.5514f,100.0f}, + {19.2657f,95.2381f}, + {9.7419f,80.9524f}, + {4.98f,57.1429f}, + {4.98f,42.8571f}, + {9.7419f,19.0476f}, + {19.2657f,4.7619f}, + {33.5514f,0.0f}, + {43.0752f,0.0f}, + {57.361f,4.7619f}, + {66.8848f,19.0476f}, + {71.6467f,42.8571f}, + {71.6467f,57.1429f}, + {66.8848f,80.9524f}, + {57.361f,95.2381f}, + {43.0752f,100.0f}, + {33.5514f,100.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch48st[] = +{ + {17,StrokeRoman_ch48st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch48 = {77.0667f,1,StrokeRoman_ch48st}; + +/* char: 0x31 */ + +static const SFG_StrokeVertex StrokeRoman_ch49st0[] = +{ + {11.82f,80.9524f}, + {21.3438f,85.7143f}, + {35.6295f,100.0f}, + {35.6295f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch49st[] = +{ + {4,StrokeRoman_ch49st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch49 = {66.5295f,1,StrokeRoman_ch49st}; + +/* char: 0x32 */ + +static const SFG_StrokeVertex StrokeRoman_ch50st0[] = +{ + {10.1819f,76.1905f}, + {10.1819f,80.9524f}, + {14.9438f,90.4762f}, + {19.7057f,95.2381f}, + {29.2295f,100.0f}, + {48.2771f,100.0f}, + {57.801f,95.2381f}, + {62.5629f,90.4762f}, + {67.3248f,80.9524f}, + {67.3248f,71.4286f}, + {62.5629f,61.9048f}, + {53.039f,47.619f}, + {5.42f,0.0f}, + {72.0867f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch50st[] = +{ + {14,StrokeRoman_ch50st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch50 = {77.6467f,1,StrokeRoman_ch50st}; + +/* char: 0x33 */ + +static const SFG_StrokeVertex StrokeRoman_ch51st0[] = +{ + {14.5238f,100.0f}, + {66.9048f,100.0f}, + {38.3333f,61.9048f}, + {52.619f,61.9048f}, + {62.1429f,57.1429f}, + {66.9048f,52.381f}, + {71.6667f,38.0952f}, + {71.6667f,28.5714f}, + {66.9048f,14.2857f}, + {57.381f,4.7619f}, + {43.0952f,0.0f}, + {28.8095f,0.0f}, + {14.5238f,4.7619f}, + {9.7619f,9.5238f}, + {5.0f,19.0476f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch51st[] = +{ + {15,StrokeRoman_ch51st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch51 = {77.0467f,1,StrokeRoman_ch51st}; + +/* char: 0x34 */ + +static const SFG_StrokeVertex StrokeRoman_ch52st0[] = +{ + {51.499f,100.0f}, + {3.88f,33.3333f}, + {75.3086f,33.3333f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch52st1[] = +{ + {51.499f,100.0f}, + {51.499f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch52st[] = +{ + {3,StrokeRoman_ch52st0}, + {2,StrokeRoman_ch52st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch52 = {80.1686f,2,StrokeRoman_ch52st}; + +/* char: 0x35 */ + +static const SFG_StrokeVertex StrokeRoman_ch53st0[] = +{ + {62.0029f,100.0f}, + {14.3838f,100.0f}, + {9.6219f,57.1429f}, + {14.3838f,61.9048f}, + {28.6695f,66.6667f}, + {42.9552f,66.6667f}, + {57.241f,61.9048f}, + {66.7648f,52.381f}, + {71.5267f,38.0952f}, + {71.5267f,28.5714f}, + {66.7648f,14.2857f}, + {57.241f,4.7619f}, + {42.9552f,0.0f}, + {28.6695f,0.0f}, + {14.3838f,4.7619f}, + {9.6219f,9.5238f}, + {4.86f,19.0476f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch53st[] = +{ + {17,StrokeRoman_ch53st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch53 = {77.6867f,1,StrokeRoman_ch53st}; + +/* char: 0x36 */ + +static const SFG_StrokeVertex StrokeRoman_ch54st0[] = +{ + {62.7229f,85.7143f}, + {57.961f,95.2381f}, + {43.6752f,100.0f}, + {34.1514f,100.0f}, + {19.8657f,95.2381f}, + {10.3419f,80.9524f}, + {5.58f,57.1429f}, + {5.58f,33.3333f}, + {10.3419f,14.2857f}, + {19.8657f,4.7619f}, + {34.1514f,0.0f}, + {38.9133f,0.0f}, + {53.199f,4.7619f}, + {62.7229f,14.2857f}, + {67.4848f,28.5714f}, + {67.4848f,33.3333f}, + {62.7229f,47.619f}, + {53.199f,57.1429f}, + {38.9133f,61.9048f}, + {34.1514f,61.9048f}, + {19.8657f,57.1429f}, + {10.3419f,47.619f}, + {5.58f,33.3333f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch54st[] = +{ + {23,StrokeRoman_ch54st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch54 = {73.8048f,1,StrokeRoman_ch54st}; + +/* char: 0x37 */ + +static const SFG_StrokeVertex StrokeRoman_ch55st0[] = +{ + {72.2267f,100.0f}, + {24.6076f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch55st1[] = +{ + {5.56f,100.0f}, + {72.2267f,100.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch55st[] = +{ + {2,StrokeRoman_ch55st0}, + {2,StrokeRoman_ch55st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch55 = {77.2267f,2,StrokeRoman_ch55st}; + +/* char: 0x38 */ + +static const SFG_StrokeVertex StrokeRoman_ch56st0[] = +{ + {29.4095f,100.0f}, + {15.1238f,95.2381f}, + {10.3619f,85.7143f}, + {10.3619f,76.1905f}, + {15.1238f,66.6667f}, + {24.6476f,61.9048f}, + {43.6952f,57.1429f}, + {57.981f,52.381f}, + {67.5048f,42.8571f}, + {72.2667f,33.3333f}, + {72.2667f,19.0476f}, + {67.5048f,9.5238f}, + {62.7429f,4.7619f}, + {48.4571f,0.0f}, + {29.4095f,0.0f}, + {15.1238f,4.7619f}, + {10.3619f,9.5238f}, + {5.6f,19.0476f}, + {5.6f,33.3333f}, + {10.3619f,42.8571f}, + {19.8857f,52.381f}, + {34.1714f,57.1429f}, + {53.219f,61.9048f}, + {62.7429f,66.6667f}, + {67.5048f,76.1905f}, + {67.5048f,85.7143f}, + {62.7429f,95.2381f}, + {48.4571f,100.0f}, + {29.4095f,100.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch56st[] = +{ + {29,StrokeRoman_ch56st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch56 = {77.6667f,1,StrokeRoman_ch56st}; + +/* char: 0x39 */ + +static const SFG_StrokeVertex StrokeRoman_ch57st0[] = +{ + {68.5048f,66.6667f}, + {63.7429f,52.381f}, + {54.219f,42.8571f}, + {39.9333f,38.0952f}, + {35.1714f,38.0952f}, + {20.8857f,42.8571f}, + {11.3619f,52.381f}, + {6.6f,66.6667f}, + {6.6f,71.4286f}, + {11.3619f,85.7143f}, + {20.8857f,95.2381f}, + {35.1714f,100.0f}, + {39.9333f,100.0f}, + {54.219f,95.2381f}, + {63.7429f,85.7143f}, + {68.5048f,66.6667f}, + {68.5048f,42.8571f}, + {63.7429f,19.0476f}, + {54.219f,4.7619f}, + {39.9333f,0.0f}, + {30.4095f,0.0f}, + {16.1238f,4.7619f}, + {11.3619f,14.2857f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch57st[] = +{ + {23,StrokeRoman_ch57st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch57 = {74.0648f,1,StrokeRoman_ch57st}; + +/* char: 0x3a */ + +static const SFG_StrokeVertex StrokeRoman_ch58st0[] = +{ + {14.0819f,66.6667f}, + {9.32f,61.9048f}, + {14.0819f,57.1429f}, + {18.8438f,61.9048f}, + {14.0819f,66.6667f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch58st1[] = +{ + {14.0819f,9.5238f}, + {9.32f,4.7619f}, + {14.0819f,0.0f}, + {18.8438f,4.7619f}, + {14.0819f,9.5238f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch58st[] = +{ + {5,StrokeRoman_ch58st0}, + {5,StrokeRoman_ch58st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch58 = {26.2238f,2,StrokeRoman_ch58st}; + +/* char: 0x3b */ + +static const SFG_StrokeVertex StrokeRoman_ch59st0[] = +{ + {12.9619f,66.6667f}, + {8.2f,61.9048f}, + {12.9619f,57.1429f}, + {17.7238f,61.9048f}, + {12.9619f,66.6667f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch59st1[] = +{ + {17.7238f,4.7619f}, + {12.9619f,0.0f}, + {8.2f,4.7619f}, + {12.9619f,9.5238f}, + {17.7238f,4.7619f}, + {17.7238f,-4.7619f}, + {12.9619f,-14.2857f}, + {8.2f,-19.0476f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch59st[] = +{ + {5,StrokeRoman_ch59st0}, + {8,StrokeRoman_ch59st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch59 = {26.3038f,2,StrokeRoman_ch59st}; + +/* char: 0x3c */ + +static const SFG_StrokeVertex StrokeRoman_ch60st0[] = +{ + {79.2505f,85.7143f}, + {3.06f,42.8571f}, + {79.2505f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch60st[] = +{ + {3,StrokeRoman_ch60st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch60 = {81.6105f,1,StrokeRoman_ch60st}; + +/* char: 0x3d */ + +static const SFG_StrokeVertex StrokeRoman_ch61st0[] = +{ + {5.7f,57.1429f}, + {91.4143f,57.1429f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch61st1[] = +{ + {5.7f,28.5714f}, + {91.4143f,28.5714f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch61st[] = +{ + {2,StrokeRoman_ch61st0}, + {2,StrokeRoman_ch61st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch61 = {97.2543f,2,StrokeRoman_ch61st}; + +/* char: 0x3e */ + +static const SFG_StrokeVertex StrokeRoman_ch62st0[] = +{ + {2.78f,85.7143f}, + {78.9705f,42.8571f}, + {2.78f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch62st[] = +{ + {3,StrokeRoman_ch62st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch62 = {81.6105f,1,StrokeRoman_ch62st}; + +/* char: 0x3f */ + +static const SFG_StrokeVertex StrokeRoman_ch63st0[] = +{ + {8.42f,76.1905f}, + {8.42f,80.9524f}, + {13.1819f,90.4762f}, + {17.9438f,95.2381f}, + {27.4676f,100.0f}, + {46.5152f,100.0f}, + {56.039f,95.2381f}, + {60.801f,90.4762f}, + {65.5629f,80.9524f}, + {65.5629f,71.4286f}, + {60.801f,61.9048f}, + {56.039f,57.1429f}, + {36.9914f,47.619f}, + {36.9914f,33.3333f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch63st1[] = +{ + {36.9914f,9.5238f}, + {32.2295f,4.7619f}, + {36.9914f,0.0f}, + {41.7533f,4.7619f}, + {36.9914f,9.5238f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch63st[] = +{ + {14,StrokeRoman_ch63st0}, + {5,StrokeRoman_ch63st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch63 = {73.9029f,2,StrokeRoman_ch63st}; + +/* char: 0x40 */ + +static const SFG_StrokeVertex StrokeRoman_ch64st0[] = +{ + {49.2171f,52.381f}, + {39.6933f,57.1429f}, + {30.1695f,57.1429f}, + {25.4076f,47.619f}, + {25.4076f,42.8571f}, + {30.1695f,33.3333f}, + {39.6933f,33.3333f}, + {49.2171f,38.0952f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch64st1[] = +{ + {49.2171f,57.1429f}, + {49.2171f,38.0952f}, + {53.979f,33.3333f}, + {63.5029f,33.3333f}, + {68.2648f,42.8571f}, + {68.2648f,47.619f}, + {63.5029f,61.9048f}, + {53.979f,71.4286f}, + {39.6933f,76.1905f}, + {34.9314f,76.1905f}, + {20.6457f,71.4286f}, + {11.1219f,61.9048f}, + {6.36f,47.619f}, + {6.36f,42.8571f}, + {11.1219f,28.5714f}, + {20.6457f,19.0476f}, + {34.9314f,14.2857f}, + {39.6933f,14.2857f}, + {53.979f,19.0476f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch64st[] = +{ + {8,StrokeRoman_ch64st0}, + {19,StrokeRoman_ch64st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch64 = {74.3648f,2,StrokeRoman_ch64st}; + +/* char: 0x41 */ + +static const SFG_StrokeVertex StrokeRoman_ch65st0[] = +{ + {40.5952f,100.0f}, + {2.5f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch65st1[] = +{ + {40.5952f,100.0f}, + {78.6905f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch65st2[] = +{ + {16.7857f,33.3333f}, + {64.4048f,33.3333f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch65st[] = +{ + {2,StrokeRoman_ch65st0}, + {2,StrokeRoman_ch65st1}, + {2,StrokeRoman_ch65st2} +}; + +static const SFG_StrokeChar StrokeRoman_ch65 = {80.4905f,3,StrokeRoman_ch65st}; + +/* char: 0x42 */ + +static const SFG_StrokeVertex StrokeRoman_ch66st0[] = +{ + {11.42f,100.0f}, + {11.42f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch66st1[] = +{ + {11.42f,100.0f}, + {54.2771f,100.0f}, + {68.5629f,95.2381f}, + {73.3248f,90.4762f}, + {78.0867f,80.9524f}, + {78.0867f,71.4286f}, + {73.3248f,61.9048f}, + {68.5629f,57.1429f}, + {54.2771f,52.381f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch66st2[] = +{ + {11.42f,52.381f}, + {54.2771f,52.381f}, + {68.5629f,47.619f}, + {73.3248f,42.8571f}, + {78.0867f,33.3333f}, + {78.0867f,19.0476f}, + {73.3248f,9.5238f}, + {68.5629f,4.7619f}, + {54.2771f,0.0f}, + {11.42f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch66st[] = +{ + {2,StrokeRoman_ch66st0}, + {9,StrokeRoman_ch66st1}, + {10,StrokeRoman_ch66st2} +}; + +static const SFG_StrokeChar StrokeRoman_ch66 = {83.6267f,3,StrokeRoman_ch66st}; + +/* char: 0x43 */ + +static const SFG_StrokeVertex StrokeRoman_ch67st0[] = +{ + {78.0886f,76.1905f}, + {73.3267f,85.7143f}, + {63.8029f,95.2381f}, + {54.279f,100.0f}, + {35.2314f,100.0f}, + {25.7076f,95.2381f}, + {16.1838f,85.7143f}, + {11.4219f,76.1905f}, + {6.66f,61.9048f}, + {6.66f,38.0952f}, + {11.4219f,23.8095f}, + {16.1838f,14.2857f}, + {25.7076f,4.7619f}, + {35.2314f,0.0f}, + {54.279f,0.0f}, + {63.8029f,4.7619f}, + {73.3267f,14.2857f}, + {78.0886f,23.8095f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch67st[] = +{ + {18,StrokeRoman_ch67st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch67 = {84.4886f,1,StrokeRoman_ch67st}; + +/* char: 0x44 */ + +static const SFG_StrokeVertex StrokeRoman_ch68st0[] = +{ + {11.96f,100.0f}, + {11.96f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch68st1[] = +{ + {11.96f,100.0f}, + {45.2933f,100.0f}, + {59.579f,95.2381f}, + {69.1029f,85.7143f}, + {73.8648f,76.1905f}, + {78.6267f,61.9048f}, + {78.6267f,38.0952f}, + {73.8648f,23.8095f}, + {69.1029f,14.2857f}, + {59.579f,4.7619f}, + {45.2933f,0.0f}, + {11.96f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch68st[] = +{ + {2,StrokeRoman_ch68st0}, + {12,StrokeRoman_ch68st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch68 = {85.2867f,2,StrokeRoman_ch68st}; + +/* char: 0x45 */ + +static const SFG_StrokeVertex StrokeRoman_ch69st0[] = +{ + {11.42f,100.0f}, + {11.42f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch69st1[] = +{ + {11.42f,100.0f}, + {73.3248f,100.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch69st2[] = +{ + {11.42f,52.381f}, + {49.5152f,52.381f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch69st3[] = +{ + {11.42f,0.0f}, + {73.3248f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch69st[] = +{ + {2,StrokeRoman_ch69st0}, + {2,StrokeRoman_ch69st1}, + {2,StrokeRoman_ch69st2}, + {2,StrokeRoman_ch69st3} +}; + +static const SFG_StrokeChar StrokeRoman_ch69 = {78.1848f,4,StrokeRoman_ch69st}; + +/* char: 0x46 */ + +static const SFG_StrokeVertex StrokeRoman_ch70st0[] = +{ + {11.42f,100.0f}, + {11.42f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch70st1[] = +{ + {11.42f,100.0f}, + {73.3248f,100.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch70st2[] = +{ + {11.42f,52.381f}, + {49.5152f,52.381f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch70st[] = +{ + {2,StrokeRoman_ch70st0}, + {2,StrokeRoman_ch70st1}, + {2,StrokeRoman_ch70st2} +}; + +static const SFG_StrokeChar StrokeRoman_ch70 = {78.7448f,3,StrokeRoman_ch70st}; + +/* char: 0x47 */ + +static const SFG_StrokeVertex StrokeRoman_ch71st0[] = +{ + {78.4886f,76.1905f}, + {73.7267f,85.7143f}, + {64.2029f,95.2381f}, + {54.679f,100.0f}, + {35.6314f,100.0f}, + {26.1076f,95.2381f}, + {16.5838f,85.7143f}, + {11.8219f,76.1905f}, + {7.06f,61.9048f}, + {7.06f,38.0952f}, + {11.8219f,23.8095f}, + {16.5838f,14.2857f}, + {26.1076f,4.7619f}, + {35.6314f,0.0f}, + {54.679f,0.0f}, + {64.2029f,4.7619f}, + {73.7267f,14.2857f}, + {78.4886f,23.8095f}, + {78.4886f,38.0952f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch71st1[] = +{ + {54.679f,38.0952f}, + {78.4886f,38.0952f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch71st[] = +{ + {19,StrokeRoman_ch71st0}, + {2,StrokeRoman_ch71st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch71 = {89.7686f,2,StrokeRoman_ch71st}; + +/* char: 0x48 */ + +static const SFG_StrokeVertex StrokeRoman_ch72st0[] = +{ + {11.42f,100.0f}, + {11.42f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch72st1[] = +{ + {78.0867f,100.0f}, + {78.0867f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch72st2[] = +{ + {11.42f,52.381f}, + {78.0867f,52.381f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch72st[] = +{ + {2,StrokeRoman_ch72st0}, + {2,StrokeRoman_ch72st1}, + {2,StrokeRoman_ch72st2} +}; + +static const SFG_StrokeChar StrokeRoman_ch72 = {89.0867f,3,StrokeRoman_ch72st}; + +/* char: 0x49 */ + +static const SFG_StrokeVertex StrokeRoman_ch73st0[] = +{ + {10.86f,100.0f}, + {10.86f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch73st[] = +{ + {2,StrokeRoman_ch73st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch73 = {21.3f,1,StrokeRoman_ch73st}; + +/* char: 0x4a */ + +static const SFG_StrokeVertex StrokeRoman_ch74st0[] = +{ + {50.119f,100.0f}, + {50.119f,23.8095f}, + {45.3571f,9.5238f}, + {40.5952f,4.7619f}, + {31.0714f,0.0f}, + {21.5476f,0.0f}, + {12.0238f,4.7619f}, + {7.2619f,9.5238f}, + {2.5f,23.8095f}, + {2.5f,33.3333f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch74st[] = +{ + {10,StrokeRoman_ch74st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch74 = {59.999f,1,StrokeRoman_ch74st}; + +/* char: 0x4b */ + +static const SFG_StrokeVertex StrokeRoman_ch75st0[] = +{ + {11.28f,100.0f}, + {11.28f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch75st1[] = +{ + {77.9467f,100.0f}, + {11.28f,33.3333f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch75st2[] = +{ + {35.0895f,57.1429f}, + {77.9467f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch75st[] = +{ + {2,StrokeRoman_ch75st0}, + {2,StrokeRoman_ch75st1}, + {2,StrokeRoman_ch75st2} +}; + +static const SFG_StrokeChar StrokeRoman_ch75 = {79.3267f,3,StrokeRoman_ch75st}; + +/* char: 0x4c */ + +static const SFG_StrokeVertex StrokeRoman_ch76st0[] = +{ + {11.68f,100.0f}, + {11.68f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch76st1[] = +{ + {11.68f,0.0f}, + {68.8229f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch76st[] = +{ + {2,StrokeRoman_ch76st0}, + {2,StrokeRoman_ch76st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch76 = {71.3229f,2,StrokeRoman_ch76st}; + +/* char: 0x4d */ + +static const SFG_StrokeVertex StrokeRoman_ch77st0[] = +{ + {10.86f,100.0f}, + {10.86f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch77st1[] = +{ + {10.86f,100.0f}, + {48.9552f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch77st2[] = +{ + {87.0505f,100.0f}, + {48.9552f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch77st3[] = +{ + {87.0505f,100.0f}, + {87.0505f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch77st[] = +{ + {2,StrokeRoman_ch77st0}, + {2,StrokeRoman_ch77st1}, + {2,StrokeRoman_ch77st2}, + {2,StrokeRoman_ch77st3} +}; + +static const SFG_StrokeChar StrokeRoman_ch77 = {97.2105f,4,StrokeRoman_ch77st}; + +/* char: 0x4e */ + +static const SFG_StrokeVertex StrokeRoman_ch78st0[] = +{ + {11.14f,100.0f}, + {11.14f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch78st1[] = +{ + {11.14f,100.0f}, + {77.8067f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch78st2[] = +{ + {77.8067f,100.0f}, + {77.8067f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch78st[] = +{ + {2,StrokeRoman_ch78st0}, + {2,StrokeRoman_ch78st1}, + {2,StrokeRoman_ch78st2} +}; + +static const SFG_StrokeChar StrokeRoman_ch78 = {88.8067f,3,StrokeRoman_ch78st}; + +/* char: 0x4f */ + +static const SFG_StrokeVertex StrokeRoman_ch79st0[] = +{ + {34.8114f,100.0f}, + {25.2876f,95.2381f}, + {15.7638f,85.7143f}, + {11.0019f,76.1905f}, + {6.24f,61.9048f}, + {6.24f,38.0952f}, + {11.0019f,23.8095f}, + {15.7638f,14.2857f}, + {25.2876f,4.7619f}, + {34.8114f,0.0f}, + {53.859f,0.0f}, + {63.3829f,4.7619f}, + {72.9067f,14.2857f}, + {77.6686f,23.8095f}, + {82.4305f,38.0952f}, + {82.4305f,61.9048f}, + {77.6686f,76.1905f}, + {72.9067f,85.7143f}, + {63.3829f,95.2381f}, + {53.859f,100.0f}, + {34.8114f,100.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch79st[] = +{ + {21,StrokeRoman_ch79st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch79 = {88.8305f,1,StrokeRoman_ch79st}; + +/* char: 0x50 */ + +static const SFG_StrokeVertex StrokeRoman_ch80st0[] = +{ + {12.1f,100.0f}, + {12.1f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch80st1[] = +{ + {12.1f,100.0f}, + {54.9571f,100.0f}, + {69.2429f,95.2381f}, + {74.0048f,90.4762f}, + {78.7667f,80.9524f}, + {78.7667f,66.6667f}, + {74.0048f,57.1429f}, + {69.2429f,52.381f}, + {54.9571f,47.619f}, + {12.1f,47.619f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch80st[] = +{ + {2,StrokeRoman_ch80st0}, + {10,StrokeRoman_ch80st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch80 = {85.6667f,2,StrokeRoman_ch80st}; + +/* char: 0x51 */ + +static const SFG_StrokeVertex StrokeRoman_ch81st0[] = +{ + {33.8714f,100.0f}, + {24.3476f,95.2381f}, + {14.8238f,85.7143f}, + {10.0619f,76.1905f}, + {5.3f,61.9048f}, + {5.3f,38.0952f}, + {10.0619f,23.8095f}, + {14.8238f,14.2857f}, + {24.3476f,4.7619f}, + {33.8714f,0.0f}, + {52.919f,0.0f}, + {62.4429f,4.7619f}, + {71.9667f,14.2857f}, + {76.7286f,23.8095f}, + {81.4905f,38.0952f}, + {81.4905f,61.9048f}, + {76.7286f,76.1905f}, + {71.9667f,85.7143f}, + {62.4429f,95.2381f}, + {52.919f,100.0f}, + {33.8714f,100.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch81st1[] = +{ + {48.1571f,19.0476f}, + {76.7286f,-9.5238f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch81st[] = +{ + {21,StrokeRoman_ch81st0}, + {2,StrokeRoman_ch81st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch81 = {88.0905f,2,StrokeRoman_ch81st}; + +/* char: 0x52 */ + +static const SFG_StrokeVertex StrokeRoman_ch82st0[] = +{ + {11.68f,100.0f}, + {11.68f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch82st1[] = +{ + {11.68f,100.0f}, + {54.5371f,100.0f}, + {68.8229f,95.2381f}, + {73.5848f,90.4762f}, + {78.3467f,80.9524f}, + {78.3467f,71.4286f}, + {73.5848f,61.9048f}, + {68.8229f,57.1429f}, + {54.5371f,52.381f}, + {11.68f,52.381f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch82st2[] = +{ + {45.0133f,52.381f}, + {78.3467f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch82st[] = +{ + {2,StrokeRoman_ch82st0}, + {10,StrokeRoman_ch82st1}, + {2,StrokeRoman_ch82st2} +}; + +static const SFG_StrokeChar StrokeRoman_ch82 = {82.3667f,3,StrokeRoman_ch82st}; + +/* char: 0x53 */ + +static const SFG_StrokeVertex StrokeRoman_ch83st0[] = +{ + {74.6667f,85.7143f}, + {65.1429f,95.2381f}, + {50.8571f,100.0f}, + {31.8095f,100.0f}, + {17.5238f,95.2381f}, + {8.0f,85.7143f}, + {8.0f,76.1905f}, + {12.7619f,66.6667f}, + {17.5238f,61.9048f}, + {27.0476f,57.1429f}, + {55.619f,47.619f}, + {65.1429f,42.8571f}, + {69.9048f,38.0952f}, + {74.6667f,28.5714f}, + {74.6667f,14.2857f}, + {65.1429f,4.7619f}, + {50.8571f,0.0f}, + {31.8095f,0.0f}, + {17.5238f,4.7619f}, + {8.0f,14.2857f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch83st[] = +{ + {20,StrokeRoman_ch83st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch83 = {80.8267f,1,StrokeRoman_ch83st}; + +/* char: 0x54 */ + +static const SFG_StrokeVertex StrokeRoman_ch84st0[] = +{ + {35.6933f,100.0f}, + {35.6933f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch84st1[] = +{ + {2.36f,100.0f}, + {69.0267f,100.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch84st[] = +{ + {2,StrokeRoman_ch84st0}, + {2,StrokeRoman_ch84st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch84 = {71.9467f,2,StrokeRoman_ch84st}; + +/* char: 0x55 */ + +static const SFG_StrokeVertex StrokeRoman_ch85st0[] = +{ + {11.54f,100.0f}, + {11.54f,28.5714f}, + {16.3019f,14.2857f}, + {25.8257f,4.7619f}, + {40.1114f,0.0f}, + {49.6352f,0.0f}, + {63.921f,4.7619f}, + {73.4448f,14.2857f}, + {78.2067f,28.5714f}, + {78.2067f,100.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch85st[] = +{ + {10,StrokeRoman_ch85st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch85 = {89.4867f,1,StrokeRoman_ch85st}; + +/* char: 0x56 */ + +static const SFG_StrokeVertex StrokeRoman_ch86st0[] = +{ + {2.36f,100.0f}, + {40.4552f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch86st1[] = +{ + {78.5505f,100.0f}, + {40.4552f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch86st[] = +{ + {2,StrokeRoman_ch86st0}, + {2,StrokeRoman_ch86st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch86 = {81.6105f,2,StrokeRoman_ch86st}; + +/* char: 0x57 */ + +static const SFG_StrokeVertex StrokeRoman_ch87st0[] = +{ + {2.22f,100.0f}, + {26.0295f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch87st1[] = +{ + {49.839f,100.0f}, + {26.0295f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch87st2[] = +{ + {49.839f,100.0f}, + {73.6486f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch87st3[] = +{ + {97.4581f,100.0f}, + {73.6486f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch87st[] = +{ + {2,StrokeRoman_ch87st0}, + {2,StrokeRoman_ch87st1}, + {2,StrokeRoman_ch87st2}, + {2,StrokeRoman_ch87st3} +}; + +static const SFG_StrokeChar StrokeRoman_ch87 = {100.518f,4,StrokeRoman_ch87st}; + +/* char: 0x58 */ + +static const SFG_StrokeVertex StrokeRoman_ch88st0[] = +{ + {2.5f,100.0f}, + {69.1667f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch88st1[] = +{ + {69.1667f,100.0f}, + {2.5f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch88st[] = +{ + {2,StrokeRoman_ch88st0}, + {2,StrokeRoman_ch88st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch88 = {72.3667f,2,StrokeRoman_ch88st}; + +/* char: 0x59 */ + +static const SFG_StrokeVertex StrokeRoman_ch89st0[] = +{ + {1.52f,100.0f}, + {39.6152f,52.381f}, + {39.6152f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch89st1[] = +{ + {77.7105f,100.0f}, + {39.6152f,52.381f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch89st[] = +{ + {3,StrokeRoman_ch89st0}, + {2,StrokeRoman_ch89st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch89 = {79.6505f,2,StrokeRoman_ch89st}; + +/* char: 0x5a */ + +static const SFG_StrokeVertex StrokeRoman_ch90st0[] = +{ + {69.1667f,100.0f}, + {2.5f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch90st1[] = +{ + {2.5f,100.0f}, + {69.1667f,100.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch90st2[] = +{ + {2.5f,0.0f}, + {69.1667f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch90st[] = +{ + {2,StrokeRoman_ch90st0}, + {2,StrokeRoman_ch90st1}, + {2,StrokeRoman_ch90st2} +}; + +static const SFG_StrokeChar StrokeRoman_ch90 = {73.7467f,3,StrokeRoman_ch90st}; + +/* char: 0x5b */ + +static const SFG_StrokeVertex StrokeRoman_ch91st0[] = +{ + {7.78f,119.048f}, + {7.78f,-33.3333f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch91st1[] = +{ + {12.5419f,119.048f}, + {12.5419f,-33.3333f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch91st2[] = +{ + {7.78f,119.048f}, + {41.1133f,119.048f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch91st3[] = +{ + {7.78f,-33.3333f}, + {41.1133f,-33.3333f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch91st[] = +{ + {2,StrokeRoman_ch91st0}, + {2,StrokeRoman_ch91st1}, + {2,StrokeRoman_ch91st2}, + {2,StrokeRoman_ch91st3} +}; + +static const SFG_StrokeChar StrokeRoman_ch91 = {46.1133f,4,StrokeRoman_ch91st}; + +/* char: 0x5c */ + +static const SFG_StrokeVertex StrokeRoman_ch92st0[] = +{ + {5.84f,100.0f}, + {72.5067f,-14.2857f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch92st[] = +{ + {2,StrokeRoman_ch92st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch92 = {78.2067f,1,StrokeRoman_ch92st}; + +/* char: 0x5d */ + +static const SFG_StrokeVertex StrokeRoman_ch93st0[] = +{ + {33.0114f,119.048f}, + {33.0114f,-33.3333f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch93st1[] = +{ + {37.7733f,119.048f}, + {37.7733f,-33.3333f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch93st2[] = +{ + {4.44f,119.048f}, + {37.7733f,119.048f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch93st3[] = +{ + {4.44f,-33.3333f}, + {37.7733f,-33.3333f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch93st[] = +{ + {2,StrokeRoman_ch93st0}, + {2,StrokeRoman_ch93st1}, + {2,StrokeRoman_ch93st2}, + {2,StrokeRoman_ch93st3} +}; + +static const SFG_StrokeChar StrokeRoman_ch93 = {46.3933f,4,StrokeRoman_ch93st}; + +/* char: 0x5e */ + +static const SFG_StrokeVertex StrokeRoman_ch94st0[] = +{ + {44.0752f,109.524f}, + {5.98f,42.8571f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch94st1[] = +{ + {44.0752f,109.524f}, + {82.1705f,42.8571f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch94st[] = +{ + {2,StrokeRoman_ch94st0}, + {2,StrokeRoman_ch94st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch94 = {90.2305f,2,StrokeRoman_ch94st}; + +/* char: 0x5f */ + +static const SFG_StrokeVertex StrokeRoman_ch95st0[] = +{ + {-1.1f,-33.3333f}, + {103.662f,-33.3333f}, + {103.662f,-28.5714f}, + {-1.1f,-28.5714f}, + {-1.1f,-33.3333f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch95st[] = +{ + {5,StrokeRoman_ch95st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch95 = {104.062f,1,StrokeRoman_ch95st}; + +/* char: 0x60 */ + +static const SFG_StrokeVertex StrokeRoman_ch96st0[] = +{ + {33.0219f,100.0f}, + {56.8314f,71.4286f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch96st1[] = +{ + {33.0219f,100.0f}, + {28.26f,95.2381f}, + {56.8314f,71.4286f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch96st[] = +{ + {2,StrokeRoman_ch96st0}, + {3,StrokeRoman_ch96st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch96 = {83.5714f,2,StrokeRoman_ch96st}; + +/* char: 0x61 */ + +static const SFG_StrokeVertex StrokeRoman_ch97st0[] = +{ + {63.8229f,66.6667f}, + {63.8229f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch97st1[] = +{ + {63.8229f,52.381f}, + {54.299f,61.9048f}, + {44.7752f,66.6667f}, + {30.4895f,66.6667f}, + {20.9657f,61.9048f}, + {11.4419f,52.381f}, + {6.68f,38.0952f}, + {6.68f,28.5714f}, + {11.4419f,14.2857f}, + {20.9657f,4.7619f}, + {30.4895f,0.0f}, + {44.7752f,0.0f}, + {54.299f,4.7619f}, + {63.8229f,14.2857f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch97st[] = +{ + {2,StrokeRoman_ch97st0}, + {14,StrokeRoman_ch97st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch97 = {66.6029f,2,StrokeRoman_ch97st}; + +/* char: 0x62 */ + +static const SFG_StrokeVertex StrokeRoman_ch98st0[] = +{ + {8.76f,100.0f}, + {8.76f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch98st1[] = +{ + {8.76f,52.381f}, + {18.2838f,61.9048f}, + {27.8076f,66.6667f}, + {42.0933f,66.6667f}, + {51.6171f,61.9048f}, + {61.141f,52.381f}, + {65.9029f,38.0952f}, + {65.9029f,28.5714f}, + {61.141f,14.2857f}, + {51.6171f,4.7619f}, + {42.0933f,0.0f}, + {27.8076f,0.0f}, + {18.2838f,4.7619f}, + {8.76f,14.2857f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch98st[] = +{ + {2,StrokeRoman_ch98st0}, + {14,StrokeRoman_ch98st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch98 = {70.4629f,2,StrokeRoman_ch98st}; + +/* char: 0x63 */ + +static const SFG_StrokeVertex StrokeRoman_ch99st0[] = +{ + {62.6629f,52.381f}, + {53.139f,61.9048f}, + {43.6152f,66.6667f}, + {29.3295f,66.6667f}, + {19.8057f,61.9048f}, + {10.2819f,52.381f}, + {5.52f,38.0952f}, + {5.52f,28.5714f}, + {10.2819f,14.2857f}, + {19.8057f,4.7619f}, + {29.3295f,0.0f}, + {43.6152f,0.0f}, + {53.139f,4.7619f}, + {62.6629f,14.2857f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch99st[] = +{ + {14,StrokeRoman_ch99st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch99 = {68.9229f,1,StrokeRoman_ch99st}; + +/* char: 0x64 */ + +static const SFG_StrokeVertex StrokeRoman_ch100st0[] = +{ + {61.7829f,100.0f}, + {61.7829f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch100st1[] = +{ + {61.7829f,52.381f}, + {52.259f,61.9048f}, + {42.7352f,66.6667f}, + {28.4495f,66.6667f}, + {18.9257f,61.9048f}, + {9.4019f,52.381f}, + {4.64f,38.0952f}, + {4.64f,28.5714f}, + {9.4019f,14.2857f}, + {18.9257f,4.7619f}, + {28.4495f,0.0f}, + {42.7352f,0.0f}, + {52.259f,4.7619f}, + {61.7829f,14.2857f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch100st[] = +{ + {2,StrokeRoman_ch100st0}, + {14,StrokeRoman_ch100st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch100 = {70.2629f,2,StrokeRoman_ch100st}; + +/* char: 0x65 */ + +static const SFG_StrokeVertex StrokeRoman_ch101st0[] = +{ + {5.72f,38.0952f}, + {62.8629f,38.0952f}, + {62.8629f,47.619f}, + {58.101f,57.1429f}, + {53.339f,61.9048f}, + {43.8152f,66.6667f}, + {29.5295f,66.6667f}, + {20.0057f,61.9048f}, + {10.4819f,52.381f}, + {5.72f,38.0952f}, + {5.72f,28.5714f}, + {10.4819f,14.2857f}, + {20.0057f,4.7619f}, + {29.5295f,0.0f}, + {43.8152f,0.0f}, + {53.339f,4.7619f}, + {62.8629f,14.2857f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch101st[] = +{ + {17,StrokeRoman_ch101st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch101 = {68.5229f,1,StrokeRoman_ch101st}; + +/* char: 0x66 */ + +static const SFG_StrokeVertex StrokeRoman_ch102st0[] = +{ + {38.7752f,100.0f}, + {29.2514f,100.0f}, + {19.7276f,95.2381f}, + {14.9657f,80.9524f}, + {14.9657f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch102st1[] = +{ + {0.68f,66.6667f}, + {34.0133f,66.6667f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch102st[] = +{ + {5,StrokeRoman_ch102st0}, + {2,StrokeRoman_ch102st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch102 = {38.6552f,2,StrokeRoman_ch102st}; + +/* char: 0x67 */ + +static const SFG_StrokeVertex StrokeRoman_ch103st0[] = +{ + {62.5029f,66.6667f}, + {62.5029f,-9.5238f}, + {57.741f,-23.8095f}, + {52.979f,-28.5714f}, + {43.4552f,-33.3333f}, + {29.1695f,-33.3333f}, + {19.6457f,-28.5714f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch103st1[] = +{ + {62.5029f,52.381f}, + {52.979f,61.9048f}, + {43.4552f,66.6667f}, + {29.1695f,66.6667f}, + {19.6457f,61.9048f}, + {10.1219f,52.381f}, + {5.36f,38.0952f}, + {5.36f,28.5714f}, + {10.1219f,14.2857f}, + {19.6457f,4.7619f}, + {29.1695f,0.0f}, + {43.4552f,0.0f}, + {52.979f,4.7619f}, + {62.5029f,14.2857f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch103st[] = +{ + {7,StrokeRoman_ch103st0}, + {14,StrokeRoman_ch103st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch103 = {70.9829f,2,StrokeRoman_ch103st}; + +/* char: 0x68 */ + +static const SFG_StrokeVertex StrokeRoman_ch104st0[] = +{ + {9.6f,100.0f}, + {9.6f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch104st1[] = +{ + {9.6f,47.619f}, + {23.8857f,61.9048f}, + {33.4095f,66.6667f}, + {47.6952f,66.6667f}, + {57.219f,61.9048f}, + {61.981f,47.619f}, + {61.981f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch104st[] = +{ + {2,StrokeRoman_ch104st0}, + {7,StrokeRoman_ch104st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch104 = {71.021f,2,StrokeRoman_ch104st}; + +/* char: 0x69 */ + +static const SFG_StrokeVertex StrokeRoman_ch105st0[] = +{ + {10.02f,100.0f}, + {14.7819f,95.2381f}, + {19.5438f,100.0f}, + {14.7819f,104.762f}, + {10.02f,100.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch105st1[] = +{ + {14.7819f,66.6667f}, + {14.7819f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch105st[] = +{ + {5,StrokeRoman_ch105st0}, + {2,StrokeRoman_ch105st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch105 = {28.8638f,2,StrokeRoman_ch105st}; + +/* char: 0x6a */ + +static const SFG_StrokeVertex StrokeRoman_ch106st0[] = +{ + {17.3876f,100.0f}, + {22.1495f,95.2381f}, + {26.9114f,100.0f}, + {22.1495f,104.762f}, + {17.3876f,100.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch106st1[] = +{ + {22.1495f,66.6667f}, + {22.1495f,-14.2857f}, + {17.3876f,-28.5714f}, + {7.8638f,-33.3333f}, + {-1.66f,-33.3333f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch106st[] = +{ + {5,StrokeRoman_ch106st0}, + {5,StrokeRoman_ch106st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch106 = {36.2314f,2,StrokeRoman_ch106st}; + +/* char: 0x6b */ + +static const SFG_StrokeVertex StrokeRoman_ch107st0[] = +{ + {9.6f,100.0f}, + {9.6f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch107st1[] = +{ + {57.219f,66.6667f}, + {9.6f,19.0476f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch107st2[] = +{ + {28.6476f,38.0952f}, + {61.981f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch107st[] = +{ + {2,StrokeRoman_ch107st0}, + {2,StrokeRoman_ch107st1}, + {2,StrokeRoman_ch107st2} +}; + +static const SFG_StrokeChar StrokeRoman_ch107 = {62.521f,3,StrokeRoman_ch107st}; + +/* char: 0x6c */ + +static const SFG_StrokeVertex StrokeRoman_ch108st0[] = +{ + {10.02f,100.0f}, + {10.02f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch108st[] = +{ + {2,StrokeRoman_ch108st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch108 = {19.34f,1,StrokeRoman_ch108st}; + +/* char: 0x6d */ + +static const SFG_StrokeVertex StrokeRoman_ch109st0[] = +{ + {9.6f,66.6667f}, + {9.6f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch109st1[] = +{ + {9.6f,47.619f}, + {23.8857f,61.9048f}, + {33.4095f,66.6667f}, + {47.6952f,66.6667f}, + {57.219f,61.9048f}, + {61.981f,47.619f}, + {61.981f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch109st2[] = +{ + {61.981f,47.619f}, + {76.2667f,61.9048f}, + {85.7905f,66.6667f}, + {100.076f,66.6667f}, + {109.6f,61.9048f}, + {114.362f,47.619f}, + {114.362f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch109st[] = +{ + {2,StrokeRoman_ch109st0}, + {7,StrokeRoman_ch109st1}, + {7,StrokeRoman_ch109st2} +}; + +static const SFG_StrokeChar StrokeRoman_ch109 = {123.962f,3,StrokeRoman_ch109st}; + +/* char: 0x6e */ + +static const SFG_StrokeVertex StrokeRoman_ch110st0[] = +{ + {9.18f,66.6667f}, + {9.18f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch110st1[] = +{ + {9.18f,47.619f}, + {23.4657f,61.9048f}, + {32.9895f,66.6667f}, + {47.2752f,66.6667f}, + {56.799f,61.9048f}, + {61.561f,47.619f}, + {61.561f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch110st[] = +{ + {2,StrokeRoman_ch110st0}, + {7,StrokeRoman_ch110st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch110 = {70.881f,2,StrokeRoman_ch110st}; + +/* char: 0x6f */ + +static const SFG_StrokeVertex StrokeRoman_ch111st0[] = +{ + {28.7895f,66.6667f}, + {19.2657f,61.9048f}, + {9.7419f,52.381f}, + {4.98f,38.0952f}, + {4.98f,28.5714f}, + {9.7419f,14.2857f}, + {19.2657f,4.7619f}, + {28.7895f,0.0f}, + {43.0752f,0.0f}, + {52.599f,4.7619f}, + {62.1229f,14.2857f}, + {66.8848f,28.5714f}, + {66.8848f,38.0952f}, + {62.1229f,52.381f}, + {52.599f,61.9048f}, + {43.0752f,66.6667f}, + {28.7895f,66.6667f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch111st[] = +{ + {17,StrokeRoman_ch111st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch111 = {71.7448f,1,StrokeRoman_ch111st}; + +/* char: 0x70 */ + +static const SFG_StrokeVertex StrokeRoman_ch112st0[] = +{ + {9.46f,66.6667f}, + {9.46f,-33.3333f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch112st1[] = +{ + {9.46f,52.381f}, + {18.9838f,61.9048f}, + {28.5076f,66.6667f}, + {42.7933f,66.6667f}, + {52.3171f,61.9048f}, + {61.841f,52.381f}, + {66.6029f,38.0952f}, + {66.6029f,28.5714f}, + {61.841f,14.2857f}, + {52.3171f,4.7619f}, + {42.7933f,0.0f}, + {28.5076f,0.0f}, + {18.9838f,4.7619f}, + {9.46f,14.2857f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch112st[] = +{ + {2,StrokeRoman_ch112st0}, + {14,StrokeRoman_ch112st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch112 = {70.8029f,2,StrokeRoman_ch112st}; + +/* char: 0x71 */ + +static const SFG_StrokeVertex StrokeRoman_ch113st0[] = +{ + {61.9829f,66.6667f}, + {61.9829f,-33.3333f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch113st1[] = +{ + {61.9829f,52.381f}, + {52.459f,61.9048f}, + {42.9352f,66.6667f}, + {28.6495f,66.6667f}, + {19.1257f,61.9048f}, + {9.6019f,52.381f}, + {4.84f,38.0952f}, + {4.84f,28.5714f}, + {9.6019f,14.2857f}, + {19.1257f,4.7619f}, + {28.6495f,0.0f}, + {42.9352f,0.0f}, + {52.459f,4.7619f}, + {61.9829f,14.2857f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch113st[] = +{ + {2,StrokeRoman_ch113st0}, + {14,StrokeRoman_ch113st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch113 = {70.7429f,2,StrokeRoman_ch113st}; + +/* char: 0x72 */ + +static const SFG_StrokeVertex StrokeRoman_ch114st0[] = +{ + {9.46f,66.6667f}, + {9.46f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch114st1[] = +{ + {9.46f,38.0952f}, + {14.2219f,52.381f}, + {23.7457f,61.9048f}, + {33.2695f,66.6667f}, + {47.5552f,66.6667f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch114st[] = +{ + {2,StrokeRoman_ch114st0}, + {5,StrokeRoman_ch114st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch114 = {49.4952f,2,StrokeRoman_ch114st}; + +/* char: 0x73 */ + +static const SFG_StrokeVertex StrokeRoman_ch115st0[] = +{ + {57.081f,52.381f}, + {52.319f,61.9048f}, + {38.0333f,66.6667f}, + {23.7476f,66.6667f}, + {9.4619f,61.9048f}, + {4.7f,52.381f}, + {9.4619f,42.8571f}, + {18.9857f,38.0952f}, + {42.7952f,33.3333f}, + {52.319f,28.5714f}, + {57.081f,19.0476f}, + {57.081f,14.2857f}, + {52.319f,4.7619f}, + {38.0333f,0.0f}, + {23.7476f,0.0f}, + {9.4619f,4.7619f}, + {4.7f,14.2857f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch115st[] = +{ + {17,StrokeRoman_ch115st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch115 = {62.321f,1,StrokeRoman_ch115st}; + +/* char: 0x74 */ + +static const SFG_StrokeVertex StrokeRoman_ch116st0[] = +{ + {14.8257f,100.0f}, + {14.8257f,19.0476f}, + {19.5876f,4.7619f}, + {29.1114f,0.0f}, + {38.6352f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch116st1[] = +{ + {0.54f,66.6667f}, + {33.8733f,66.6667f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch116st[] = +{ + {5,StrokeRoman_ch116st0}, + {2,StrokeRoman_ch116st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch116 = {39.3152f,2,StrokeRoman_ch116st}; + +/* char: 0x75 */ + +static const SFG_StrokeVertex StrokeRoman_ch117st0[] = +{ + {9.46f,66.6667f}, + {9.46f,19.0476f}, + {14.2219f,4.7619f}, + {23.7457f,0.0f}, + {38.0314f,0.0f}, + {47.5552f,4.7619f}, + {61.841f,19.0476f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch117st1[] = +{ + {61.841f,66.6667f}, + {61.841f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch117st[] = +{ + {7,StrokeRoman_ch117st0}, + {2,StrokeRoman_ch117st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch117 = {71.161f,2,StrokeRoman_ch117st}; + +/* char: 0x76 */ + +static const SFG_StrokeVertex StrokeRoman_ch118st0[] = +{ + {1.8f,66.6667f}, + {30.3714f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch118st1[] = +{ + {58.9429f,66.6667f}, + {30.3714f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch118st[] = +{ + {2,StrokeRoman_ch118st0}, + {2,StrokeRoman_ch118st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch118 = {60.6029f,2,StrokeRoman_ch118st}; + +/* char: 0x77 */ + +static const SFG_StrokeVertex StrokeRoman_ch119st0[] = +{ + {2.5f,66.6667f}, + {21.5476f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch119st1[] = +{ + {40.5952f,66.6667f}, + {21.5476f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch119st2[] = +{ + {40.5952f,66.6667f}, + {59.6429f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch119st3[] = +{ + {78.6905f,66.6667f}, + {59.6429f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch119st[] = +{ + {2,StrokeRoman_ch119st0}, + {2,StrokeRoman_ch119st1}, + {2,StrokeRoman_ch119st2}, + {2,StrokeRoman_ch119st3} +}; + +static const SFG_StrokeChar StrokeRoman_ch119 = {80.4905f,4,StrokeRoman_ch119st}; + +/* char: 0x78 */ + +static const SFG_StrokeVertex StrokeRoman_ch120st0[] = +{ + {1.66f,66.6667f}, + {54.041f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch120st1[] = +{ + {54.041f,66.6667f}, + {1.66f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch120st[] = +{ + {2,StrokeRoman_ch120st0}, + {2,StrokeRoman_ch120st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch120 = {56.401f,2,StrokeRoman_ch120st}; + +/* char: 0x79 */ + +static const SFG_StrokeVertex StrokeRoman_ch121st0[] = +{ + {6.5619f,66.6667f}, + {35.1333f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch121st1[] = +{ + {63.7048f,66.6667f}, + {35.1333f,0.0f}, + {25.6095f,-19.0476f}, + {16.0857f,-28.5714f}, + {6.5619f,-33.3333f}, + {1.8f,-33.3333f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch121st[] = +{ + {2,StrokeRoman_ch121st0}, + {6,StrokeRoman_ch121st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch121 = {66.0648f,2,StrokeRoman_ch121st}; + +/* char: 0x7a */ + +static const SFG_StrokeVertex StrokeRoman_ch122st0[] = +{ + {56.821f,66.6667f}, + {4.44f,0.0f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch122st1[] = +{ + {4.44f,66.6667f}, + {56.821f,66.6667f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch122st2[] = +{ + {4.44f,0.0f}, + {56.821f,0.0f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch122st[] = +{ + {2,StrokeRoman_ch122st0}, + {2,StrokeRoman_ch122st1}, + {2,StrokeRoman_ch122st2} +}; + +static const SFG_StrokeChar StrokeRoman_ch122 = {61.821f,3,StrokeRoman_ch122st}; + +/* char: 0x7b */ + +static const SFG_StrokeVertex StrokeRoman_ch123st0[] = +{ + {31.1895f,119.048f}, + {21.6657f,114.286f}, + {16.9038f,109.524f}, + {12.1419f,100.0f}, + {12.1419f,90.4762f}, + {16.9038f,80.9524f}, + {21.6657f,76.1905f}, + {26.4276f,66.6667f}, + {26.4276f,57.1429f}, + {16.9038f,47.619f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch123st1[] = +{ + {21.6657f,114.286f}, + {16.9038f,104.762f}, + {16.9038f,95.2381f}, + {21.6657f,85.7143f}, + {26.4276f,80.9524f}, + {31.1895f,71.4286f}, + {31.1895f,61.9048f}, + {26.4276f,52.381f}, + {7.38f,42.8571f}, + {26.4276f,33.3333f}, + {31.1895f,23.8095f}, + {31.1895f,14.2857f}, + {26.4276f,4.7619f}, + {21.6657f,0.0f}, + {16.9038f,-9.5238f}, + {16.9038f,-19.0476f}, + {21.6657f,-28.5714f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch123st2[] = +{ + {16.9038f,38.0952f}, + {26.4276f,28.5714f}, + {26.4276f,19.0476f}, + {21.6657f,9.5238f}, + {16.9038f,4.7619f}, + {12.1419f,-4.7619f}, + {12.1419f,-14.2857f}, + {16.9038f,-23.8095f}, + {21.6657f,-28.5714f}, + {31.1895f,-33.3333f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch123st[] = +{ + {10,StrokeRoman_ch123st0}, + {17,StrokeRoman_ch123st1}, + {10,StrokeRoman_ch123st2} +}; + +static const SFG_StrokeChar StrokeRoman_ch123 = {41.6295f,3,StrokeRoman_ch123st}; + +/* char: 0x7c */ + +static const SFG_StrokeVertex StrokeRoman_ch124st0[] = +{ + {11.54f,119.048f}, + {11.54f,-33.3333f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch124st[] = +{ + {2,StrokeRoman_ch124st0} +}; + +static const SFG_StrokeChar StrokeRoman_ch124 = {23.78f,1,StrokeRoman_ch124st}; + +/* char: 0x7d */ + +static const SFG_StrokeVertex StrokeRoman_ch125st0[] = +{ + {9.18f,119.048f}, + {18.7038f,114.286f}, + {23.4657f,109.524f}, + {28.2276f,100.0f}, + {28.2276f,90.4762f}, + {23.4657f,80.9524f}, + {18.7038f,76.1905f}, + {13.9419f,66.6667f}, + {13.9419f,57.1429f}, + {23.4657f,47.619f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch125st1[] = +{ + {18.7038f,114.286f}, + {23.4657f,104.762f}, + {23.4657f,95.2381f}, + {18.7038f,85.7143f}, + {13.9419f,80.9524f}, + {9.18f,71.4286f}, + {9.18f,61.9048f}, + {13.9419f,52.381f}, + {32.9895f,42.8571f}, + {13.9419f,33.3333f}, + {9.18f,23.8095f}, + {9.18f,14.2857f}, + {13.9419f,4.7619f}, + {18.7038f,0.0f}, + {23.4657f,-9.5238f}, + {23.4657f,-19.0476f}, + {18.7038f,-28.5714f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch125st2[] = +{ + {23.4657f,38.0952f}, + {13.9419f,28.5714f}, + {13.9419f,19.0476f}, + {18.7038f,9.5238f}, + {23.4657f,4.7619f}, + {28.2276f,-4.7619f}, + {28.2276f,-14.2857f}, + {23.4657f,-23.8095f}, + {18.7038f,-28.5714f}, + {9.18f,-33.3333f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch125st[] = +{ + {10,StrokeRoman_ch125st0}, + {17,StrokeRoman_ch125st1}, + {10,StrokeRoman_ch125st2} +}; + +static const SFG_StrokeChar StrokeRoman_ch125 = {41.4695f,3,StrokeRoman_ch125st}; + +/* char: 0x7e */ + +static const SFG_StrokeVertex StrokeRoman_ch126st0[] = +{ + {2.92f,28.5714f}, + {2.92f,38.0952f}, + {7.6819f,52.381f}, + {17.2057f,57.1429f}, + {26.7295f,57.1429f}, + {36.2533f,52.381f}, + {55.301f,38.0952f}, + {64.8248f,33.3333f}, + {74.3486f,33.3333f}, + {83.8724f,38.0952f}, + {88.6343f,47.619f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch126st1[] = +{ + {2.92f,38.0952f}, + {7.6819f,47.619f}, + {17.2057f,52.381f}, + {26.7295f,52.381f}, + {36.2533f,47.619f}, + {55.301f,33.3333f}, + {64.8248f,28.5714f}, + {74.3486f,28.5714f}, + {83.8724f,33.3333f}, + {88.6343f,47.619f}, + {88.6343f,57.1429f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch126st[] = +{ + {11,StrokeRoman_ch126st0}, + {11,StrokeRoman_ch126st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch126 = {91.2743f,2,StrokeRoman_ch126st}; + +/* char: 0x7f */ + +static const SFG_StrokeVertex StrokeRoman_ch127st0[] = +{ + {52.381f,100.0f}, + {14.2857f,-33.3333f} +}; + +static const SFG_StrokeVertex StrokeRoman_ch127st1[] = +{ + {28.5714f,66.6667f}, + {14.2857f,61.9048f}, + {4.7619f,52.381f}, + {0.0f,38.0952f}, + {0.0f,23.8095f}, + {4.7619f,14.2857f}, + {14.2857f,4.7619f}, + {28.5714f,0.0f}, + {38.0952f,0.0f}, + {52.381f,4.7619f}, + {61.9048f,14.2857f}, + {66.6667f,28.5714f}, + {66.6667f,42.8571f}, + {61.9048f,52.381f}, + {52.381f,61.9048f}, + {38.0952f,66.6667f}, + {28.5714f,66.6667f} +}; + +static const SFG_StrokeStrip StrokeRoman_ch127st[] = +{ + {2,StrokeRoman_ch127st0}, + {17,StrokeRoman_ch127st1} +}; + +static const SFG_StrokeChar StrokeRoman_ch127 = {66.6667f,2,StrokeRoman_ch127st}; + +static const SFG_StrokeChar *StrokeRoman_chars[] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + &StrokeRoman_ch32, &StrokeRoman_ch33, &StrokeRoman_ch34, &StrokeRoman_ch35, &StrokeRoman_ch36, &StrokeRoman_ch37, &StrokeRoman_ch38, &StrokeRoman_ch39, + &StrokeRoman_ch40, &StrokeRoman_ch41, &StrokeRoman_ch42, &StrokeRoman_ch43, &StrokeRoman_ch44, &StrokeRoman_ch45, &StrokeRoman_ch46, &StrokeRoman_ch47, + &StrokeRoman_ch48, &StrokeRoman_ch49, &StrokeRoman_ch50, &StrokeRoman_ch51, &StrokeRoman_ch52, &StrokeRoman_ch53, &StrokeRoman_ch54, &StrokeRoman_ch55, + &StrokeRoman_ch56, &StrokeRoman_ch57, &StrokeRoman_ch58, &StrokeRoman_ch59, &StrokeRoman_ch60, &StrokeRoman_ch61, &StrokeRoman_ch62, &StrokeRoman_ch63, + &StrokeRoman_ch64, &StrokeRoman_ch65, &StrokeRoman_ch66, &StrokeRoman_ch67, &StrokeRoman_ch68, &StrokeRoman_ch69, &StrokeRoman_ch70, &StrokeRoman_ch71, + &StrokeRoman_ch72, &StrokeRoman_ch73, &StrokeRoman_ch74, &StrokeRoman_ch75, &StrokeRoman_ch76, &StrokeRoman_ch77, &StrokeRoman_ch78, &StrokeRoman_ch79, + &StrokeRoman_ch80, &StrokeRoman_ch81, &StrokeRoman_ch82, &StrokeRoman_ch83, &StrokeRoman_ch84, &StrokeRoman_ch85, &StrokeRoman_ch86, &StrokeRoman_ch87, + &StrokeRoman_ch88, &StrokeRoman_ch89, &StrokeRoman_ch90, &StrokeRoman_ch91, &StrokeRoman_ch92, &StrokeRoman_ch93, &StrokeRoman_ch94, &StrokeRoman_ch95, + &StrokeRoman_ch96, &StrokeRoman_ch97, &StrokeRoman_ch98, &StrokeRoman_ch99, &StrokeRoman_ch100, &StrokeRoman_ch101, &StrokeRoman_ch102, &StrokeRoman_ch103, + &StrokeRoman_ch104, &StrokeRoman_ch105, &StrokeRoman_ch106, &StrokeRoman_ch107, &StrokeRoman_ch108, &StrokeRoman_ch109, &StrokeRoman_ch110, &StrokeRoman_ch111, + &StrokeRoman_ch112, &StrokeRoman_ch113, &StrokeRoman_ch114, &StrokeRoman_ch115, &StrokeRoman_ch116, &StrokeRoman_ch117, &StrokeRoman_ch118, &StrokeRoman_ch119, + &StrokeRoman_ch120, &StrokeRoman_ch121, &StrokeRoman_ch122, &StrokeRoman_ch123, &StrokeRoman_ch124, &StrokeRoman_ch125, &StrokeRoman_ch126, &StrokeRoman_ch127 +}; + +SFG_StrokeFont fgStrokeRoman = {"Roman",128,152.381f,StrokeRoman_chars}; diff --git a/src/fg_structure.c b/src/fg_structure.c new file mode 100644 index 0000000..747a8b5 --- /dev/null +++ b/src/fg_structure.c @@ -0,0 +1,689 @@ +/* + * fg_structure.c + * + * Windows and menus need tree structure + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Sat Dec 18 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" + +/* -- GLOBAL EXPORTS ------------------------------------------------------- */ + +/* + * The SFG_Structure container holds information about windows and menus + * created between glutInit() and glutMainLoop() return. + */ + +SFG_Structure fgStructure = { { NULL, NULL }, /* The list of windows */ + { NULL, NULL }, /* The list of menus */ + { NULL, NULL }, /* Windows to Destroy list */ + NULL, /* The current window */ + NULL, /* The current menu */ + NULL, /* The menu OpenGL context */ + NULL, /* The game mode window */ + 0, /* The current new window ID */ + 0 }; /* The current new menu ID */ + + +/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ + +extern void fgPlatformCreateWindow ( SFG_Window *window ); +extern void fghDefaultReshape(int width, int height, FGCBUserData userData); + +static void fghClearCallBacks( SFG_Window *window ) +{ + if( window ) + { + int i; + for( i = 0; i < TOTAL_CALLBACKS; ++i ) + { + window->CallBacks[ i ] = NULL; + window->CallbackDatas[ i ] = NULL; + } + } +} + +/* + * This private function creates, opens and adds to the hierarchy + * a freeglut window complete with OpenGL context and stuff... + * + * If parent is set to NULL, the window created will be a topmost one. + */ +SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, + GLboolean positionUse, int x, int y, + GLboolean sizeUse, int w, int h, + GLboolean gameMode, GLboolean isMenu ) +{ + /* Have the window object created */ + SFG_Window *window = (SFG_Window *)calloc( 1, sizeof(SFG_Window) ); + + if( !window ) + { + fgError( "Out of memory. Could not create window." ); + } + + fgPlatformCreateWindow ( window ); + + fghClearCallBacks( window ); + SET_WCB( *window, Reshape, fghDefaultReshape, NULL); + + /* Initialize the object properties */ + window->ID = ++fgStructure.WindowID; + + fgListInit( &window->Children ); + if( parent ) + { + fgListAppend( &parent->Children, &window->Node ); + window->Parent = parent; + } + else + fgListAppend( &fgStructure.Windows, &window->Node ); + + /* Set the default mouse cursor */ + window->State.Cursor = GLUT_CURSOR_INHERIT; + + /* Mark window as menu if a menu is to be created */ + window->IsMenu = isMenu; + + /* + * Open the window now. The fgOpenWindow() function is system + * dependent, and resides in fg_window.c. Uses fgState. + */ + fgOpenWindow( window, title, positionUse, x, y, sizeUse, w, h, gameMode, + (GLboolean)(parent ? GL_TRUE : GL_FALSE) ); + + return window; +} + +/* + * This private function creates a menu and adds it to the menus list + */ +SFG_Menu* fgCreateMenu( FGCBMenuUC menuCallback, FGCBUserData userData ) +{ + SFG_Window *current_window = fgStructure.CurrentWindow; + + /* Have the menu object created */ + SFG_Menu* menu = (SFG_Menu *)calloc( sizeof(SFG_Menu), 1 ); + + menu->ParentWindow = NULL; + + /* Create a window for the menu to reside in. */ + fgCreateWindow( NULL, "freeglut menu", GL_FALSE, 0, 0, GL_FALSE, 0, 0, + GL_FALSE, GL_TRUE ); + menu->Window = fgStructure.CurrentWindow; + glutDisplayFunc( fgDisplayMenu ); + + fgSetWindow( current_window ); + + /* Initialize the object properties: */ + menu->ID = ++fgStructure.MenuID; + menu->Callback = menuCallback; + menu->CallbackData = userData; + menu->ActiveEntry = NULL; + menu->Font = fgState.MenuFont; + + fgListInit( &menu->Entries ); + fgListAppend( &fgStructure.Menus, &menu->Node ); + + /* Newly created menus implicitly become current ones */ + fgStructure.CurrentMenu = menu; + + return menu; +} + +/* + * Function to add a window to the linked list of windows to destroy. + * Subwindows are automatically added because they hang from the window + * structure. + */ +void fgAddToWindowDestroyList( SFG_Window* window ) +{ + SFG_WindowList *new_list_entry = + ( SFG_WindowList* )malloc( sizeof(SFG_WindowList ) ); + new_list_entry->window = window; + fgListAppend( &fgStructure.WindowsToDestroy, &new_list_entry->node ); + + /* Check if the window is the current one... */ + if( fgStructure.CurrentWindow == window ) + fgStructure.CurrentWindow = NULL; + + /* + * Clear all window callbacks except Destroy, which will + * be invoked later. Right now, we are potentially carrying + * out a freeglut operation at the behest of a client callback, + * so we are reluctant to re-enter the client with the Destroy + * callback, right now. The others are all wiped out, however, + * to ensure that they are no longer called after this point. + */ + { + FGCBDestroyUC destroy = (FGCBDestroyUC)FETCH_WCB( *window, Destroy ); + FGCBUserData destroyData = FETCH_USER_DATA_WCB( *window, Destroy ); + fghClearCallBacks( window ); + SET_WCB( *window, Destroy, destroy, destroyData ); + } + + /* + * Similarly, clear all work set for the window, none of this has to be executed anymore + */ + window->State.WorkMask = 0; +} + +/* + * Function to close down all the windows in the "WindowsToDestroy" list + */ +void fgCloseWindows( ) +{ + while( fgStructure.WindowsToDestroy.First ) + { + SFG_WindowList *window_ptr = fgStructure.WindowsToDestroy.First; + fgDestroyWindow( window_ptr->window ); + fgListRemove( &fgStructure.WindowsToDestroy, &window_ptr->node ); + free( window_ptr ); + } +} + +/* + * This function destroys a window and all of its subwindows. Actually, + * another function, defined in fg_window.c is called, but this is + * a whole different story... + */ +void fgDestroyWindow( SFG_Window* window ) +{ + FREEGLUT_INTERNAL_ERROR_EXIT ( window, "Window destroy function called with null window", + "fgDestroyWindow" ); + + while( window->Children.First ) + fgDestroyWindow( ( SFG_Window * )window->Children.First ); + + { + SFG_Window *activeWindow = fgStructure.CurrentWindow; + INVOKE_WCB( *window, Destroy, ( ) ); + fgSetWindow( activeWindow ); + } + + if( window->Parent ) + fgListRemove( &window->Parent->Children, &window->Node ); + else + fgListRemove( &fgStructure.Windows, &window->Node ); + + if( window->ActiveMenu ) + fgDeactivateMenu( window ); + + fghClearCallBacks( window ); + fgCloseWindow( window ); + free( window ); + if( fgStructure.CurrentWindow == window ) + fgStructure.CurrentWindow = NULL; +} + +/* + * This is a helper static function that removes a menu (given its pointer) + * from any windows that can be accessed from a given parent... + */ +static void fghRemoveMenuFromWindow( SFG_Window* window, SFG_Menu* menu ) +{ + SFG_Window *subWindow; + int i; + + /* Check whether this is the active menu in the window */ + if ( menu == window->ActiveMenu ) + window->ActiveMenu = NULL ; + + /* + * Check if the menu is attached to the current window, + * if so, have it detached (by overwriting with a NULL): + */ + for( i = 0; i < FREEGLUT_MAX_MENUS; i++ ) + if( window->Menu[ i ] == menu ) + window->Menu[ i ] = NULL; + + /* Call this function for all of the window's children recursively: */ + for( subWindow = (SFG_Window *)window->Children.First; + subWindow; + subWindow = (SFG_Window *)subWindow->Node.Next) + fghRemoveMenuFromWindow( subWindow, menu ); +} + +/* + * This is a static helper function that removes menu references + * from another menu, given two pointers to them... + */ +static void fghRemoveMenuFromMenu( SFG_Menu* from, SFG_Menu* menu ) +{ + SFG_MenuEntry *entry; + + for( entry = (SFG_MenuEntry *)from->Entries.First; + entry; + entry = ( SFG_MenuEntry * )entry->Node.Next ) + if( entry->SubMenu == menu ) + entry->SubMenu = NULL; +} + +/* + * This function destroys a menu specified by the parameter. All menus + * and windows are updated to make sure no ill pointers hang around. + */ +void fgDestroyMenu( SFG_Menu* menu ) +{ + SFG_Window *window; + SFG_Menu *from; + + FREEGLUT_INTERNAL_ERROR_EXIT ( menu, "Menu destroy function called with null menu", + "fgDestroyMenu" ); + + /* First of all, have all references to this menu removed from all windows: */ + for( window = (SFG_Window *)fgStructure.Windows.First; + window; + window = (SFG_Window *)window->Node.Next ) + fghRemoveMenuFromWindow( window, menu ); + + /* Now proceed with removing menu entries that lead to this menu */ + for( from = ( SFG_Menu * )fgStructure.Menus.First; + from; + from = ( SFG_Menu * )from->Node.Next ) + fghRemoveMenuFromMenu( from, menu ); + + /* + * If the programmer defined a destroy callback, call it + * A. Donev: But first make this the active menu + */ + if( menu->Destroy ) + { + SFG_Menu *activeMenu=fgStructure.CurrentMenu; + fgStructure.CurrentMenu = menu; + menu->Destroy( menu->DestroyData ); + fgStructure.CurrentMenu = activeMenu; + } + + /* + * Now we are pretty sure the menu is not used anywhere + * and that we can remove all of its entries + */ + while( menu->Entries.First ) + { + SFG_MenuEntry *entry = ( SFG_MenuEntry * ) menu->Entries.First; + + fgListRemove( &menu->Entries, &entry->Node ); + + if( entry->Text ) + free( entry->Text ); + entry->Text = NULL; + + free( entry ); + } + + if( fgStructure.CurrentWindow == menu->Window ) + fgSetWindow( NULL ); + fgDestroyWindow( menu->Window ); + fgListRemove( &fgStructure.Menus, &menu->Node ); + if( fgStructure.CurrentMenu == menu ) + fgStructure.CurrentMenu = NULL; + + free( menu ); +} + +/* + * This function should be called on glutInit(). It will prepare the internal + * structure of freeglut to be used in the application. The structure will be + * destroyed using fgDestroyStructure() on glutMainLoop() return. In that + * case further use of freeglut should be preceded with a glutInit() call. + */ +void fgCreateStructure( void ) +{ + /* + * We will be needing two lists: the first containing windows, + * and the second containing the user-defined menus. + * Also, no current window/menu is set, as none has been created yet. + */ + + fgListInit(&fgStructure.Windows); + fgListInit(&fgStructure.Menus); + fgListInit(&fgStructure.WindowsToDestroy); + + fgStructure.CurrentWindow = NULL; + fgStructure.CurrentMenu = NULL; + fgStructure.MenuContext = NULL; + fgStructure.GameModeWindow = NULL; + fgStructure.WindowID = 0; + fgStructure.MenuID = 0; +} + +/* + * This function is automatically called on glutMainLoop() return. + * It should deallocate and destroy all remnants of previous + * glutInit()-enforced structure initialization... + */ +void fgDestroyStructure( void ) +{ + /* Clean up the WindowsToDestroy list. */ + fgCloseWindows( ); + + /* Make sure all windows and menus have been deallocated */ + while( fgStructure.Menus.First ) + fgDestroyMenu( ( SFG_Menu * )fgStructure.Menus.First ); + + while( fgStructure.Windows.First ) + fgDestroyWindow( ( SFG_Window * )fgStructure.Windows.First ); +} + +/* + * Helper function to enumerate through all registered top-level windows + */ +void fgEnumWindows( FGCBWindowEnumerator enumCallback, SFG_Enumerator* enumerator ) +{ + SFG_Window *window; + + FREEGLUT_INTERNAL_ERROR_EXIT ( enumCallback && enumerator, + "Enumerator or callback missing from window enumerator call", + "fgEnumWindows" ); + + /* Check every of the top-level windows */ + for( window = ( SFG_Window * )fgStructure.Windows.First; + window; + window = ( SFG_Window * )window->Node.Next ) + { + enumCallback( window, enumerator ); + if( enumerator->found ) + return; + } +} + +/* +* Helper function to enumerate through all registered top-level windows +*/ +void fgEnumMenus( FGCBMenuEnumerator enumCallback, SFG_Enumerator* enumerator ) +{ + SFG_Menu *menu; + + FREEGLUT_INTERNAL_ERROR_EXIT ( enumCallback && enumerator, + "Enumerator or callback missing from window enumerator call", + "fgEnumWindows" ); + + /* It's enough to check all entries in fgStructure.Menus... */ + for( menu = (SFG_Menu *)fgStructure.Menus.First; + menu; + menu = (SFG_Menu *)menu->Node.Next ) + { + enumCallback( menu, enumerator ); + if( enumerator->found ) + return; + } +} + +/* + * Helper function to enumerate through all a window's subwindows + * (single level descent) + */ +void fgEnumSubWindows( SFG_Window* window, FGCBWindowEnumerator enumCallback, + SFG_Enumerator* enumerator ) +{ + SFG_Window *child; + + FREEGLUT_INTERNAL_ERROR_EXIT ( enumCallback && enumerator, + "Enumerator or callback missing from subwindow enumerator call", + "fgEnumSubWindows" ); + FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED ( "Window Enumeration" ); + + for( child = ( SFG_Window * )window->Children.First; + child; + child = ( SFG_Window * )child->Node.Next ) + { + enumCallback( child, enumerator ); + if( enumerator->found ) + return; + } +} + +/* + * A static helper function to look for a window given its handle + */ +static void fghcbWindowByHandle( SFG_Window *window, + SFG_Enumerator *enumerator ) +{ + if ( enumerator->found ) + return; + + /* Check the window's handle. Hope this works. Looks ugly. That's for sure. */ + if( window->Window.Handle == (SFG_WindowHandleType) (enumerator->data) ) + { + enumerator->found = GL_TRUE; + enumerator->data = window; + + return; + } + + /* Otherwise, check this window's children */ + fgEnumSubWindows( window, fghcbWindowByHandle, enumerator ); +} + +/* + * fgWindowByHandle returns a (SFG_Window *) value pointing to the + * first window in the queue matching the specified window handle. + * The function is defined in fg_structure.c file. + */ +SFG_Window* fgWindowByHandle ( SFG_WindowHandleType hWindow ) +{ + SFG_Enumerator enumerator; + + /* This is easy and makes use of the windows enumeration defined above */ + enumerator.found = GL_FALSE; + enumerator.data = (void *)hWindow; + fgEnumWindows( fghcbWindowByHandle, &enumerator ); + + if( enumerator.found ) + return( SFG_Window *) enumerator.data; + return NULL; +} + +/* + * A static helper function to look for a window given its ID + */ +static void fghcbWindowByID( SFG_Window *window, SFG_Enumerator *enumerator ) +{ + /* Make sure we do not overwrite our precious results... */ + if( enumerator->found ) + return; + + /* Check the window's handle. Hope this works. Looks ugly. That's for sure. */ + if( window->ID == *( int *)(enumerator->data) ) + { + enumerator->found = GL_TRUE; + enumerator->data = window; + + return; + } + + /* Otherwise, check this window's children */ + fgEnumSubWindows( window, fghcbWindowByID, enumerator ); +} + +/* + * This function is similar to the previous one, except it is + * looking for a specified (sub)window identifier. The function + * is defined in fg_structure.c file. + */ +SFG_Window* fgWindowByID( int windowID ) +{ + SFG_Enumerator enumerator; + + /* Uses a method very similar for fgWindowByHandle... */ + enumerator.found = GL_FALSE; + enumerator.data = ( void * )&windowID; + fgEnumWindows( fghcbWindowByID, &enumerator ); + if( enumerator.found ) + return ( SFG_Window * )enumerator.data; + return NULL; +} + +/* + * A static helper function to look for a menu given its ID + */ +static void fghcbMenuByID( SFG_Menu *menu, + SFG_Enumerator *enumerator ) +{ + if ( enumerator->found ) + return; + + /* Check the menu's ID. */ + if( menu->ID == *( int *)(enumerator->data) ) + { + enumerator->found = GL_TRUE; + enumerator->data = menu; + + return; + } +} + +/* + * Looks up a menu given its ID. This is easier than fgWindowByXXX + * as all menus are placed in one doubly linked list... + */ +SFG_Menu* fgMenuByID( int menuID ) +{ + SFG_Enumerator enumerator; + + /* This is easy and makes use of the menus enumeration defined above */ + enumerator.found = GL_FALSE; + enumerator.data = (void *)&menuID; + fgEnumMenus( fghcbMenuByID, &enumerator ); + + if( enumerator.found ) + return( SFG_Menu *) enumerator.data; + + return NULL; +} + +/* + * A static helper function to look for an active menu + */ +static void fghcbGetActiveMenu( SFG_Menu *menu, + SFG_Enumerator *enumerator ) +{ + if ( enumerator->found ) + return; + + /* Check the menu's is active */ + if( menu->IsActive ) + { + enumerator->found = GL_TRUE; + enumerator->data = menu; + + return; + } +} + +/* + * Returns active menu, if any. Assumption: only one menu active throughout application at any one time. + * This is false when a submenu is also open. + * This is easier than fgWindowByXXX as all menus are placed in one doubly linked list... + */ +SFG_Menu* fgGetActiveMenu( ) +{ + SFG_Enumerator enumerator; + + /* This is easy and makes use of the menus enumeration defined above */ + enumerator.found = GL_FALSE; + fgEnumMenus( fghcbGetActiveMenu, &enumerator ); + + if( enumerator.found ) + return( SFG_Menu *) enumerator.data; + + return NULL; +} + +/* + * List functions... + */ +void fgListInit(SFG_List *list) +{ + list->First = NULL; + list->Last = NULL; +} + +void fgListAppend(SFG_List *list, SFG_Node *node) +{ + if ( list->Last ) + { + SFG_Node *ln = (SFG_Node *) list->Last; + ln->Next = node; + node->Prev = ln; + } + else + { + node->Prev = NULL; + list->First = node; + } + + node->Next = NULL; + list->Last = node; +} + +void fgListRemove(SFG_List *list, SFG_Node *node) +{ + if( node->Next ) + ( ( SFG_Node * )node->Next )->Prev = node->Prev; + if( node->Prev ) + ( ( SFG_Node * )node->Prev )->Next = node->Next; + if( ( ( SFG_Node * )list->First ) == node ) + list->First = node->Next; + if( ( ( SFG_Node * )list->Last ) == node ) + list->Last = node->Prev; +} + +int fgListLength(SFG_List *list) +{ + SFG_Node *node; + int length = 0; + + for( node =( SFG_Node * )list->First; + node; + node = ( SFG_Node * )node->Next ) + ++length; + + return length; +} + + +void fgListInsert(SFG_List *list, SFG_Node *next, SFG_Node *node) +{ + SFG_Node *prev; + + if( (node->Next = next) ) + { + prev = next->Prev; + next->Prev = node; + } + else + { + prev = list->Last; + list->Last = node; + } + + if( (node->Prev = prev) ) + prev->Next = node; + else + list->First = node; +} + +/*** END OF FILE ***/ diff --git a/src/fg_teapot.c b/src/fg_teapot.c new file mode 100644 index 0000000..a378b9b --- /dev/null +++ b/src/fg_teapot.c @@ -0,0 +1,570 @@ +/* + * fg_teapot.c + * + * Teapot(tm) rendering code. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Fri Dec 24 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* notes: + * the (very little) required math is found here: http://www.gamasutra.com/view/feature/131848/tessellation_of_4x4_bezier_patches_.php?print=1 + * a much more optimized version is here, didn't bother to implement that: http://www.gamasutra.com/view/feature/131794/an_indepth_look_at_bicubic_bezier_.php?print=1 + */ + +#include +#include "fg_internal.h" +#include "fg_teapot_data.h" + +/* -- STATIC VARS: CACHES ---------------------------------------------------- */ + +/* General defs */ +#define GLUT_SOLID_N_SUBDIV 8 +#define GLUT_WIRE_N_SUBDIV 10 + +/* Bernstein coefficients only have to be precomputed once (number of patch subdivisions is fixed) + * Can thus define arrays for them here, they will be filled upon first use. + * 3rd order Bezier surfaces have 4 Bernstein coeffs. + * Have separate caches for solid and wire as they use a different number of subdivisions + * _0 is for Bernstein polynomials, _1 for their first derivative (which we need for normals) + */ +static GLfloat bernWire_0 [GLUT_WIRE_N_SUBDIV] [4]; +static GLfloat bernWire_1 [GLUT_WIRE_N_SUBDIV] [4]; +static GLfloat bernSolid_0[GLUT_SOLID_N_SUBDIV][4]; +static GLfloat bernSolid_1[GLUT_SOLID_N_SUBDIV][4]; + +/* Teapot defs */ +#define GLUT_TEAPOT_N_PATCHES (6*4 + 4*2) /* 6 patches are reproduced (rotated) 4 times, 4 patches (flipped) 2 times */ +#define GLUT_SOLID_TEAPOT_N_VERT GLUT_SOLID_N_SUBDIV*GLUT_SOLID_N_SUBDIV * GLUT_TEAPOT_N_PATCHES /* N_SUBDIV^2 vertices per patch */ +#define GLUT_SOLID_TEAPOT_N_TRI (GLUT_SOLID_N_SUBDIV-1)*(GLUT_SOLID_N_SUBDIV-1) * GLUT_TEAPOT_N_PATCHES * 2 /* if e.g. 7x7 vertices for each patch, there are 6*6 squares for each patch. Each square is decomposed into 2 triangles */ + +#define GLUT_WIRE_TEAPOT_N_VERT GLUT_WIRE_N_SUBDIV*GLUT_WIRE_N_SUBDIV * GLUT_TEAPOT_N_PATCHES /* N_SUBDIV^2 vertices per patch */ + +/* Bit of caching: + * vertex indices and normals only need to be generated once for + * a given number of subdivisions as they don't change with scale. + * Vertices can be cached and reused if scale didn't change. + */ +static GLushort vertIdxsTeapotS[GLUT_SOLID_TEAPOT_N_TRI*3]; +static GLfloat normsTeapotS [GLUT_SOLID_TEAPOT_N_VERT*3]; +static GLfloat vertsTeapotS [GLUT_SOLID_TEAPOT_N_VERT*3]; +static GLfloat texcsTeapotS [GLUT_SOLID_TEAPOT_N_VERT*2]; +static GLfloat lastScaleTeapotS = 0.f; +static GLboolean initedTeapotS = GL_FALSE; + +static GLushort vertIdxsTeapotW[GLUT_WIRE_TEAPOT_N_VERT*2]; +static GLfloat normsTeapotW [GLUT_WIRE_TEAPOT_N_VERT*3]; +static GLfloat vertsTeapotW [GLUT_WIRE_TEAPOT_N_VERT*3]; +static GLfloat lastScaleTeapotW = 0.f; +static GLboolean initedTeapotW = GL_FALSE; + + +/* Teacup defs */ +#define GLUT_TEACUP_N_PATCHES (6*4 + 1*2) /* 6 patches are reproduced (rotated) 4 times, 1 patch (flipped) 2 times */ +#define GLUT_SOLID_TEACUP_N_VERT GLUT_SOLID_N_SUBDIV*GLUT_SOLID_N_SUBDIV * GLUT_TEACUP_N_PATCHES /* N_SUBDIV^2 vertices per patch */ +#define GLUT_SOLID_TEACUP_N_TRI (GLUT_SOLID_N_SUBDIV-1)*(GLUT_SOLID_N_SUBDIV-1) * GLUT_TEACUP_N_PATCHES * 2 /* if e.g. 7x7 vertices for each patch, there are 6*6 squares for each patch. Each square is decomposed into 2 triangles */ + +#define GLUT_WIRE_TEACUP_N_VERT GLUT_WIRE_N_SUBDIV*GLUT_WIRE_N_SUBDIV * GLUT_TEACUP_N_PATCHES /* N_SUBDIV^2 vertices per patch */ + +/* Bit of caching: + * vertex indices and normals only need to be generated once for + * a given number of subdivisions as they don't change with scale. + * Vertices can be cached and reused if scale didn't change. + */ +static GLushort vertIdxsTeacupS[GLUT_SOLID_TEACUP_N_TRI*3]; +static GLfloat normsTeacupS [GLUT_SOLID_TEACUP_N_VERT*3]; +static GLfloat vertsTeacupS [GLUT_SOLID_TEACUP_N_VERT*3]; +static GLfloat texcsTeacupS [GLUT_SOLID_TEACUP_N_VERT*2]; +static GLfloat lastScaleTeacupS = 0.f; +static GLboolean initedTeacupS = GL_FALSE; + +static GLushort vertIdxsTeacupW[GLUT_WIRE_TEACUP_N_VERT*2]; +static GLfloat normsTeacupW [GLUT_WIRE_TEACUP_N_VERT*3]; +static GLfloat vertsTeacupW [GLUT_WIRE_TEACUP_N_VERT*3]; +static GLfloat lastScaleTeacupW = 0.f; +static GLboolean initedTeacupW = GL_FALSE; + + +/* Teaspoon defs */ +#define GLUT_TEASPOON_N_PATCHES GLUT_TEASPOON_N_INPUT_PATCHES +#define GLUT_SOLID_TEASPOON_N_VERT GLUT_SOLID_N_SUBDIV*GLUT_SOLID_N_SUBDIV * GLUT_TEASPOON_N_PATCHES /* N_SUBDIV^2 vertices per patch */ +#define GLUT_SOLID_TEASPOON_N_TRI (GLUT_SOLID_N_SUBDIV-1)*(GLUT_SOLID_N_SUBDIV-1) * GLUT_TEASPOON_N_PATCHES * 2 /* if e.g. 7x7 vertices for each patch, there are 6*6 squares for each patch. Each square is decomposed into 2 triangles */ + +#define GLUT_WIRE_TEASPOON_N_VERT GLUT_WIRE_N_SUBDIV*GLUT_WIRE_N_SUBDIV * GLUT_TEASPOON_N_PATCHES /* N_SUBDIV^2 vertices per patch */ + +/* Bit of caching: + * vertex indices and normals only need to be generated once for + * a given number of subdivisions as they don't change with scale. + * Vertices can be cached and reused if scale didn't change. + */ +static GLushort vertIdxsTeaspoonS[GLUT_SOLID_TEASPOON_N_TRI*3]; +static GLfloat normsTeaspoonS [GLUT_SOLID_TEASPOON_N_VERT*3]; +static GLfloat vertsTeaspoonS [GLUT_SOLID_TEASPOON_N_VERT*3]; +static GLfloat texcsTeaspoonS [GLUT_SOLID_TEASPOON_N_VERT*2]; +static GLfloat lastScaleTeaspoonS = 0.f; +static GLboolean initedTeaspoonS = GL_FALSE; + +static GLushort vertIdxsTeaspoonW[GLUT_WIRE_TEASPOON_N_VERT*2]; +static GLfloat normsTeaspoonW [GLUT_WIRE_TEASPOON_N_VERT*3]; +static GLfloat vertsTeaspoonW [GLUT_WIRE_TEASPOON_N_VERT*3]; +static GLfloat lastScaleTeaspoonW = 0.f; +static GLboolean initedTeaspoonW = GL_FALSE; + + + +/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ +extern void fghDrawGeometrySolid(GLfloat *vertices, GLfloat *normals, GLfloat *textcs, GLsizei numVertices, + GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart); +extern void fghDrawGeometryWire(GLfloat *vertices, GLfloat *normals, GLsizei numVertices, + GLushort *vertIdxs, GLsizei numParts, GLsizei numVertPerPart, GLenum vertexMode, + GLushort *vertIdxs2, GLsizei numParts2, GLsizei numVertPerPart2); + +/* evaluate 3rd order Bernstein polynomial and its 1st deriv */ +static void bernstein3(int i, GLfloat x, GLfloat *r0, GLfloat *r1) +{ + float invx = 1.f - x; + + /* r0: zero order coeff, r1: first deriv coeff */ + switch (i) + { + GLfloat temp; + case 0: + temp = invx*invx; + *r0 = invx * temp; /* invx * invx * invx */ + *r1 = -3 * temp; /* -3 * invx * invx */ + break; + case 1: + temp = invx*invx; + *r0 = 3 * x * temp; /* 3 * x * invx * invx */ + *r1 = 3 * temp - 6 * x * invx; /* 3 * invx * invx - 6 * x * invx */ + break; + case 2: + temp = x*x; + *r0 = 3 * temp * invx; /* 3 * x * x * invx */ + *r1 = 6 * x * invx - 3 * temp; /* 6 * x * invx - 3 * x * x */ + break; + case 3: + temp = x*x; + *r0 = x * temp; /* x * x * x */ + *r1 = 3 * temp; /* 3 * x * x */ + break; + default: + *r0 = *r1 = 0; + } +} + +static void pregenBernstein(int nSubDivs, GLfloat (*bern_0)[4], GLfloat (*bern_1)[4]) +{ + int s,i; + for (s=0; s was 1.5 for teapot, but should be 1.575 to center it on the Z axis. Teacup and teaspoon have different offsets + */ + cp[i/4][i%4][0] = cpdata[patchdata[p][i]][0] *scale/2.f; + cp[i/4][i%4][1] = (cpdata[patchdata[p][i]][2]-zOffset)*scale/2.f; + cp[i/4][i%4][2] = -cpdata[patchdata[p][i]][1] *scale/2.f; + } + + /* eval bezier patch */ + if (!*inited) /* first time, generate normals as well */ + o += evalBezierWithNorm(cp,nSubDivs,bern_0,bern_1, flag, normalFix, verts+o,norms+o); + else /* only need to regen vertices */ + o += evalBezier(cp,nSubDivs,bern_0, flag, verts+o); + } + *lastScale = scale; + + if (!*inited) + { + int r,c; + /* generate texture coordinates if solid teapot/teacup/teaspoon */ + if (!useWireMode) + { + /* generate for first patch */ + for (r=0,o=0; r + To: jk87377@tut.fi + Status: R + + Hi -- + + Here's the data you requested. Unfortunately, I have not found the data + for the creamer, so it is not included. The format is very simple. The first + line of each file is a comment describing what object is in the file. + The second line are counts : + + #vertices #objects #patches #patches + + Following this, there is a numbered list of vertices. Following the + vertices are, one per line, a list of indices of vertices, describing + each patch. The first index in each patch is preceded by the character + "-" to delimit patch index lists. The patches are all bicubic Bezier + patches, so there are 16 vertices in each patch, and thus the vertex lists + are each 16 entries long. This is analogous to an "indexed polygon", if you + are familiar with that format. + + The files follow below, delimited by two lines of "XXXXX". Let me know + if you have any problems understanding the format. + + - Philip Schneider + pjs@decwrl.dec.com + + XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + + Martin Newell's teapot made famous by J. Blinn (Bezier patches) + 269 1 28 28 + 1 0.397163 0.638298 0 + 2 0.397163 0.638298 -0.222411 + 3 0.222411 0.638298 -0.397163 + 4 0 0.638298 -0.397163 + 5 0.379433 0.675532 0 + 6 0.379433 0.675532 -0.212482 + 7 0.212482 0.675532 -0.379433 + 8 0 0.675532 -0.379433 + 9 0.407801 0.675532 0 + 10 0.407801 0.675532 -0.228369 + 11 0.228369 0.675532 -0.407801 + 12 0 0.675532 -0.407801 + 13 0.425532 0.638298 0 + 14 0.425532 0.638298 -0.238298 + 15 0.238298 0.638298 -0.425532 + 16 0 0.638298 -0.425532 + 17 -0.222411 0.638298 -0.397163 + 18 -0.397163 0.638298 -0.222411 + 19 -0.397163 0.638298 0 + 20 -0.212482 0.675532 -0.379433 + 21 -0.379433 0.675532 -0.212482 + 22 -0.379433 0.675532 0 + 23 -0.228369 0.675532 -0.407801 + 24 -0.407801 0.675532 -0.228369 + 25 -0.407801 0.675532 0 + 26 -0.238298 0.638298 -0.425532 + 27 -0.425532 0.638298 -0.238298 + 28 -0.425532 0.638298 0 + 29 -0.397163 0.638298 0.222411 + 30 -0.222411 0.638298 0.397163 + 31 0 0.638298 0.397163 + 32 -0.379433 0.675532 0.212482 + 33 -0.212482 0.675532 0.379433 + 34 0 0.675532 0.379433 + 35 -0.407801 0.675532 0.228369 + 36 -0.228369 0.675532 0.407801 + 37 0 0.675532 0.407801 + 38 -0.425532 0.638298 0.238298 + 39 -0.238298 0.638298 0.425532 + 40 0 0.638298 0.425532 + 41 0.222411 0.638298 0.397163 + 42 0.397163 0.638298 0.222411 + 43 0.212482 0.675532 0.379433 + 44 0.379433 0.675532 0.212482 + 45 0.228369 0.675532 0.407801 + 46 0.407801 0.675532 0.228369 + 47 0.238298 0.638298 0.425532 + 48 0.425532 0.638298 0.238298 + 49 0.496454 0.489362 0 + 50 0.496454 0.489362 -0.278014 + 51 0.278014 0.489362 -0.496454 + 52 0 0.489362 -0.496454 + 53 0.567376 0.340426 0 + 54 0.567376 0.340426 -0.31773 + 55 0.31773 0.340426 -0.567376 + 56 0 0.340426 -0.567376 + 57 0.567376 0.212766 0 + 58 0.567376 0.212766 -0.31773 + 59 0.31773 0.212766 -0.567376 + 60 0 0.212766 -0.567376 + 61 -0.278014 0.489362 -0.496454 + 62 -0.496454 0.489362 -0.278014 + 63 -0.496454 0.489362 0 + 64 -0.31773 0.340426 -0.567376 + 65 -0.567376 0.340426 -0.31773 + 66 -0.567376 0.340426 0 + 67 -0.31773 0.212766 -0.567376 + 68 -0.567376 0.212766 -0.31773 + 69 -0.567376 0.212766 0 + 70 -0.496454 0.489362 0.278014 + 71 -0.278014 0.489362 0.496454 + 72 0 0.489362 0.496454 + 73 -0.567376 0.340426 0.31773 + 74 -0.31773 0.340426 0.567376 + 75 0 0.340426 0.567376 + 76 -0.567376 0.212766 0.31773 + 77 -0.31773 0.212766 0.567376 + 78 0 0.212766 0.567376 + 79 0.278014 0.489362 0.496454 + 80 0.496454 0.489362 0.278014 + 81 0.31773 0.340426 0.567376 + 82 0.567376 0.340426 0.31773 + 83 0.31773 0.212766 0.567376 + 84 0.567376 0.212766 0.31773 + 85 0.567376 0.0851064 0 + 86 0.567376 0.0851064 -0.31773 + 87 0.31773 0.0851064 -0.567376 + 88 0 0.0851064 -0.567376 + 89 0.425532 0.0212766 0 + 90 0.425532 0.0212766 -0.238298 + 91 0.238298 0.0212766 -0.425532 + 92 0 0.0212766 -0.425532 + 93 0.425532 0 0 + 94 0.425532 0 -0.238298 + 95 0.238298 0 -0.425532 + 96 0 0 -0.425532 + 97 -0.31773 0.0851064 -0.567376 + 98 -0.567376 0.0851064 -0.31773 + 99 -0.567376 0.0851064 0 + 100 -0.238298 0.0212766 -0.425532 + 101 -0.425532 0.0212766 -0.238298 + 102 -0.425532 0.0212766 0 + 103 -0.238298 0 -0.425532 + 104 -0.425532 0 -0.238298 + 105 -0.425532 0 0 + 106 -0.567376 0.0851064 0.31773 + 107 -0.31773 0.0851064 0.567376 + 108 0 0.0851064 0.567376 + 109 -0.425532 0.0212766 0.238298 + 110 -0.238298 0.0212766 0.425532 + 111 0 0.0212766 0.425532 + 112 -0.425532 0 0.238298 + 113 -0.238298 0 0.425532 + 114 0 0 0.425532 + 115 0.31773 0.0851064 0.567376 + 116 0.567376 0.0851064 0.31773 + 117 0.238298 0.0212766 0.425532 + 118 0.425532 0.0212766 0.238298 + 119 0.238298 0 0.425532 + 120 0.425532 0 0.238298 + 121 -0.453901 0.531915 0 + 122 -0.453901 0.531915 -0.0851064 + 123 -0.425532 0.595745 -0.0851064 + 124 -0.425532 0.595745 0 + 125 -0.652482 0.531915 0 + 126 -0.652482 0.531915 -0.0851064 + 127 -0.70922 0.595745 -0.0851064 + 128 -0.70922 0.595745 0 + 129 -0.765957 0.531915 0 + 130 -0.765957 0.531915 -0.0851064 + 131 -0.851064 0.595745 -0.0851064 + 132 -0.851064 0.595745 0 + 133 -0.765957 0.468085 0 + 134 -0.765957 0.468085 -0.0851064 + 135 -0.851064 0.468085 -0.0851064 + 136 -0.851064 0.468085 0 + 137 -0.425532 0.595745 0.0851064 + 138 -0.453901 0.531915 0.0851064 + 139 -0.70922 0.595745 0.0851064 + 140 -0.652482 0.531915 0.0851064 + 141 -0.851064 0.595745 0.0851064 + 142 -0.765957 0.531915 0.0851064 + 143 -0.851064 0.468085 0.0851064 + 144 -0.765957 0.468085 0.0851064 + 145 -0.765957 0.404255 0 + 146 -0.765957 0.404255 -0.0851064 + 147 -0.851064 0.340426 -0.0851064 + 148 -0.851064 0.340426 0 + 149 -0.70922 0.276596 0 + 150 -0.70922 0.276596 -0.0851064 + 151 -0.751773 0.223404 -0.0851064 + 152 -0.751773 0.223404 0 + 153 -0.567376 0.212766 -0.0851064 + 154 -0.539007 0.12766 -0.0851064 + 155 -0.539007 0.12766 0 + 156 -0.851064 0.340426 0.0851064 + 157 -0.765957 0.404255 0.0851064 + 158 -0.751773 0.223404 0.0851064 + 159 -0.70922 0.276596 0.0851064 + 160 -0.539007 0.12766 0.0851064 + 161 -0.567376 0.212766 0.0851064 + 162 0.482269 0.361702 0 + 163 0.482269 0.361702 -0.187234 + 164 0.482269 0.12766 -0.187234 + 165 0.482269 0.12766 0 + 166 0.737589 0.361702 0 + 167 0.737589 0.361702 -0.187234 + 168 0.879433 0.191489 -0.187234 + 169 0.879433 0.191489 0 + 170 0.652482 0.553191 0 + 171 0.652482 0.553191 -0.070922 + 172 0.680851 0.531915 -0.070922 + 173 0.680851 0.531915 0 + 174 0.765957 0.638298 0 + 175 0.765957 0.638298 -0.070922 + 176 0.93617 0.638298 -0.070922 + 177 0.93617 0.638298 0 + 178 0.482269 0.12766 0.187234 + 179 0.482269 0.361702 0.187234 + 180 0.879433 0.191489 0.187234 + 181 0.737589 0.361702 0.187234 + 182 0.680851 0.531915 0.070922 + 183 0.652482 0.553191 0.070922 + 184 0.93617 0.638298 0.070922 + 185 0.765957 0.638298 0.070922 + 186 0.794326 0.659574 0 + 187 0.794326 0.659574 -0.070922 + 188 1 0.664894 -0.070922 + 189 1 0.664894 0 + 190 0.822695 0.659574 0 + 191 0.822695 0.659574 -0.0425532 + 192 0.978723 0.670213 -0.0425532 + 193 0.978723 0.670213 0 + 194 0.794326 0.638298 0 + 195 0.794326 0.638298 -0.0425532 + 196 0.907801 0.638298 -0.0425532 + 197 0.907801 0.638298 0 + 198 1 0.664894 0.070922 + 199 0.794326 0.659574 0.070922 + 200 0.978723 0.670213 0.0425532 + 201 0.822695 0.659574 0.0425532 + 202 0.907801 0.638298 0.0425532 + 203 0.794326 0.638298 0.0425532 + 204 0 0.851064 0 + 205 0 0.851064 -0.000567376 + 206 0.000567376 0.851064 0 + 207 0.22695 0.851064 0 + 208 0.22695 0.851064 -0.12766 + 209 0.12766 0.851064 -0.22695 + 210 0 0.851064 -0.22695 + 211 0 0.765957 0 + 212 0.0567376 0.723404 0 + 213 0.0567376 0.723404 -0.031773 + 214 0.031773 0.723404 -0.0567376 + 215 0 0.723404 -0.0567376 + 216 -0.000567376 0.851064 0 + 217 -0.12766 0.851064 -0.22695 + 218 -0.22695 0.851064 -0.12766 + 219 -0.22695 0.851064 0 + 220 -0.031773 0.723404 -0.0567376 + 221 -0.0567376 0.723404 -0.031773 + 222 -0.0567376 0.723404 0 + 223 0 0.851064 0.000567376 + 224 -0.22695 0.851064 0.12766 + 225 -0.12766 0.851064 0.22695 + 226 0 0.851064 0.22695 + 227 -0.0567376 0.723404 0.031773 + 228 -0.031773 0.723404 0.0567376 + 229 0 0.723404 0.0567376 + 230 0.12766 0.851064 0.22695 + 231 0.22695 0.851064 0.12766 + 232 0.031773 0.723404 0.0567376 + 233 0.0567376 0.723404 0.031773 + 234 0.113475 0.680851 0 + 235 0.113475 0.680851 -0.0635461 + 236 0.0635461 0.680851 -0.113475 + 237 0 0.680851 -0.113475 + 238 0.368794 0.680851 0 + 239 0.368794 0.680851 -0.206525 + 240 0.206525 0.680851 -0.368794 + 241 0 0.680851 -0.368794 + 242 0.368794 0.638298 0 + 243 0.368794 0.638298 -0.206525 + 244 0.206525 0.638298 -0.368794 + 245 0 0.638298 -0.368794 + 246 -0.0635461 0.680851 -0.113475 + 247 -0.113475 0.680851 -0.0635461 + 248 -0.113475 0.680851 0 + 249 -0.206525 0.680851 -0.368794 + 250 -0.368794 0.680851 -0.206525 + 251 -0.368794 0.680851 0 + 252 -0.206525 0.638298 -0.368794 + 253 -0.368794 0.638298 -0.206525 + 254 -0.368794 0.638298 0 + 255 -0.113475 0.680851 0.0635461 + 256 -0.0635461 0.680851 0.113475 + 257 0 0.680851 0.113475 + 258 -0.368794 0.680851 0.206525 + 259 -0.206525 0.680851 0.368794 + 260 0 0.680851 0.368794 + 261 -0.368794 0.638298 0.206525 + 262 -0.206525 0.638298 0.368794 + 263 0 0.638298 0.368794 + 264 0.0635461 0.680851 0.113475 + 265 0.113475 0.680851 0.0635461 + 266 0.206525 0.680851 0.368794 + 267 0.368794 0.680851 0.206525 + 268 0.206525 0.638298 0.368794 + 269 0.368794 0.638298 0.206525 + -1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + -4 17 18 19 8 20 21 22 12 23 24 25 16 26 27 28 + -19 29 30 31 22 32 33 34 25 35 36 37 28 38 39 40 + -31 41 42 1 34 43 44 5 37 45 46 9 40 47 48 13 + -13 14 15 16 49 50 51 52 53 54 55 56 57 58 59 60 + -16 26 27 28 52 61 62 63 56 64 65 66 60 67 68 69 + -28 38 39 40 63 70 71 72 66 73 74 75 69 76 77 78 + -40 47 48 13 72 79 80 49 75 81 82 53 78 83 84 57 + -57 58 59 60 85 86 87 88 89 90 91 92 93 94 95 96 + -60 67 68 69 88 97 98 99 92 100 101 102 96 103 104 105 + -69 76 77 78 99 106 107 108 102 109 110 111 105 112 113 114 + -78 83 84 57 108 115 116 85 111 117 118 89 114 119 120 93 + -121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 + -124 137 138 121 128 139 140 125 132 141 142 129 136 143 144 133 + -133 134 135 136 145 146 147 148 149 150 151 152 69 153 154 155 + -136 143 144 133 148 156 157 145 152 158 159 149 155 160 161 69 + -162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 + -165 178 179 162 169 180 181 166 173 182 183 170 177 184 185 174 + -174 175 176 177 186 187 188 189 190 191 192 193 194 195 196 197 + -177 184 185 174 189 198 199 186 193 200 201 190 197 202 203 194 + -204 205 206 204 207 208 209 210 211 211 211 211 212 213 214 215 + -204 216 205 204 210 217 218 219 211 211 211 211 215 220 221 222 + -204 223 216 204 219 224 225 226 211 211 211 211 222 227 228 229 + -204 206 223 204 226 230 231 207 211 211 211 211 229 232 233 212 + -212 213 214 215 234 235 236 237 238 239 240 241 242 243 244 245 + -215 220 221 222 237 246 247 248 241 249 250 251 245 252 253 254 + -222 227 228 229 248 255 256 257 251 258 259 260 254 261 262 263 + -229 232 233 212 257 264 265 234 260 266 267 238 263 268 269 242 + + + XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + + Martin Newell's Teacup + 251 2 26 14 + 1 0.409091 0.772727 0 + 2 0.409091 0.772727 -0.229091 + 3 0.229091 0.772727 -0.409091 + 4 0 0.772727 -0.409091 + 5 0.409091 0.886364 0 + 6 0.409091 0.886364 -0.229091 + 7 0.229091 0.886364 -0.409091 + 8 0 0.886364 -0.409091 + 9 0.454545 0.886364 0 + 10 0.454545 0.886364 -0.254545 + 11 0.254545 0.886364 -0.454545 + 12 0 0.886364 -0.454545 + 13 0.454545 0.772727 0 + 14 0.454545 0.772727 -0.254545 + 15 0.254545 0.772727 -0.454545 + 16 0 0.772727 -0.454545 + 17 -0.229091 0.772727 -0.409091 + 18 -0.409091 0.772727 -0.229091 + 19 -0.409091 0.772727 0 + 20 -0.229091 0.886364 -0.409091 + 21 -0.409091 0.886364 -0.229091 + 22 -0.409091 0.886364 0 + 23 -0.254545 0.886364 -0.454545 + 24 -0.454545 0.886364 -0.254545 + 25 -0.454545 0.886364 0 + 26 -0.254545 0.772727 -0.454545 + 27 -0.454545 0.772727 -0.254545 + 28 -0.454545 0.772727 0 + 29 -0.409091 0.772727 0.229091 + 30 -0.229091 0.772727 0.409091 + 31 0 0.772727 0.409091 + 32 -0.409091 0.886364 0.229091 + 33 -0.229091 0.886364 0.409091 + 34 0 0.886364 0.409091 + 35 -0.454545 0.886364 0.254545 + 36 -0.254545 0.886364 0.454545 + 37 0 0.886364 0.454545 + 38 -0.454545 0.772727 0.254545 + 39 -0.254545 0.772727 0.454545 + 40 0 0.772727 0.454545 + 41 0.229091 0.772727 0.409091 + 42 0.409091 0.772727 0.229091 + 43 0.229091 0.886364 0.409091 + 44 0.409091 0.886364 0.229091 + 45 0.254545 0.886364 0.454545 + 46 0.454545 0.886364 0.254545 + 47 0.254545 0.772727 0.454545 + 48 0.454545 0.772727 0.254545 + 49 0.454545 0.545455 0 + 50 0.454545 0.545455 -0.254545 + 51 0.254545 0.545455 -0.454545 + 52 0 0.545455 -0.454545 + 53 0.454545 0.272727 0 + 54 0.454545 0.272727 -0.254545 + 55 0.254545 0.272727 -0.454545 + 56 0 0.272727 -0.454545 + 57 0.318182 0.0454545 0 + 58 0.318182 0.0454545 -0.178182 + 59 0.178182 0.0454545 -0.318182 + 60 0 0.0454545 -0.318182 + 61 -0.254545 0.545455 -0.454545 + 62 -0.454545 0.545455 -0.254545 + 63 -0.454545 0.545455 0 + 64 -0.254545 0.272727 -0.454545 + 65 -0.454545 0.272727 -0.254545 + 66 -0.454545 0.272727 0 + 67 -0.178182 0.0454545 -0.318182 + 68 -0.318182 0.0454545 -0.178182 + 69 -0.318182 0.0454545 0 + 70 -0.454545 0.545455 0.254545 + 71 -0.254545 0.545455 0.454545 + 72 0 0.545455 0.454545 + 73 -0.454545 0.272727 0.254545 + 74 -0.254545 0.272727 0.454545 + 75 0 0.272727 0.454545 + 76 -0.318182 0.0454545 0.178182 + 77 -0.178182 0.0454545 0.318182 + 78 0 0.0454545 0.318182 + 79 0.254545 0.545455 0.454545 + 80 0.454545 0.545455 0.254545 + 81 0.254545 0.272727 0.454545 + 82 0.454545 0.272727 0.254545 + 83 0.178182 0.0454545 0.318182 + 84 0.318182 0.0454545 0.178182 + 85 0.545455 0.0454545 0 + 86 0.545455 0.0454545 -0.305455 + 87 0.305455 0.0454545 -0.545455 + 88 0 0.0454545 -0.545455 + 89 0.727273 0.136364 0 + 90 0.727273 0.136364 -0.407273 + 91 0.407273 0.136364 -0.727273 + 92 0 0.136364 -0.727273 + 93 0.909091 0.136364 0 + 94 0.909091 0.136364 -0.509091 + 95 0.509091 0.136364 -0.909091 + 96 0 0.136364 -0.909091 + 97 -0.305455 0.0454545 -0.545455 + 98 -0.545455 0.0454545 -0.305455 + 99 -0.545455 0.0454545 0 + 100 -0.407273 0.136364 -0.727273 + 101 -0.727273 0.136364 -0.407273 + 102 -0.727273 0.136364 0 + 103 -0.509091 0.136364 -0.909091 + 104 -0.909091 0.136364 -0.509091 + 105 -0.909091 0.136364 0 + 106 -0.545455 0.0454545 0.305455 + 107 -0.305455 0.0454545 0.545455 + 108 0 0.0454545 0.545455 + 109 -0.727273 0.136364 0.407273 + 110 -0.407273 0.136364 0.727273 + 111 0 0.136364 0.727273 + 112 -0.909091 0.136364 0.509091 + 113 -0.509091 0.136364 0.909091 + 114 0 0.136364 0.909091 + 115 0.305455 0.0454545 0.545455 + 116 0.545455 0.0454545 0.305455 + 117 0.407273 0.136364 0.727273 + 118 0.727273 0.136364 0.407273 + 119 0.509091 0.136364 0.909091 + 120 0.909091 0.136364 0.509091 + 121 1 0.136364 0 + 122 1 0.136364 -0.56 + 123 0.56 0.136364 -1 + 124 0 0.136364 -1 + 125 1 0.0909091 0 + 126 1 0.0909091 -0.56 + 127 0.56 0.0909091 -1 + 128 0 0.0909091 -1 + 129 0.909091 0.0909091 0 + 130 0.909091 0.0909091 -0.509091 + 131 0.509091 0.0909091 -0.909091 + 132 0 0.0909091 -0.909091 + 133 -0.56 0.136364 -1 + 134 -1 0.136364 -0.56 + 135 -1 0.136364 0 + 136 -0.56 0.0909091 -1 + 137 -1 0.0909091 -0.56 + 138 -1 0.0909091 0 + 139 -0.509091 0.0909091 -0.909091 + 140 -0.909091 0.0909091 -0.509091 + 141 -0.909091 0.0909091 0 + 142 -1 0.136364 0.56 + 143 -0.56 0.136364 1 + 144 0 0.136364 1 + 145 -1 0.0909091 0.56 + 146 -0.56 0.0909091 1 + 147 0 0.0909091 1 + 148 -0.909091 0.0909091 0.509091 + 149 -0.509091 0.0909091 0.909091 + 150 0 0.0909091 0.909091 + 151 0.56 0.136364 1 + 152 1 0.136364 0.56 + 153 0.56 0.0909091 1 + 154 1 0.0909091 0.56 + 155 0.509091 0.0909091 0.909091 + 156 0.909091 0.0909091 0.509091 + 157 0.727273 0.0909091 0 + 158 0.727273 0.0909091 -0.407273 + 159 0.407273 0.0909091 -0.727273 + 160 0 0.0909091 -0.727273 + 161 0.545455 0 0 + 162 0.545455 0 -0.305455 + 163 0.305455 0 -0.545455 + 164 0 0 -0.545455 + 165 0.318182 0 0 + 166 0.318182 0 -0.178182 + 167 0.178182 0 -0.318182 + 168 0 0 -0.318182 + 169 -0.407273 0.0909091 -0.727273 + 170 -0.727273 0.0909091 -0.407273 + 171 -0.727273 0.0909091 0 + 172 -0.305455 0 -0.545455 + 173 -0.545455 0 -0.305455 + 174 -0.545455 0 0 + 175 -0.178182 0 -0.318182 + 176 -0.318182 0 -0.178182 + 177 -0.318182 0 0 + 178 -0.727273 0.0909091 0.407273 + 179 -0.407273 0.0909091 0.727273 + 180 0 0.0909091 0.727273 + 181 -0.545455 0 0.305455 + 182 -0.305455 0 0.545455 + 183 0 0 0.545455 + 184 -0.318182 0 0.178182 + 185 -0.178182 0 0.318182 + 186 0 0 0.318182 + 187 0.407273 0.0909091 0.727273 + 188 0.727273 0.0909091 0.407273 + 189 0.305455 0 0.545455 + 190 0.545455 0 0.305455 + 191 0.178182 0 0.318182 + 192 0.318182 0 0.178182 + 193 0.272727 0.0454545 0 + 194 0.272727 0.0454545 -0.152727 + 195 0.152727 0.0454545 -0.272727 + 196 0 0.0454545 -0.272727 + 197 0.409091 0.272727 0 + 198 0.409091 0.272727 -0.229091 + 199 0.229091 0.272727 -0.409091 + 200 0 0.272727 -0.409091 + 201 0.409091 0.545455 0 + 202 0.409091 0.545455 -0.229091 + 203 0.229091 0.545455 -0.409091 + 204 0 0.545455 -0.409091 + 205 -0.152727 0.0454545 -0.272727 + 206 -0.272727 0.0454545 -0.152727 + 207 -0.272727 0.0454545 0 + 208 -0.229091 0.272727 -0.409091 + 209 -0.409091 0.272727 -0.229091 + 210 -0.409091 0.272727 0 + 211 -0.229091 0.545455 -0.409091 + 212 -0.409091 0.545455 -0.229091 + 213 -0.409091 0.545455 0 + 214 -0.272727 0.0454545 0.152727 + 215 -0.152727 0.0454545 0.272727 + 216 0 0.0454545 0.272727 + 217 -0.409091 0.272727 0.229091 + 218 -0.229091 0.272727 0.409091 + 219 0 0.272727 0.409091 + 220 -0.409091 0.545455 0.229091 + 221 -0.229091 0.545455 0.409091 + 222 0 0.545455 0.409091 + 223 0.152727 0.0454545 0.272727 + 224 0.272727 0.0454545 0.152727 + 225 0.229091 0.272727 0.409091 + 226 0.409091 0.272727 0.229091 + 227 0.229091 0.545455 0.409091 + 228 0.409091 0.545455 0.229091 + 229 -0.454545 0.704545 0 + 230 -0.454545 0.704545 -0.0454545 + 231 -0.454545 0.772727 -0.0454545 + 232 -0.772727 0.863636 0 + 233 -0.772727 0.863636 -0.0454545 + 234 -0.818182 0.954545 -0.0454545 + 235 -0.818182 0.954545 0 + 236 -0.772727 0.522727 0 + 237 -0.772727 0.522727 -0.0454545 + 238 -0.909091 0.477273 -0.0454545 + 239 -0.909091 0.477273 0 + 240 -0.409091 0.363636 0 + 241 -0.409091 0.363636 -0.0454545 + 242 -0.409091 0.295455 -0.0454545 + 243 -0.409091 0.295455 0 + 244 -0.454545 0.772727 0.0454545 + 245 -0.454545 0.704545 0.0454545 + 246 -0.818182 0.954545 0.0454545 + 247 -0.772727 0.863636 0.0454545 + 248 -0.909091 0.477273 0.0454545 + 249 -0.772727 0.522727 0.0454545 + 250 -0.409091 0.295455 0.0454545 + 251 -0.409091 0.363636 0.0454545 + -1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + -4 17 18 19 8 20 21 22 12 23 24 25 16 26 27 28 + -19 29 30 31 22 32 33 34 25 35 36 37 28 38 39 40 + -31 41 42 1 34 43 44 5 37 45 46 9 40 47 48 13 + -13 14 15 16 49 50 51 52 53 54 55 56 57 58 59 60 + -16 26 27 28 52 61 62 63 56 64 65 66 60 67 68 69 + -28 38 39 40 63 70 71 72 66 73 74 75 69 76 77 78 + -40 47 48 13 72 79 80 49 75 81 82 53 78 83 84 57 + -193 194 195 196 197 198 199 200 201 202 203 204 1 2 3 4 + -196 205 206 207 200 208 209 210 204 211 212 213 4 17 18 19 + -207 214 215 216 210 217 218 219 213 220 221 222 19 29 30 31 + -216 223 224 193 219 225 226 197 222 227 228 201 31 41 42 1 + -229 230 231 28 232 233 234 235 236 237 238 239 240 241 242 243 + -28 244 245 229 235 246 247 232 239 248 249 236 243 250 251 240 + -57 58 59 60 85 86 87 88 89 90 91 92 93 94 95 96 + -60 67 68 69 88 97 98 99 92 100 101 102 96 103 104 105 + -69 76 77 78 99 106 107 108 102 109 110 111 105 112 113 114 + -78 83 84 57 108 115 116 85 111 117 118 89 114 119 120 93 + -93 94 95 96 121 122 123 124 125 126 127 128 129 130 131 132 + -96 103 104 105 124 133 134 135 128 136 137 138 132 139 140 141 + -105 112 113 114 135 142 143 144 138 145 146 147 141 148 149 150 + -114 119 120 93 144 151 152 121 147 153 154 125 150 155 156 129 + -129 130 131 132 157 158 159 160 161 162 163 164 165 166 167 168 + -132 139 140 141 160 169 170 171 164 172 173 174 168 175 176 177 + -141 148 149 150 171 178 179 180 174 181 182 183 177 184 185 186 + -150 155 156 129 180 187 188 157 183 189 190 161 186 191 192 165 + + + + XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + + Martin Newell's Teaspoon (bezier patches) + 256 1 16 16 + 1 -0.000107143 0.205357 0 + 2 0 0.196429 -0.0178571 + 3 0 0.196429 -0.0178571 + 4 0.000107143 0.205357 0 + 5 -0.0535714 0.205357 0 + 6 -0.0222714 0.178571 -0.0534286 + 7 0.0222714 0.178571 -0.0534286 + 8 0.0535714 0.205357 0 + 9 -0.107143 0.0952429 -0.0178571 + 10 -0.0446429 0.0952429 -0.0892857 + 11 0.0446429 0.0952429 -0.0892857 + 12 0.107143 0.0952429 -0.0178571 + 13 -0.107143 0 -0.0178571 + 14 -0.0446429 0 -0.0892857 + 15 0.0446429 0 -0.0892857 + 16 0.107143 0 -0.0178571 + 17 0.000107143 0.205357 0 + 18 0.000135714 0.207589 0.00446429 + 19 0.000157143 0.216518 0.00446429 + 20 0.000125 0.214286 0 + 21 0.0535714 0.205357 0 + 22 0.0613964 0.212054 0.0133571 + 23 0.0714286 0.220982 0.015625 + 24 0.0625 0.214286 0 + 25 0.107143 0.0952429 -0.0178571 + 26 0.122768 0.0952429 0 + 27 0.142857 0.0952429 0.00446429 + 28 0.125 0.0952429 -0.0178571 + 29 0.107143 0 -0.0178571 + 30 0.122768 0 0 + 31 0.142857 0 0.00446429 + 32 0.125 0 -0.0178571 + 33 0.000125 0.214286 0 + 34 0 0.205357 -0.0178571 + 35 0 0.205357 -0.0178571 + 36 -0.000125 0.214286 0 + 37 0.0625 0.214286 0 + 38 0.0267857 0.1875 -0.0625 + 39 -0.0267857 0.1875 -0.0625 + 40 -0.0625 0.214286 0 + 41 0.125 0.0952429 -0.0178571 + 42 0.0535714 0.0952429 -0.107143 + 43 -0.0535714 0.0952429 -0.107143 + 44 -0.125 0.0952429 -0.0178571 + 45 0.125 0 -0.0178571 + 46 0.0535714 0 -0.107143 + 47 -0.0535714 0 -0.107143 + 48 -0.125 0 -0.0178571 + 49 -0.000125 0.214286 0 + 50 -0.000157143 0.216518 0.00446429 + 51 -0.000135714 0.207589 0.00446429 + 52 -0.000107143 0.205357 0 + 53 -0.0625 0.214286 0 + 54 -0.0714286 0.220982 0.015625 + 55 -0.0613964 0.212054 0.0133571 + 56 -0.0535714 0.205357 0 + 57 -0.125 0.0952429 -0.0178571 + 58 -0.142857 0.0952429 0.00446429 + 59 -0.122768 0.0952429 0 + 60 -0.107143 0.0952429 -0.0178571 + 61 -0.125 0 -0.0178571 + 62 -0.142857 0 0.00446429 + 63 -0.122768 0 0 + 64 -0.107143 0 -0.0178571 + 65 -0.107143 0 -0.0178571 + 66 -0.0446429 0 -0.0892857 + 67 0.0446429 0 -0.0892857 + 68 0.107143 0 -0.0178571 + 69 -0.107143 -0.142857 -0.0178571 + 70 -0.0446429 -0.142857 -0.0892857 + 71 0.0446429 -0.142857 -0.0892857 + 72 0.107143 -0.142857 -0.0178571 + 73 -0.0133929 -0.160714 0.0386893 + 74 -0.00557857 -0.160714 0.0386893 + 75 0.00557857 -0.160714 0.0386893 + 76 0.0133929 -0.160714 0.0386893 + 77 -0.0133929 -0.25 0.0535714 + 78 -0.00557857 -0.25 0.0535714 + 79 0.00557857 -0.25 0.0535714 + 80 0.0133929 -0.25 0.0535714 + 81 0.107143 0 -0.0178571 + 82 0.122768 0 0 + 83 0.142857 0 0.00446429 + 84 0.125 0 -0.0178571 + 85 0.107143 -0.142857 -0.0178571 + 86 0.122768 -0.142857 0 + 87 0.142857 -0.142857 0.00446429 + 88 0.125 -0.142857 -0.0178571 + 89 0.0133929 -0.160714 0.0386893 + 90 0.0153464 -0.160714 0.0386893 + 91 0.0178571 -0.160714 0.0314357 + 92 0.015625 -0.160714 0.0297607 + 93 0.0133929 -0.25 0.0535714 + 94 0.0153464 -0.25 0.0535714 + 95 0.0178571 -0.25 0.0463179 + 96 0.015625 -0.25 0.0446429 + 97 0.125 0 -0.0178571 + 98 0.0535714 0 -0.107143 + 99 -0.0535714 0 -0.107143 + 100 -0.125 0 -0.0178571 + 101 0.125 -0.142857 -0.0178571 + 102 0.0535714 -0.142857 -0.107143 + 103 -0.0535714 -0.142857 -0.107143 + 104 -0.125 -0.142857 -0.0178571 + 105 0.015625 -0.160714 0.0297607 + 106 0.00669643 -0.160714 0.0230643 + 107 -0.00781071 -0.160714 0.0208321 + 108 -0.015625 -0.160714 0.0297607 + 109 0.015625 -0.25 0.0446429 + 110 0.00669643 -0.25 0.0379464 + 111 -0.00781071 -0.25 0.0357143 + 112 -0.015625 -0.25 0.0446429 + 113 -0.125 0 -0.0178571 + 114 -0.142857 0 0.00446429 + 115 -0.122768 0 0 + 116 -0.107143 0 -0.0178571 + 117 -0.125 -0.142857 -0.0178571 + 118 -0.142857 -0.142857 0.00446429 + 119 -0.122768 -0.142857 0 + 120 -0.107143 -0.142857 -0.0178571 + 121 -0.015625 -0.160714 0.0297607 + 122 -0.0175786 -0.160714 0.0319929 + 123 -0.0153464 -0.160714 0.0386893 + 124 -0.0133929 -0.160714 0.0386893 + 125 -0.015625 -0.25 0.0446429 + 126 -0.0175786 -0.25 0.046875 + 127 -0.0153464 -0.25 0.0535714 + 128 -0.0133929 -0.25 0.0535714 + 129 -0.0133929 -0.25 0.0535714 + 130 -0.00557857 -0.25 0.0535714 + 131 0.00557857 -0.25 0.0535714 + 132 0.0133929 -0.25 0.0535714 + 133 -0.0133929 -0.46425 0.0892857 + 134 -0.00557857 -0.46425 0.0892857 + 135 0.00557857 -0.46425 0.0892857 + 136 0.0133929 -0.46425 0.0892857 + 137 -0.0446429 -0.678571 0.0535714 + 138 -0.00892857 -0.678571 0.0625 + 139 0.00892857 -0.678571 0.0625 + 140 0.0446429 -0.678571 0.0535714 + 141 -0.0446429 -0.857143 0.0357143 + 142 -0.00892857 -0.857143 0.0446429 + 143 0.00892857 -0.857143 0.0446429 + 144 0.0446429 -0.857143 0.0357143 + 145 0.0133929 -0.25 0.0535714 + 146 0.0153464 -0.25 0.0535714 + 147 0.0178571 -0.25 0.0463179 + 148 0.015625 -0.25 0.0446429 + 149 0.0133929 -0.46425 0.0892857 + 150 0.0153464 -0.464286 0.0892857 + 151 0.0178571 -0.46425 0.0820321 + 152 0.015625 -0.46425 0.0803571 + 153 0.0446429 -0.678571 0.0535714 + 154 0.0535714 -0.678571 0.0513393 + 155 0.0535714 -0.678571 0.0334821 + 156 0.0446429 -0.678571 0.0357143 + 157 0.0446429 -0.857143 0.0357143 + 158 0.0535714 -0.857143 0.0334821 + 159 0.0535714 -0.857143 0.015625 + 160 0.0446429 -0.857143 0.0178571 + 161 0.015625 -0.25 0.0446429 + 162 0.00669643 -0.25 0.0379464 + 163 -0.00781071 -0.25 0.0357143 + 164 -0.015625 -0.25 0.0446429 + 165 0.015625 -0.46425 0.0803571 + 166 0.00669643 -0.464286 0.0736607 + 167 -0.00781071 -0.46425 0.0714286 + 168 -0.015625 -0.46425 0.0803571 + 169 0.0446429 -0.678571 0.0357143 + 170 0.00892857 -0.678571 0.0446429 + 171 -0.00892857 -0.678571 0.0446429 + 172 -0.0446429 -0.678571 0.0357143 + 173 0.0446429 -0.857143 0.0178571 + 174 0.00892857 -0.857143 0.0267857 + 175 -0.00892857 -0.857143 0.0267857 + 176 -0.0446429 -0.857143 0.0178571 + 177 -0.015625 -0.25 0.0446429 + 178 -0.0175786 -0.25 0.046875 + 179 -0.0153464 -0.25 0.0535714 + 180 -0.0133929 -0.25 0.0535714 + 181 -0.015625 -0.46425 0.0803571 + 182 -0.0175786 -0.464286 0.0825893 + 183 -0.0153464 -0.464286 0.0892857 + 184 -0.0133929 -0.46425 0.0892857 + 185 -0.0446429 -0.678571 0.0357143 + 186 -0.0535714 -0.678571 0.0334821 + 187 -0.0535714 -0.678571 0.0513393 + 188 -0.0446429 -0.678571 0.0535714 + 189 -0.0446429 -0.857143 0.0178571 + 190 -0.0535714 -0.857143 0.015625 + 191 -0.0535714 -0.857143 0.0334821 + 192 -0.0446429 -0.857143 0.0357143 + 193 -0.0446429 -0.857143 0.0357143 + 194 -0.00892857 -0.857143 0.0446429 + 195 0.00892857 -0.857143 0.0446429 + 196 0.0446429 -0.857143 0.0357143 + 197 -0.0446429 -0.928571 0.0285714 + 198 -0.00892857 -0.928571 0.0375 + 199 0.00892857 -0.928571 0.0375 + 200 0.0446429 -0.928571 0.0285714 + 201 -0.0539286 -0.999643 0.0178571 + 202 0.000357143 -0.999643 0.0178571 + 203 0 -0.999643 0.0178571 + 204 0.0535714 -0.999643 0.0178571 + 205 -0.000357143 -1 0.0178571 + 206 0.000357143 -1 0.0178571 + 207 0 -1 0.0178571 + 208 0 -1 0.0178571 + 209 0.0446429 -0.857143 0.0357143 + 210 0.0535714 -0.857143 0.0334821 + 211 0.0535714 -0.857143 0.015625 + 212 0.0446429 -0.857143 0.0178571 + 213 0.0446429 -0.928571 0.0285714 + 214 0.0535714 -0.928571 0.0263393 + 215 0.0535714 -0.928571 0.00848214 + 216 0.0446429 -0.928571 0.0107143 + 217 0.0535714 -0.999643 0.0178571 + 218 0.0669643 -0.999643 0.0178571 + 219 0.0673214 -0.999643 0 + 220 0.0539286 -0.999643 0 + 221 0 -1 0.0178571 + 222 0 -1 0.0178571 + 223 0.000357143 -1 0 + 224 0.000357143 -1 0 + 225 0.0446429 -0.857143 0.0178571 + 226 0.00892857 -0.857143 0.0267857 + 227 -0.00892857 -0.857143 0.0267857 + 228 -0.0446429 -0.857143 0.0178571 + 229 0.0446429 -0.928571 0.0107143 + 230 0.00892857 -0.928571 0.0196429 + 231 -0.00892857 -0.928571 0.0196429 + 232 -0.0446429 -0.928571 0.0107143 + 233 0.0539286 -0.999643 0 + 234 0.000357143 -0.999643 0 + 235 -0.000357143 -0.999643 0 + 236 -0.0539286 -0.999643 0 + 237 0.000357143 -1 0 + 238 0.000357143 -1 0 + 239 -0.000357143 -1 0 + 240 -0.000357143 -1 0 + 241 -0.0446429 -0.857143 0.0178571 + 242 -0.0535714 -0.857143 0.015625 + 243 -0.0535714 -0.857143 0.0334821 + 244 -0.0446429 -0.857143 0.0357143 + 245 -0.0446429 -0.928571 0.0107143 + 246 -0.0535714 -0.928571 0.00848214 + 247 -0.0535714 -0.928571 0.0263393 + 248 -0.0446429 -0.928571 0.0285714 + 249 -0.0539286 -0.999643 0 + 250 -0.0673214 -0.999643 0 + 251 -0.0675 -0.999643 0.0178571 + 252 -0.0539286 -0.999643 0.0178571 + 253 -0.000357143 -1 0 + 254 -0.000357143 -1 0 + 255 -0.000535714 -1 0.0178571 + 256 -0.000357143 -1 0.0178571 + -1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + -17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 + -33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 + -49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 + -65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 + -81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 + -97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 + -113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 + -129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 + -145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 + -161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 + -177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 + -193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 + -209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 + -225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 + -241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 + + + XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + + + Jim Blinn's doughnout (used in III table top scene) bezier patches + [snip] + + */ + +#ifndef FREEGLUT_TEAPOT_DATA_H +#define FREEGLUT_TEAPOT_DATA_H + +/* + * Rim, body, lid, and bottom data must be rotated along all four quadrants; + * handle and spout data is flipped across the x-y plane (negate z values) only. + */ +#define GLUT_TEAPOT_N_INPUT_PATCHES 10 +static int patchdata_teapot[GLUT_TEAPOT_N_INPUT_PATCHES][16] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, }, /* rim */ + { 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, }, /* body */ + { 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, }, + { 40, 41, 42, 40, 43, 44, 45, 46, 47, 47, 47, 47, 48, 49, 50, 51, }, /* lid */ + { 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, }, + { 64, 64, 64, 64, 65, 66, 67, 68, 69, 70, 71, 72, 39, 38, 37, 36, }, /* bottom */ + { 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, }, /* handle */ + { 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, }, + {101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, }, /* spout */ + {113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128 } +}; + +static GLfloat cpdata_teapot[][3] = +{ + { 1.40000f, 0.00000f, 2.40000f}, { 1.40000f, -0.78400f, 2.40000f}, + { 0.78400f, -1.40000f, 2.40000f}, { 0.00000f, -1.40000f, 2.40000f}, + { 1.33750f, 0.00000f, 2.53125f}, { 1.33750f, -0.74900f, 2.53125f}, + { 0.74900f, -1.33750f, 2.53125f}, { 0.00000f, -1.33750f, 2.53125f}, + { 1.43750f, 0.00000f, 2.53125f}, { 1.43750f, -0.80500f, 2.53125f}, + { 0.80500f, -1.43750f, 2.53125f}, { 0.00000f, -1.43750f, 2.53125f}, + { 1.50000f, 0.00000f, 2.40000f}, { 1.50000f, -0.84000f, 2.40000f}, + { 0.84000f, -1.50000f, 2.40000f}, { 0.00000f, -1.50000f, 2.40000f}, + { 1.75000f, 0.00000f, 1.87500f}, { 1.75000f, -0.98000f, 1.87500f}, + { 0.98000f, -1.75000f, 1.87500f}, { 0.00000f, -1.75000f, 1.87500f}, + { 2.00000f, 0.00000f, 1.35000f}, { 2.00000f, -1.12000f, 1.35000f}, + { 1.12000f, -2.00000f, 1.35000f}, { 0.00000f, -2.00000f, 1.35000f}, + { 2.00000f, 0.00000f, 0.90000f}, { 2.00000f, -1.12000f, 0.90000f}, + { 1.12000f, -2.00000f, 0.90000f}, { 0.00000f, -2.00000f, 0.90000f}, + { 2.00000f, 0.00000f, 0.45000f}, { 2.00000f, -1.12000f, 0.45000f}, + { 1.12000f, -2.00000f, 0.45000f}, { 0.00000f, -2.00000f, 0.45000f}, + { 1.50000f, 0.00000f, 0.22500f}, { 1.50000f, -0.84000f, 0.22500f}, + { 0.84000f, -1.50000f, 0.22500f}, { 0.00000f, -1.50000f, 0.22500f}, + { 1.50000f, 0.00000f, 0.15000f}, { 1.50000f, -0.84000f, 0.15000f}, + { 0.84000f, -1.50000f, 0.15000f}, { 0.00000f, -1.50000f, 0.15000f}, + { 0.00000f, 0.00000f, 3.15000f}, { 0.00000f, -0.00200f, 3.15000f}, + { 0.00200f, 0.00000f, 3.15000f}, { 0.80000f, 0.00000f, 3.15000f}, + { 0.80000f, -0.45000f, 3.15000f}, { 0.45000f, -0.80000f, 3.15000f}, + { 0.00000f, -0.80000f, 3.15000f}, { 0.00000f, 0.00000f, 2.85000f}, + { 0.20000f, 0.00000f, 2.70000f}, { 0.20000f, -0.11200f, 2.70000f}, + { 0.11200f, -0.20000f, 2.70000f}, { 0.00000f, -0.20000f, 2.70000f}, + { 0.40000f, 0.00000f, 2.55000f}, { 0.40000f, -0.22400f, 2.55000f}, + { 0.22400f, -0.40000f, 2.55000f}, { 0.00000f, -0.40000f, 2.55000f}, + { 1.30000f, 0.00000f, 2.55000f}, { 1.30000f, -0.72800f, 2.55000f}, + { 0.72800f, -1.30000f, 2.55000f}, { 0.00000f, -1.30000f, 2.55000f}, + { 1.30000f, 0.00000f, 2.40000f}, { 1.30000f, -0.72800f, 2.40000f}, + { 0.72800f, -1.30000f, 2.40000f}, { 0.00000f, -1.30000f, 2.40000f}, + { 0.00000f, 0.00000f, 0.00000f}, { 0.00000f, -1.42500f, 0.00000f}, + { 0.79800f, -1.42500f, 0.00000f}, { 1.42500f, -0.79800f, 0.00000f}, + { 1.42500f, 0.00000f, 0.00000f}, { 0.00000f, -1.50000f, 0.07500f}, + { 0.84000f, -1.50000f, 0.07500f}, { 1.50000f, -0.84000f, 0.07500f}, + { 1.50000f, 0.00000f, 0.07500f}, {-1.60000f, 0.00000f, 2.02500f}, + {-1.60000f, -0.30000f, 2.02500f}, {-1.50000f, -0.30000f, 2.25000f}, + {-1.50000f, 0.00000f, 2.25000f}, {-2.30000f, 0.00000f, 2.02500f}, + {-2.30000f, -0.30000f, 2.02500f}, {-2.50000f, -0.30000f, 2.25000f}, + {-2.50000f, 0.00000f, 2.25000f}, {-2.70000f, 0.00000f, 2.02500f}, + {-2.70000f, -0.30000f, 2.02500f}, {-3.00000f, -0.30000f, 2.25000f}, + {-3.00000f, 0.00000f, 2.25000f}, {-2.70000f, 0.00000f, 1.80000f}, + {-2.70000f, -0.30000f, 1.80000f}, {-3.00000f, -0.30000f, 1.80000f}, + {-3.00000f, 0.00000f, 1.80000f}, {-2.70000f, 0.00000f, 1.57500f}, + {-2.70000f, -0.30000f, 1.57500f}, {-3.00000f, -0.30000f, 1.35000f}, + {-3.00000f, 0.00000f, 1.35000f}, {-2.50000f, 0.00000f, 1.12500f}, + {-2.50000f, -0.30000f, 1.12500f}, {-2.65000f, -0.30000f, 0.93750f}, + {-2.65000f, 0.00000f, 0.93750f}, {-2.00000f, 0.00000f, 0.90000f}, + {-2.00000f, -0.30000f, 0.90000f}, {-1.90000f, -0.30000f, 0.60000f}, + {-1.90000f, 0.00000f, 0.60000f}, { 1.70000f, 0.00000f, 1.42500f}, + { 1.70000f, -0.66000f, 1.42500f}, { 1.70000f, -0.66000f, 0.60000f}, + { 1.70000f, 0.00000f, 0.60000f}, { 2.60000f, 0.00000f, 1.42500f}, + { 2.60000f, -0.66000f, 1.42500f}, { 3.10000f, -0.66000f, 0.82500f}, + { 3.10000f, 0.00000f, 0.82500f}, { 2.30000f, 0.00000f, 2.10000f}, + { 2.30000f, -0.25000f, 2.10000f}, { 2.40000f, -0.25000f, 2.02500f}, + { 2.40000f, 0.00000f, 2.02500f}, { 2.70000f, 0.00000f, 2.40000f}, + { 2.70000f, -0.25000f, 2.40000f}, { 3.30000f, -0.25000f, 2.40000f}, + { 3.30000f, 0.00000f, 2.40000f}, { 2.80000f, 0.00000f, 2.47500f}, + { 2.80000f, -0.25000f, 2.47500f}, { 3.52500f, -0.25000f, 2.49375f}, + { 3.52500f, 0.00000f, 2.49375f}, { 2.90000f, 0.00000f, 2.47500f}, + { 2.90000f, -0.15000f, 2.47500f}, { 3.45000f, -0.15000f, 2.51250f}, + { 3.45000f, 0.00000f, 2.51250f}, { 2.80000f, 0.00000f, 2.40000f}, + { 2.80000f, -0.15000f, 2.40000f}, { 3.20000f, -0.15000f, 2.40000f}, + { 3.20000f, 0.00000f, 2.40000f} +}; + +#define GLUT_TEACUP_N_INPUT_PATCHES 7 +static int patchdata_teacup[GLUT_TEACUP_N_INPUT_PATCHES][16] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, }, /* like teapot, first 6 are rotated along all four quadrants */ + { 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, }, + { 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 0, 1, 2, 3, }, + { 24, 25, 26, 27, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, }, + { 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, }, + { 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, }, + { 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91 } /* this one is flipped once */ +}; + +static GLfloat cpdata_teacup[][3] = +{ + { 1.44205f, 0.00000f, 2.72386f}, { 1.44205f, -0.80755f, 2.72386f}, + { 0.80755f, -1.44205f, 2.72386f}, { 0.00000f, -1.44205f, 2.72386f}, + { 1.44205f, 0.00000f, 3.12443f}, { 1.44205f, -0.80755f, 3.12443f}, + { 0.80755f, -1.44205f, 3.12443f}, { 0.00000f, -1.44205f, 3.12443f}, + { 1.60227f, 0.00000f, 3.12443f}, { 1.60227f, -0.89727f, 3.12443f}, + { 0.89727f, -1.60227f, 3.12443f}, { 0.00000f, -1.60227f, 3.12443f}, + { 1.60227f, 0.00000f, 2.72386f}, { 1.60227f, -0.89727f, 2.72386f}, + { 0.89727f, -1.60227f, 2.72386f}, { 0.00000f, -1.60227f, 2.72386f}, + { 1.60227f, 0.00000f, 1.92273f}, { 1.60227f, -0.89727f, 1.92273f}, + { 0.89727f, -1.60227f, 1.92273f}, { 0.00000f, -1.60227f, 1.92273f}, + { 1.60227f, 0.00000f, 0.96136f}, { 1.60227f, -0.89727f, 0.96136f}, + { 0.89727f, -1.60227f, 0.96136f}, { 0.00000f, -1.60227f, 0.96136f}, + { 1.12159f, 0.00000f, 0.16023f}, { 1.12159f, -0.62809f, 0.16023f}, + { 0.62809f, -1.12159f, 0.16023f}, { 0.00000f, -1.12159f, 0.16023f}, + { 0.96136f, 0.00000f, 0.16023f}, { 0.96136f, -0.53836f, 0.16023f}, + { 0.53836f, -0.96136f, 0.16023f}, { 0.00000f, -0.96136f, 0.16023f}, + { 1.44205f, 0.00000f, 0.96136f}, { 1.44205f, -0.80755f, 0.96136f}, + { 0.80755f, -1.44205f, 0.96136f}, { 0.00000f, -1.44205f, 0.96136f}, + { 1.44205f, 0.00000f, 1.92273f}, { 1.44205f, -0.80755f, 1.92273f}, + { 0.80755f, -1.44205f, 1.92273f}, { 0.00000f, -1.44205f, 1.92273f}, + { 1.92273f, 0.00000f, 0.16023f}, { 1.92273f, -1.07673f, 0.16023f}, + { 1.07673f, -1.92273f, 0.16023f}, { 0.00000f, -1.92273f, 0.16023f}, + { 2.56364f, 0.00000f, 0.48068f}, { 2.56364f, -1.43564f, 0.48068f}, + { 1.43564f, -2.56364f, 0.48068f}, { 0.00000f, -2.56364f, 0.48068f}, + { 3.20455f, 0.00000f, 0.48068f}, { 3.20455f, -1.79455f, 0.48068f}, + { 1.79455f, -3.20455f, 0.48068f}, { 0.00000f, -3.20455f, 0.48068f}, + { 3.52500f, 0.00000f, 0.48068f}, { 3.52500f, -1.97400f, 0.48068f}, + { 1.97400f, -3.52500f, 0.48068f}, { 0.00000f, -3.52500f, 0.48068f}, + { 3.52500f, 0.00000f, 0.32045f}, { 3.52500f, -1.97400f, 0.32045f}, + { 1.97400f, -3.52500f, 0.32045f}, { 0.00000f, -3.52500f, 0.32045f}, + { 3.20455f, 0.00000f, 0.32045f}, { 3.20455f, -1.79455f, 0.32045f}, + { 1.79455f, -3.20455f, 0.32045f}, { 0.00000f, -3.20455f, 0.32045f}, + { 2.56364f, 0.00000f, 0.32045f}, { 2.56364f, -1.43564f, 0.32045f}, + { 1.43564f, -2.56364f, 0.32045f}, { 0.00000f, -2.56364f, 0.32045f}, + { 1.92273f, 0.00000f, 0.00000f}, { 1.92273f, -1.07673f, 0.00000f}, + { 1.07673f, -1.92273f, 0.00000f}, { 0.00000f, -1.92273f, 0.00000f}, + { 1.12159f, 0.00000f, 0.00000f}, { 1.12159f, -0.62809f, 0.00000f}, + { 0.62809f, -1.12159f, 0.00000f}, { 0.00000f, -1.12159f, 0.00000f}, + {-1.60227f, 0.00000f, 2.48352f}, {-1.60227f, -0.16023f, 2.48352f}, + {-1.60227f, -0.16023f, 2.72386f}, {-1.60227f, 0.00000f, 2.72386f}, + {-2.72386f, 0.00000f, 3.04432f}, {-2.72386f, -0.16023f, 3.04432f}, + {-2.88409f, -0.16023f, 3.36477f}, {-2.88409f, 0.00000f, 3.36477f}, + {-2.72386f, 0.00000f, 1.84261f}, {-2.72386f, -0.16023f, 1.84261f}, + {-3.20455f, -0.16023f, 1.68239f}, {-3.20455f, 0.00000f, 1.68239f}, + {-1.44205f, 0.00000f, 1.28182f}, {-1.44205f, -0.16023f, 1.28182f}, + {-1.44205f, -0.16023f, 1.04148f}, {-1.44205f, 0.00000f, 1.04148f} +}; + +#define GLUT_TEASPOON_N_INPUT_PATCHES 16 +static int patchdata_teaspoon[GLUT_TEASPOON_N_INPUT_PATCHES][16] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 12, }, + { 3, 14, 15, 16, 7, 17, 18, 19, 11, 20, 21, 22, 12, 23, 24, 25, }, + { 26, 27, 28, 0, 29, 30, 31, 4, 32, 33, 34, 8, 25, 24, 23, 12, }, + { 16, 35, 36, 26, 19, 37, 38, 29, 22, 39, 40, 32, 25, 41, 41, 25, }, + { 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 0, 1, 2, 3, }, + { 45, 54, 55, 56, 49, 57, 58, 59, 53, 60, 61, 62, 3, 14, 15, 16, }, + { 56, 63, 64, 65, 59, 66, 67, 68, 62, 69, 70, 71, 16, 35, 36, 26, }, + { 65, 72, 73, 42, 68, 74, 75, 46, 71, 76, 77, 50, 26, 27, 28, 0, }, + { 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 42, 43, 44, 45, }, + { 81, 90, 91, 92, 85, 93, 94, 95, 89, 96, 97, 98, 45, 54, 55, 56, }, + { 92, 99, 100, 101, 95, 102, 103, 104, 98, 105, 106, 107, 56, 63, 64, 65, }, + {101, 108, 109, 78, 104, 110, 111, 82, 107, 112, 113, 86, 65, 72, 73, 42, }, + {114, 115, 116, 116, 117, 118, 119, 120, 121, 122, 123, 124, 78, 79, 80, 81, }, + {116, 116, 125, 125, 120, 126, 127, 128, 124, 129, 130, 131, 81, 90, 91, 92, }, + {125, 125, 132, 132, 128, 133, 134, 135, 131, 136, 137, 138, 92, 99, 100, 101, }, + {132, 132, 139, 114, 135, 140, 141, 117, 138, 142, 143, 121, 101, 108, 109, 78 } +}; + +static GLfloat cpdata_teaspoon[][3] = +{ + {-0.37768f, 0.00000f, -0.06295f}, {-0.15737f, 0.00000f, -0.31473f}, + { 0.15737f, 0.00000f, -0.31473f}, { 0.37768f, 0.00000f, -0.06295f}, + {-0.37768f, 0.33573f, -0.06295f}, {-0.15737f, 0.33573f, -0.31473f}, + { 0.15737f, 0.33573f, -0.31473f}, { 0.37768f, 0.33573f, -0.06295f}, + {-0.18884f, 0.72388f, 0.00000f}, {-0.07851f, 0.62946f, -0.18834f}, + { 0.07851f, 0.62946f, -0.18834f}, { 0.18884f, 0.72388f, 0.00000f}, + {-0.00000f, 0.72388f, 0.00000f}, { 0.00000f, 0.69241f, -0.06295f}, + { 0.43276f, 0.00000f, 0.00000f}, { 0.50357f, 0.00000f, 0.01574f}, + { 0.44062f, 0.00000f, -0.06295f}, { 0.43276f, 0.33573f, 0.00000f}, + { 0.50357f, 0.33573f, 0.01574f}, { 0.44062f, 0.33573f, -0.06295f}, + { 0.21642f, 0.74749f, 0.04708f}, { 0.25179f, 0.77896f, 0.05508f}, + { 0.22031f, 0.75536f, 0.00000f}, { 0.00000f, 0.73175f, 0.01574f}, + { 0.00000f, 0.76323f, 0.01574f}, { 0.00000f, 0.75536f, 0.00000f}, + {-0.44062f, 0.00000f, -0.06295f}, {-0.50357f, 0.00000f, 0.01574f}, + {-0.43276f, 0.00000f, 0.00000f}, {-0.44062f, 0.33573f, -0.06295f}, + {-0.50357f, 0.33573f, 0.01574f}, {-0.43276f, 0.33573f, 0.00000f}, + {-0.22031f, 0.75536f, 0.00000f}, {-0.25179f, 0.77896f, 0.05508f}, + {-0.21642f, 0.74749f, 0.04708f}, { 0.18884f, 0.00000f, -0.37768f}, + {-0.18884f, 0.00000f, -0.37768f}, { 0.18884f, 0.33573f, -0.37768f}, + {-0.18884f, 0.33573f, -0.37768f}, { 0.09442f, 0.66094f, -0.22031f}, + {-0.09442f, 0.66094f, -0.22031f}, { 0.00000f, 0.72388f, -0.06295f}, + {-0.04721f, -0.88125f, 0.18884f}, {-0.01966f, -0.88125f, 0.18884f}, + { 0.01966f, -0.88125f, 0.18884f}, { 0.04721f, -0.88125f, 0.18884f}, + {-0.04721f, -0.56652f, 0.13638f}, {-0.01966f, -0.56652f, 0.13638f}, + { 0.01966f, -0.56652f, 0.13638f}, { 0.04721f, -0.56652f, 0.13638f}, + {-0.37768f, -0.50357f, -0.06295f}, {-0.15737f, -0.50357f, -0.31473f}, + { 0.15737f, -0.50357f, -0.31473f}, { 0.37768f, -0.50357f, -0.06295f}, + { 0.05410f, -0.88125f, 0.18884f}, { 0.06295f, -0.88125f, 0.16327f}, + { 0.05508f, -0.88125f, 0.15737f}, { 0.05410f, -0.56652f, 0.13638f}, + { 0.06295f, -0.56652f, 0.11081f}, { 0.05508f, -0.56652f, 0.10491f}, + { 0.43276f, -0.50357f, 0.00000f}, { 0.50357f, -0.50357f, 0.01574f}, + { 0.44062f, -0.50357f, -0.06295f}, { 0.02360f, -0.88125f, 0.13376f}, + {-0.02753f, -0.88125f, 0.12589f}, {-0.05508f, -0.88125f, 0.15737f}, + { 0.02360f, -0.56652f, 0.08130f}, {-0.02753f, -0.56652f, 0.07343f}, + {-0.05508f, -0.56652f, 0.10491f}, { 0.18884f, -0.50357f, -0.37768f}, + {-0.18884f, -0.50357f, -0.37768f}, {-0.44062f, -0.50357f, -0.06295f}, + {-0.06196f, -0.88125f, 0.16523f}, {-0.05410f, -0.88125f, 0.18884f}, + {-0.06196f, -0.56652f, 0.11277f}, {-0.05410f, -0.56652f, 0.13638f}, + {-0.50357f, -0.50357f, 0.01574f}, {-0.43276f, -0.50357f, 0.00000f}, + {-0.15737f, -3.02143f, 0.12589f}, {-0.03147f, -3.02143f, 0.15737f}, + { 0.03147f, -3.02143f, 0.15737f}, { 0.15737f, -3.02143f, 0.12589f}, + {-0.15737f, -2.39196f, 0.18884f}, {-0.03147f, -2.39196f, 0.22031f}, + { 0.03147f, -2.39196f, 0.22031f}, { 0.15737f, -2.39196f, 0.18884f}, + {-0.04721f, -1.63648f, 0.31473f}, {-0.01966f, -1.63648f, 0.31473f}, + { 0.01966f, -1.63648f, 0.31473f}, { 0.04721f, -1.63648f, 0.31473f}, + { 0.18884f, -3.02143f, 0.11802f}, { 0.18884f, -3.02143f, 0.05508f}, + { 0.15737f, -3.02143f, 0.06295f}, { 0.18884f, -2.39196f, 0.18097f}, + { 0.18884f, -2.39196f, 0.11802f}, { 0.15737f, -2.39196f, 0.12589f}, + { 0.05410f, -1.63661f, 0.31473f}, { 0.06295f, -1.63648f, 0.28916f}, + { 0.05508f, -1.63648f, 0.28326f}, { 0.03147f, -3.02143f, 0.09442f}, + {-0.03147f, -3.02143f, 0.09442f}, {-0.15737f, -3.02143f, 0.06295f}, + { 0.03147f, -2.39196f, 0.15737f}, {-0.03147f, -2.39196f, 0.15737f}, + {-0.15737f, -2.39196f, 0.12589f}, { 0.02360f, -1.63661f, 0.25965f}, + {-0.02753f, -1.63648f, 0.25179f}, {-0.05508f, -1.63648f, 0.28326f}, + {-0.18884f, -3.02143f, 0.05508f}, {-0.18884f, -3.02143f, 0.11802f}, + {-0.18884f, -2.39196f, 0.11802f}, {-0.18884f, -2.39196f, 0.18097f}, + {-0.06196f, -1.63661f, 0.29113f}, {-0.05410f, -1.63661f, 0.31473f}, + {-0.00126f, -3.52500f, 0.06295f}, { 0.00126f, -3.52500f, 0.06295f}, + { 0.00000f, -3.52500f, 0.06295f}, {-0.19010f, -3.52374f, 0.06295f}, + { 0.00126f, -3.52374f, 0.06295f}, { 0.00000f, -3.52374f, 0.06295f}, + { 0.18884f, -3.52374f, 0.06295f}, {-0.15737f, -3.27321f, 0.10071f}, + {-0.03147f, -3.27321f, 0.13219f}, { 0.03147f, -3.27321f, 0.13219f}, + { 0.15737f, -3.27321f, 0.10071f}, { 0.00126f, -3.52500f, 0.00000f}, + { 0.23605f, -3.52374f, 0.06295f}, { 0.23731f, -3.52374f, 0.00000f}, + { 0.19010f, -3.52374f, 0.00000f}, { 0.18884f, -3.27321f, 0.09285f}, + { 0.18884f, -3.27321f, 0.02990f}, { 0.15737f, -3.27321f, 0.03777f}, + {-0.00126f, -3.52500f, 0.00000f}, { 0.00126f, -3.52374f, 0.00000f}, + {-0.00126f, -3.52374f, 0.00000f}, {-0.19010f, -3.52374f, 0.00000f}, + { 0.03147f, -3.27321f, 0.06924f}, {-0.03147f, -3.27321f, 0.06924f}, + {-0.15737f, -3.27321f, 0.03777f}, {-0.00189f, -3.52500f, 0.06295f}, + {-0.23731f, -3.52374f, 0.00000f}, {-0.23794f, -3.52374f, 0.06295f}, + {-0.18884f, -3.27321f, 0.02990f}, {-0.18884f, -3.27321f, 0.09285f} +}; + +#endif /* FREEGLUT_TEAPOT_DATA_H */ diff --git a/src/fg_version.h b/src/fg_version.h new file mode 100644 index 0000000..4bbbd12 --- /dev/null +++ b/src/fg_version.h @@ -0,0 +1,47 @@ +/* + * fg_version.h + * + * The freeglut library private include file. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Thu Dec 2 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef FREEGLUT_VERSION_H +#define FREEGLUT_VERSION_H + +/* Ordinarily it's cmake's job to update fg_version.h, + * edit CMakeLists.txt rather than this file directly. + */ + +#ifndef VERSION_MAJOR +#define VERSION_MAJOR 3 +#endif + +#ifndef VERSION_MINOR +#define VERSION_MINOR 4 +#endif + +#ifndef VERSION_PATCH +#define VERSION_PATCH 0 +#endif + +#endif diff --git a/src/fg_version.h.in b/src/fg_version.h.in new file mode 100644 index 0000000..45b489a --- /dev/null +++ b/src/fg_version.h.in @@ -0,0 +1,47 @@ +/* + * fg_version.h + * + * The freeglut library private include file. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Thu Dec 2 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef FREEGLUT_VERSION_H +#define FREEGLUT_VERSION_H + +/* Ordinarily it's cmake's job to update fg_version.h, + * edit CMakeLists.txt rather than this file directly. + */ + +#ifndef VERSION_MAJOR +#define VERSION_MAJOR @VERSION_MAJOR@ +#endif + +#ifndef VERSION_MINOR +#define VERSION_MINOR @VERSION_MINOR@ +#endif + +#ifndef VERSION_PATCH +#define VERSION_PATCH @VERSION_PATCH@ +#endif + +#endif diff --git a/src/fg_videoresize.c b/src/fg_videoresize.c new file mode 100644 index 0000000..67148c7 --- /dev/null +++ b/src/fg_videoresize.c @@ -0,0 +1,44 @@ +/* + * fg_videoresize.c + * + * Video resize functions (as defined by GLUT API) + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Thu Dec 16 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" + +/* + * NOTE: functions declared in this file probably will not be implemented. + */ + +/* -- INTERFACE FUNCTIONS -------------------------------------------------- */ + +int FGAPIENTRY glutVideoResizeGet( GLenum eWhat ) { return( 0x00 ); } +void FGAPIENTRY glutSetupVideoResizing( void ) { /* Not implemented */ } +void FGAPIENTRY glutStopVideoResizing( void ) { /* Not implemented */ } +void FGAPIENTRY glutVideoResize( int x, int y, int w, int h ) { /* Not implemented */ } +void FGAPIENTRY glutVideoPan( int x, int y, int w, int h ) { /* Not implemented */ } + +/*** END OF FILE ***/ + diff --git a/src/fg_window.c b/src/fg_window.c new file mode 100644 index 0000000..6efff54 --- /dev/null +++ b/src/fg_window.c @@ -0,0 +1,519 @@ +/* + * fg_window.c + * + * Window management methods. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Fri Dec 3 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#define FREEGLUT_BUILDING_LIB +#include +#include "fg_internal.h" +#include "fg_gl2.h" + +/* + * TODO BEFORE THE STABLE RELEASE: + * + * fgSetupPixelFormat -- ignores the display mode settings + * fgOpenWindow() -- check the Win32 version, -iconic handling! + * fgCloseWindow() -- check the Win32 version + * glutCreateWindow() -- Check when default position and size is {-1,-1} + * glutCreateSubWindow() -- Check when default position and size is {-1,-1} + * glutDestroyWindow() -- check the Win32 version + * glutSetWindow() -- check the Win32 version + * glutSetWindowTitle() -- check the Win32 version + * glutSetIconTitle() -- check the Win32 version + * glutShowWindow() -- check the Win32 version + * glutHideWindow() -- check the Win32 version + * glutIconifyWindow() -- check the Win32 version + * glutPushWindow() -- check the Win32 version + * glutPopWindow() -- check the Win32 version + */ + + +extern void fgPlatformSetWindow ( SFG_Window *window ); +extern void fgPlatformOpenWindow( SFG_Window* window, const char* title, + GLboolean positionUse, int x, int y, + GLboolean sizeUse, int w, int h, + GLboolean gameMode, GLboolean isSubWindow ); +extern void fgPlatformCloseWindow( SFG_Window* window ); +extern void fgPlatformGlutSetWindowTitle( const char* title ); +extern void fgPlatformGlutSetIconTitle( const char* title ); + + +/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ + +int fghIsLegacyContextRequested( SFG_Window *win ) +{ + int vmajor = fgState.MajorVersion; + int vminor = fgState.MinorVersion; + /* XXX: menu windows are drawn with the fixed function pipeline, therefore + * the context created for them can't be a modern core-profile context. + * Force the traditional context creation for menu windows. + */ + return vmajor < 2 || (vmajor == 2 && vminor <= 1) || win->IsMenu; +} + +int fghNumberOfAuxBuffersRequested( void ) +{ + if ( fgState.DisplayMode & GLUT_AUX4 ) { + return 4; + } + if ( fgState.DisplayMode & GLUT_AUX3 ) { + return 3; + } + if ( fgState.DisplayMode & GLUT_AUX2 ) { + return 2; + } + if ( fgState.DisplayMode & GLUT_AUX1 ) { /* NOTE: Same as GLUT_AUX! */ + return fgState.AuxiliaryBufferNumber; + } + return 0; +} + +int fghMapBit( int mask, int from, int to ) +{ + return ( mask & from ) ? to : 0; + +} + +void fghContextCreationError( void ) +{ + fgError( "Unable to create OpenGL %d.%d context (flags %x, profile %x)", + fgState.MajorVersion, fgState.MinorVersion, fgState.ContextFlags, + fgState.ContextProfile ); +} + + +/* -- SYSTEM-DEPENDENT PRIVATE FUNCTIONS ------------------------------------ */ + +/* + * Sets the OpenGL context and the fgStructure "Current Window" pointer to + * the window structure passed in. + */ +void fgSetWindow ( SFG_Window *window ) +{ + fgPlatformSetWindow ( window ); + + fgStructure.CurrentWindow = window; +} + +/* + * Opens a window. Requires a SFG_Window object created and attached + * to the freeglut structure. OpenGL context is created here. + */ +void fgOpenWindow( SFG_Window* window, const char* title, + GLboolean positionUse, int x, int y, + GLboolean sizeUse, int w, int h, + GLboolean gameMode, GLboolean isSubWindow ) +{ + fgPlatformOpenWindow( window, title, + positionUse, x, y, + sizeUse, w, h, + gameMode, isSubWindow ); + + fgSetWindow( window ); + +#ifndef EGL_VERSION_1_0 + window->Window.DoubleBuffered = + ( fgState.DisplayMode & GLUT_DOUBLE ) ? 1 : 0; + + if ( ! window->Window.DoubleBuffered ) + { + glDrawBuffer ( GL_FRONT ); + glReadBuffer ( GL_FRONT ); + } +#else + /* - EGL is always double-buffered */ + /* - No glDrawBuffer/glReadBuffer in GLES */ + window->Window.DoubleBuffered = 1; +#endif + window->Window.attribute_v_coord = -1; + window->Window.attribute_v_normal = -1; + window->Window.attribute_v_texture = -1; + + fgInitGL2(); + + window->State.WorkMask |= GLUT_INIT_WORK; +} + +/* + * Closes a window, destroying the frame and OpenGL context + */ +void fgCloseWindow( SFG_Window* window ) +{ + /* if we're in gamemode and we're closing the gamemode window, + * call glutLeaveGameMode first to make sure the gamemode is + * properly closed before closing the window + */ + if (fgStructure.GameModeWindow != NULL && fgStructure.GameModeWindow->ID==window->ID) + glutLeaveGameMode(); + + fgPlatformCloseWindow ( window ); +} + + +/* -- INTERFACE FUNCTIONS -------------------------------------------------- */ + +/* + * Creates a new top-level freeglut window + */ +int FGAPIENTRY glutCreateWindow( const char* title ) +{ + /* XXX GLUT does not exit; it simply calls "glutInit" quietly if the + * XXX application has not already done so. The "freeglut" community + * XXX decided not to go this route (freeglut-developer e-mail from + * XXX Steve Baker, 12/16/04, 4:22 PM CST, "Re: [Freeglut-developer] + * XXX Desired 'freeglut' behaviour when there is no current window") + */ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateWindow" ); + + return fgCreateWindow( NULL, title, + fgState.Position.Use, fgState.Position.X, fgState.Position.Y, + fgState.Size.Use, fgState.Size.X, fgState.Size.Y, + GL_FALSE, GL_FALSE )->ID; +} + +/* + * This function creates a sub window. + */ +int FGAPIENTRY glutCreateSubWindow( int parentID, int x, int y, int w, int h ) +{ + int ret = 0; + SFG_Window* window = NULL; + SFG_Window* parent = NULL; + + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateSubWindow" ); + parent = fgWindowByID( parentID ); + freeglut_return_val_if_fail( parent != NULL, 0 ); + + if ( fgState.AllowNegativeWindowPosition ) + { + /* XXX This results in different widths/heights than if AllowNegativeWindowPosition + * XXX was false. The "freeglut" community defined this logic. + * XXX (freeglut-developer e-mail from Diederick C. Niehorster, 11/15/2015, 4:06 PM EST. + * XXX "Re: [Freeglut-developer] glutInitWindowPosition with negative coordinate(s)") + */ + + if ( w < 0 ) w = parent->State.Width + w ; + if ( h < 0 ) h = parent->State.Height + h ; + } + else + { + if ( ( x < 0 ) ) + { + x = parent->State.Width + x ; + if ( w > 0 ) x -= w ; + } + + if ( w < 0 ) w = parent->State.Width - x + w ; + if ( w < 0 ) + { + x += w ; + w = -w ; + } + + if ( ( y < 0 ) ) + { + y = parent->State.Height + y ; + if ( h > 0 ) y -= h ; + } + + if ( h < 0 ) h = parent->State.Height - y + h ; + if ( h < 0 ) + { + y += h ; + h = -h ; + } + } + + window = fgCreateWindow( parent, "", + GL_TRUE, x, y, + GL_TRUE, w, h, + GL_FALSE, GL_FALSE ); + ret = window->ID; + + return ret; +} + +/* + * Destroys a window and all of its subwindows + */ +void FGAPIENTRY glutDestroyWindow( int windowID ) +{ + SFG_Window* window; + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDestroyWindow" ); + window = fgWindowByID( windowID ); + freeglut_return_if_fail( window != NULL ); + { + fgExecutionState ExecState = fgState.ExecState; + fgAddToWindowDestroyList( window ); + fgState.ExecState = ExecState; + } +} + +/* + * This function selects the specified window as the current window + */ +void FGAPIENTRY glutSetWindow( int ID ) +{ + SFG_Window* window = NULL; + + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetWindow" ); + if( fgStructure.CurrentWindow != NULL ) + if( fgStructure.CurrentWindow->ID == ID ) + return; + + window = fgWindowByID( ID ); + if( window == NULL ) + { + fgWarning( "glutSetWindow(): window ID %d not found!", ID ); + return; + } + + fgSetWindow( window ); +} + +/* + * This function returns the ID number of the current window, 0 if none exists + */ +int FGAPIENTRY glutGetWindow( void ) +{ + SFG_Window *win = fgStructure.CurrentWindow; + /* + * Since GLUT did not throw an error if this function was called without a prior call to + * "glutInit", this function shouldn't do so here. Instead let us return a zero. + * See Feature Request "[ 1307049 ] glutInit check". + */ + if ( ! fgState.Initialised ) + return 0; + + while ( win && win->IsMenu ) + win = win->Parent; + return win ? win->ID : 0; +} + +/* + * This function makes the current window visible + */ +void FGAPIENTRY glutShowWindow( void ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutShowWindow" ); + FREEGLUT_EXIT_IF_NO_WINDOW ( "glutShowWindow" ); + + fgStructure.CurrentWindow->State.WorkMask |= GLUT_VISIBILITY_WORK; + fgStructure.CurrentWindow->State.DesiredVisibility = DesireNormalState; + + fgStructure.CurrentWindow->State.WorkMask |= GLUT_DISPLAY_WORK; +} + +/* + * This function hides the current window + */ +void FGAPIENTRY glutHideWindow( void ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutHideWindow" ); + FREEGLUT_EXIT_IF_NO_WINDOW ( "glutHideWindow" ); + + fgStructure.CurrentWindow->State.WorkMask |= GLUT_VISIBILITY_WORK; + fgStructure.CurrentWindow->State.DesiredVisibility = DesireHiddenState; + + fgStructure.CurrentWindow->State.WorkMask &= ~GLUT_DISPLAY_WORK; +} + +/* + * Iconify the current window (top-level windows only) + */ +void FGAPIENTRY glutIconifyWindow( void ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIconifyWindow" ); + FREEGLUT_EXIT_IF_NO_WINDOW ( "glutIconifyWindow" ); + + fgStructure.CurrentWindow->State.WorkMask |= GLUT_VISIBILITY_WORK; + fgStructure.CurrentWindow->State.DesiredVisibility = DesireIconicState; + + fgStructure.CurrentWindow->State.WorkMask &= ~GLUT_DISPLAY_WORK; +} + +/* + * Set the current window's title + */ +void FGAPIENTRY glutSetWindowTitle( const char* title ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetWindowTitle" ); + FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetWindowTitle" ); + if( ! fgStructure.CurrentWindow->Parent ) + { + fgPlatformGlutSetWindowTitle ( title ); + } +} + +/* + * Set the current window's iconified title + */ +void FGAPIENTRY glutSetIconTitle( const char* title ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetIconTitle" ); + FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetIconTitle" ); + + if( ! fgStructure.CurrentWindow->Parent ) + { + fgPlatformGlutSetIconTitle ( title ); + } +} + +/* + * Change the current window's size + */ +void FGAPIENTRY glutReshapeWindow( int width, int height ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeWindow" ); + FREEGLUT_EXIT_IF_NO_WINDOW ( "glutReshapeWindow" ); + + if (glutGet(GLUT_FULL_SCREEN)) + { + /* Leave full screen state before resizing. */ + glutLeaveFullScreen(); + } + + fgStructure.CurrentWindow->State.WorkMask |= GLUT_SIZE_WORK; + fgStructure.CurrentWindow->State.DesiredWidth = width ; + fgStructure.CurrentWindow->State.DesiredHeight = height; +} + +/* + * Change the current window's position + */ +void FGAPIENTRY glutPositionWindow( int x, int y ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPositionWindow" ); + FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPositionWindow" ); + + if (glutGet(GLUT_FULL_SCREEN)) + { + /* Leave full screen state before moving. */ + glutLeaveFullScreen(); + } + + fgStructure.CurrentWindow->State.WorkMask |= GLUT_POSITION_WORK; + fgStructure.CurrentWindow->State.DesiredXpos = x; + fgStructure.CurrentWindow->State.DesiredYpos = y; +} + +/* + * Lowers the current window (by Z order change) + */ +void FGAPIENTRY glutPushWindow( void ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPushWindow" ); + FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPushWindow" ); + + fgStructure.CurrentWindow->State.WorkMask |= GLUT_ZORDER_WORK; + fgStructure.CurrentWindow->State.DesiredZOrder = -1; +} + +/* + * Raises the current window (by Z order change) + */ +void FGAPIENTRY glutPopWindow( void ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPopWindow" ); + FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPopWindow" ); + + fgStructure.CurrentWindow->State.WorkMask |= GLUT_ZORDER_WORK; + fgStructure.CurrentWindow->State.DesiredZOrder = 1; +} + +/* + * Resize the current window so that it fits the whole screen + */ +void FGAPIENTRY glutFullScreen( void ) +{ + SFG_Window *win; + + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreen" ); + FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreen" ); + + win = fgStructure.CurrentWindow; + + if (win->Parent) + { + /* Child windows cannot be made fullscreen, consistent with GLUT's behavior + * Also, what would it mean for a child window to be fullscreen, given that it + * is confined to its parent? + */ + fgWarning("glutFullScreen called on a child window, ignoring..."); + return; + } + else if (fgStructure.GameModeWindow != NULL && fgStructure.GameModeWindow->ID==win->ID && win->State.IsFullscreen) + { + /* Ignore fullscreen call on GameMode window, those are always fullscreen already + * only exception is when first entering GameMode + */ + return; + } + + if (!win->State.IsFullscreen) + win->State.WorkMask |= GLUT_FULL_SCREEN_WORK; +} + +/* + * If we are fullscreen, resize the current window back to its original size + */ +void FGAPIENTRY glutLeaveFullScreen( void ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreen" ); + FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreen" ); + + if (fgStructure.CurrentWindow->State.IsFullscreen) + fgStructure.CurrentWindow->State.WorkMask |= GLUT_FULL_SCREEN_WORK; +} + +/* + * Toggle the window's full screen state. + */ +void FGAPIENTRY glutFullScreenToggle( void ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreenToggle" ); + FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreenToggle" ); + + fgStructure.CurrentWindow->State.WorkMask |= GLUT_FULL_SCREEN_WORK; +} + +/* + * A.Donev: Set and retrieve the window's user data + */ +void* FGAPIENTRY glutGetWindowData( void ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGetWindowData" ); + FREEGLUT_EXIT_IF_NO_WINDOW ( "glutGetWindowData" ); + return fgStructure.CurrentWindow->UserData; +} + +void FGAPIENTRY glutSetWindowData(void* data) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetWindowData" ); + FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetWindowData" ); + fgStructure.CurrentWindow->UserData = data; +} + +/*** END OF FILE ***/ diff --git a/src/freeglutdll.def.in b/src/freeglutdll.def.in new file mode 100644 index 0000000..50971bb --- /dev/null +++ b/src/freeglutdll.def.in @@ -0,0 +1,165 @@ +VERSION @VERSION_MAJOR@.@VERSION_MINOR@ +EXPORTS + glutInit + glutInitWindowPosition + glutInitWindowSize + glutInitDisplayMode + glutInitDisplayString + glutMainLoop + glutMainLoopEvent + glutLeaveMainLoop + glutCreateWindow + glutCreateSubWindow + glutDestroyWindow + glutSetWindow + glutGetWindow + glutSetWindowData + glutGetWindowData + glutSetWindowTitle + glutSetIconTitle + glutReshapeWindow + glutPositionWindow + glutShowWindow + glutHideWindow + glutIconifyWindow + glutPushWindow + glutPopWindow + glutFullScreen + glutPostWindowRedisplay + glutPostRedisplay + glutSwapBuffers + glutWarpPointer + glutSetCursor + glutEstablishOverlay + glutRemoveOverlay + glutUseLayer + glutPostOverlayRedisplay + glutPostWindowOverlayRedisplay + glutShowOverlay + glutHideOverlay + glutCreateMenu + glutDestroyMenu + glutGetMenu + glutSetMenu + glutGetMenuData + glutSetMenuData + glutAddMenuEntry + glutAddSubMenu + glutChangeToMenuEntry + glutChangeToSubMenu + glutRemoveMenuItem + glutAttachMenu + glutDetachMenu + glutTimerFunc + glutIdleFunc + glutKeyboardFunc + glutSpecialFunc + glutReshapeFunc + glutPositionFunc + glutVisibilityFunc + glutDisplayFunc + glutMouseFunc + glutMouseWheelFunc + glutMotionFunc + glutPassiveMotionFunc + glutEntryFunc + glutCloseFunc + glutWMCloseFunc + glutKeyboardUpFunc + glutSpecialUpFunc + glutJoystickFunc + glutMenuStateFunc + glutMenuStatusFunc + glutMenuDestroyFunc + glutOverlayDisplayFunc + glutWindowStatusFunc + glutSpaceballMotionFunc + glutSpaceballRotateFunc + glutSpaceballButtonFunc + glutButtonBoxFunc + glutDialsFunc + glutTabletMotionFunc + glutTabletButtonFunc + glutSetOption + glutGet + glutDeviceGet + glutGetModifiers + glutLayerGet + glutBitmapCharacter + glutBitmapWidth + glutStrokeCharacter + glutStrokeWidth + glutBitmapLength + glutStrokeLength + glutBitmapHeight + glutStrokeHeight + glutBitmapString + glutStrokeString + glutWireCube + glutSolidCube + glutWireSphere + glutSolidSphere + glutWireCone + glutSolidCone + glutWireTorus + glutSolidTorus + glutWireDodecahedron + glutSolidDodecahedron + glutWireOctahedron + glutSolidOctahedron + glutWireTetrahedron + glutSolidTetrahedron + glutWireIcosahedron + glutSolidIcosahedron + glutWireRhombicDodecahedron + glutSolidRhombicDodecahedron + glutWireSierpinskiSponge + glutSolidSierpinskiSponge + glutWireTeapot + glutSolidTeapot + glutWireTeacup + glutSolidTeacup + glutWireTeaspoon + glutSolidTeaspoon + glutWireCylinder + glutSolidCylinder + glutGameModeString + glutEnterGameMode + glutLeaveGameMode + glutGameModeGet + glutVideoResizeGet + glutSetupVideoResizing + glutStopVideoResizing + glutVideoResize + glutVideoPan + glutSetColor + glutGetColor + glutCopyColormap + glutIgnoreKeyRepeat + glutSetKeyRepeat + glutForceJoystickFunc + glutExtensionSupported + glutReportErrors + glutGetProcAddress + glutExit + glutFullScreenToggle + glutLeaveFullScreen + glutSetMenuFont + glutGetModeValues + glutInitContextFlags + glutInitContextVersion + glutInitContextProfile + glutInitErrorFunc + glutInitWarningFunc + __glutInitWithExit + __glutCreateWindowWithExit + __glutCreateMenuWithExit + glutMultiButtonFunc + glutMultiEntryFunc + glutMultiMotionFunc + glutMultiPassiveFunc + glutInitContextFunc + glutAppStatusFunc + glutSetVertexAttribCoord3 + glutSetVertexAttribNormal + glutSetVertexAttribTexCoord2 diff --git a/src/gles_stubs.c b/src/gles_stubs.c new file mode 100644 index 0000000..2695fc7 --- /dev/null +++ b/src/gles_stubs.c @@ -0,0 +1,52 @@ +/* TODO: implement me! */ + +#define FREEGLUT_BUILDING_LIB +#include +#include "fg_internal.h" + +void fgDeactivateMenu( SFG_Window *window ) { + fprintf(stderr, "fgDeactivateMenu: STUB\n"); +} +void fgDisplayMenu( void ) { + fprintf(stderr, "fgDisplayMenu: STUB\n"); +} +void fgUpdateMenuHighlight ( SFG_Menu *menu ) { + fprintf(stderr, "fgUpdateMenuHighlight: STUB\n"); +} +GLboolean fgCheckActiveMenu ( SFG_Window *window, int button, GLboolean pressed, + int mouse_x, int mouse_y ) { + fprintf(stderr, "fgCheckActiveMenu: STUB\n"); + return GL_FALSE; +} + +int FGAPIENTRY glutCreateMenuUcall( FGCBMenuUC callback, FGCBUserData userData ) { return 0; } + +int glutCreateMenu( void (* callback)( int menu ) ) { return 0; } +void glutDestroyMenu( int menu ) {} +int glutGetMenu( void ) { return 0; } +void glutSetMenu( int menu ) {} +void glutAddMenuEntry( const char* label, int value ) {} +void glutAddSubMenu( const char* label, int subMenu ) {} +void glutChangeToMenuEntry( int item, const char* label, int value ) {} +void glutChangeToSubMenu( int item, const char* label, int value ) {} +void glutRemoveMenuItem( int item ) {} +void glutAttachMenu( int button ) {} +void glutDetachMenu( int button ) {} +void glutSetMenuFont( int menuID, void* font ) {} + +void glutBitmapCharacter( void* font, int character ) {} +int glutBitmapWidth( void* font, int character ) { return 0; } +void glutStrokeCharacter( void* font, int character ) {} +int glutStrokeWidth( void* font, int character ) { return 0; } +GLfloat glutStrokeWidthf( void* font, int character ) { return 0.0f; } +int glutBitmapLength( void* font, const unsigned char* string ) { return 0; } +int glutStrokeLength( void* font, const unsigned char* string ) { return 0; } +GLfloat glutStrokeLengthf( void* font, const unsigned char *string ) { return 0.0f; } + +void *glutGetMenuData( void ) { return NULL; } +void glutSetMenuData(void* data) {} + +int glutBitmapHeight( void* font ) { return 0; } +GLfloat glutStrokeHeight( void* font ) { return 0; } +void glutBitmapString( void* font, const unsigned char *string ) {} +void glutStrokeString( void* font, const unsigned char *string ) {} diff --git a/src/mswin/fg_cmap_mswin.c b/src/mswin/fg_cmap_mswin.c new file mode 100644 index 0000000..3abf447 --- /dev/null +++ b/src/mswin/fg_cmap_mswin.c @@ -0,0 +1,86 @@ +/* fg_cmap_mswin.c + * + * Win32 implementation of the colormap functions + * + * Copyright (C) 2022 John Tsiombikas + * Creation date: Sat September 3 2022 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include +#include "../fg_internal.h" + +void fgPlatformSetColor(int idx, float r, float g, float b) +{ + HPALETTE pal; + PALETTEENTRY col; + HDC dc; + + if(idx < 0 || idx >= 256) { + return; + } + + col.peRed = (int)(r * 255.0f); + col.peGreen = (int)(g * 255.0f); + col.peBlue = (int)(b * 255.0f); + col.peFlags = PC_NOCOLLAPSE; + + pal = fgStructure.CurrentWindow->Window.cmap; + SetPaletteEntries(pal, idx, 1, &col); + + if(!(dc = fgStructure.CurrentWindow->Window.pContext.Device)) { + return; + } + + UnrealizeObject(pal); + SelectPalette(dc, pal, 0); + RealizePalette(dc); +} + +float fgPlatformGetColor(int idx, int comp) +{ + PALETTEENTRY col; + HPALETTE pal; + + if(idx < 0 || idx >= 256) { + return -1.0f; + } + + pal = fgStructure.CurrentWindow->Window.cmap; + if(!GetPaletteEntries(pal, idx, 1, &col)) { + return -1.0f; + } + + switch(comp) { + case GLUT_RED: + return col.peRed / 255.0f; + case GLUT_GREEN: + return col.peGreen / 255.0f; + case GLUT_BLUE: + return col.peBlue / 255.0f; + default: + break; + } + return -1.0f; +} + +void fgPlatformCopyColormap(int win) +{ + /* TODO */ + fgWarning("glutCopyColormap not implemented yet on Win32"); +} diff --git a/src/mswin/fg_cursor_mswin.c b/src/mswin/fg_cursor_mswin.c new file mode 100644 index 0000000..cfab200 --- /dev/null +++ b/src/mswin/fg_cursor_mswin.c @@ -0,0 +1,146 @@ +/* + * fg_cursor_mswin.c + * + * The Windows-specific mouse cursor related stuff. + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by John F. Fay, + * Creation date: Thu Jan 19, 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "../fg_internal.h" + + + +void fgPlatformSetCursor ( SFG_Window *window, int cursorID ) +{ + /* + * Joe Krahn is re-writing the following code. + */ + /* Set the cursor AND change it for this window class. */ +#if !defined(__MINGW64__) && _MSC_VER <= 1200 +# define MAP_CURSOR(a,b) \ + case a: \ + SetCursor( LoadCursor( NULL, b ) ); \ + SetClassLong( window->Window.Handle, \ + GCL_HCURSOR, \ + ( LONG )LoadCursor( NULL, b ) ); \ + break; + /* Nuke the cursor AND change it for this window class. */ +# define ZAP_CURSOR(a,b) \ + case a: \ + SetCursor( NULL ); \ + SetClassLong( window->Window.Handle, \ + GCL_HCURSOR, ( LONG )NULL ); \ + break; +#else +# define MAP_CURSOR(a,b) \ + case a: \ + SetCursor( LoadCursor( NULL, b ) ); \ + SetClassLongPtr( window->Window.Handle, \ + GCLP_HCURSOR, \ + ( LONG )( LONG_PTR )LoadCursor( NULL, b ) ); \ + break; + /* Nuke the cursor AND change it for this window class. */ +# define ZAP_CURSOR(a,b) \ + case a: \ + SetCursor( NULL ); \ + SetClassLongPtr( window->Window.Handle, \ + GCLP_HCURSOR, ( LONG )( LONG_PTR )NULL ); \ + break; +#endif + + switch( cursorID ) + { + MAP_CURSOR( GLUT_CURSOR_RIGHT_ARROW, IDC_ARROW ); + MAP_CURSOR( GLUT_CURSOR_LEFT_ARROW, IDC_ARROW ); /* XXX ToDo */ + MAP_CURSOR( GLUT_CURSOR_INFO, IDC_HAND ); + MAP_CURSOR( GLUT_CURSOR_DESTROY, IDC_CROSS ); + MAP_CURSOR( GLUT_CURSOR_HELP, IDC_HELP ); + MAP_CURSOR( GLUT_CURSOR_CYCLE, IDC_SIZEALL ); + MAP_CURSOR( GLUT_CURSOR_SPRAY, IDC_CROSS ); + MAP_CURSOR( GLUT_CURSOR_WAIT, IDC_WAIT ); + MAP_CURSOR( GLUT_CURSOR_TEXT, IDC_IBEAM ); + MAP_CURSOR( GLUT_CURSOR_CROSSHAIR, IDC_CROSS ); + MAP_CURSOR( GLUT_CURSOR_UP_DOWN, IDC_SIZENS ); + MAP_CURSOR( GLUT_CURSOR_LEFT_RIGHT, IDC_SIZEWE ); + MAP_CURSOR( GLUT_CURSOR_TOP_SIDE, IDC_UPARROW ); + MAP_CURSOR( GLUT_CURSOR_BOTTOM_SIDE, IDC_ARROW ); /* XXX ToDo */ + MAP_CURSOR( GLUT_CURSOR_LEFT_SIDE, IDC_ARROW ); /* XXX ToDo */ + MAP_CURSOR( GLUT_CURSOR_RIGHT_SIDE, IDC_ARROW ); /* XXX ToDo */ + MAP_CURSOR( GLUT_CURSOR_TOP_LEFT_CORNER, IDC_SIZENWSE ); + MAP_CURSOR( GLUT_CURSOR_TOP_RIGHT_CORNER, IDC_SIZENESW ); + MAP_CURSOR( GLUT_CURSOR_BOTTOM_RIGHT_CORNER, IDC_SIZENWSE ); + MAP_CURSOR( GLUT_CURSOR_BOTTOM_LEFT_CORNER, IDC_SIZENESW ); + ZAP_CURSOR( GLUT_CURSOR_NONE, NULL ); + MAP_CURSOR( GLUT_CURSOR_FULL_CROSSHAIR, IDC_CROSS ); /* XXX ToDo */ + case GLUT_CURSOR_INHERIT: + { + SFG_Window *temp_window = window; + while (temp_window->Parent) + { + temp_window = temp_window->Parent; + if (temp_window->State.Cursor != GLUT_CURSOR_INHERIT) + { + fgPlatformSetCursor(window,temp_window->State.Cursor); + return; + } + } + /* No parent, or no parent with cursor type set. Fall back to default */ + fgPlatformSetCursor(window,GLUT_CURSOR_LEFT_ARROW); + } + break; + + default: + fgError( "Unknown cursor type: %d", cursorID ); + break; + } +} + + +void fgPlatformWarpPointer ( int x, int y ) +{ + POINT coords; + coords.x = x; + coords.y = y; + + /* ClientToScreen() translates {coords} for us. */ + ClientToScreen( fgStructure.CurrentWindow->Window.Handle, &coords ); + SetCursorPos( coords.x, coords.y ); +} + + +void fghPlatformGetCursorPos(const SFG_Window *window, GLboolean client, SFG_XYUse *mouse_pos) +{ + /* Get current pointer location in screen coordinates (if client is false or window is NULL), else + * Get current pointer location relative to top-left of client area of window (if client is true and window is not NULL) + */ + POINT pos; + GetCursorPos(&pos); + + /* convert to client coords if wanted */ + if (client && window && window->Window.Handle) + ScreenToClient(window->Window.Handle,&pos); + + mouse_pos->X = pos.x; + mouse_pos->Y = pos.y; + mouse_pos->Use = GL_TRUE; +} diff --git a/src/mswin/fg_display_mswin.c b/src/mswin/fg_display_mswin.c new file mode 100644 index 0000000..7ba6f32 --- /dev/null +++ b/src/mswin/fg_display_mswin.c @@ -0,0 +1,37 @@ +/* + * fg_display_mswin.c + * + * The Windows-specific mouse cursor related stuff. + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by John F. Fay, + * Creation date: Sat Jan 28, 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "../fg_internal.h" + + + + +void fgPlatformGlutSwapBuffers( SFG_PlatformDisplay *pDisplayPtr, SFG_Window* CurrentWindow ) +{ + SwapBuffers( CurrentWindow->Window.pContext.Device ); +} diff --git a/src/mswin/fg_ext_mswin.c b/src/mswin/fg_ext_mswin.c new file mode 100644 index 0000000..efc2fa9 --- /dev/null +++ b/src/mswin/fg_ext_mswin.c @@ -0,0 +1,56 @@ +/* + * freeglut_ext_mswin.c + * + * The Windows-specific mouse cursor related stuff. + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by John F. Fay, + * Creation date: Thu Jan 19, 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "../fg_internal.h" + +GLUTproc fgPlatformGetGLUTProcAddress( const char* procName ) +{ +#if !defined(_WIN32_WCE) + /* optimization: quick initial check */ + if( strncmp( procName, "glut", 4 ) != 0 ) + return NULL; + +#define CHECK_NAME(x) if( strcmp( procName, #x ) == 0) return (GLUTproc)x; + CHECK_NAME(glutJoystickFunc); + CHECK_NAME(glutForceJoystickFunc); + CHECK_NAME(glutGameModeString); + CHECK_NAME(glutEnterGameMode); + CHECK_NAME(glutLeaveGameMode); + CHECK_NAME(glutGameModeGet); +#undef CHECK_NAME +#endif /* !defined(_WIN32_WCE) */ + + return NULL; +} + + + +SFG_Proc fgPlatformGetProcAddress( const char *procName ) +{ + return (SFG_Proc)wglGetProcAddress( ( LPCSTR )procName ); +} diff --git a/src/mswin/fg_gamemode_mswin.c b/src/mswin/fg_gamemode_mswin.c new file mode 100644 index 0000000..389c20d --- /dev/null +++ b/src/mswin/fg_gamemode_mswin.c @@ -0,0 +1,188 @@ +/* + * fg_gamemode_mswin.c + * + * The Windows-specific mouse cursor related stuff. + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by John F. Fay, + * Creation date: Thu Jan 19, 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "../fg_internal.h" + +/* + * Changes to requested devmode, if it doesn't match current mode + */ +GLboolean fghChangeDisplayMode(GLboolean haveToTest, DEVMODE *devModeRequested) +{ + GLboolean success = GL_FALSE; + DEVMODE devModeCurrent; + char *fggmstr = NULL; + char displayMode[300]; + + /* Get current display mode */ + EnumDisplaySettings( fgDisplay.pDisplay.DisplayName, ENUM_CURRENT_SETTINGS, &devModeCurrent ); + /* Now see if requested matches current mode, then we're done + * There's only four fields we touch: + * - dmPelsWidth + * - dmPelsHeight + * - dmBitsPerPel + * - dmDisplayFrequency + */ + if (devModeCurrent.dmPelsWidth ==devModeRequested->dmPelsWidth && + devModeCurrent.dmPelsHeight ==devModeRequested->dmPelsHeight && + devModeCurrent.dmBitsPerPel ==devModeRequested->dmBitsPerPel && + devModeCurrent.dmDisplayFrequency==devModeRequested->dmDisplayFrequency) + { + if (!haveToTest) + { + /* update vars in case if actual switch was requested */ + EnumDisplaySettings( fgDisplay.pDisplay.DisplayName, ENUM_CURRENT_SETTINGS, &devModeCurrent ); + fgState.GameModeSize.X = devModeCurrent.dmPelsWidth; + fgState.GameModeSize.Y = devModeCurrent.dmPelsHeight; + fgState.GameModeDepth = devModeCurrent.dmBitsPerPel; + fgState.GameModeRefresh = devModeCurrent.dmDisplayFrequency; + } + + /* We're done */ + return GL_TRUE; + } + + + /* Ok, we do have a mode switch to perform/test */ + switch ( ChangeDisplaySettingsEx(fgDisplay.pDisplay.DisplayName, devModeRequested, NULL, haveToTest ? CDS_TEST : CDS_FULLSCREEN , NULL) ) + { + case DISP_CHANGE_SUCCESSFUL: + success = GL_TRUE; + + if (!haveToTest) + { + /* update vars in case if windows switched to proper mode */ + EnumDisplaySettings( fgDisplay.pDisplay.DisplayName, ENUM_CURRENT_SETTINGS, &devModeCurrent ); + fgState.GameModeSize.X = devModeCurrent.dmPelsWidth; + fgState.GameModeSize.Y = devModeCurrent.dmPelsHeight; + fgState.GameModeDepth = devModeCurrent.dmBitsPerPel; + fgState.GameModeRefresh = devModeCurrent.dmDisplayFrequency; + } + break; + case DISP_CHANGE_RESTART: + fggmstr = "The computer must be restarted for the graphics mode to work."; + break; + case DISP_CHANGE_BADFLAGS: + fggmstr = "An invalid set of flags was passed in."; + break; + case DISP_CHANGE_BADPARAM: + fggmstr = "An invalid parameter was passed in. This can include an invalid flag or combination of flags."; + break; + case DISP_CHANGE_FAILED: + fggmstr = "The display driver failed the specified graphics mode."; + break; + case DISP_CHANGE_BADMODE: + fggmstr = "The graphics mode is not supported."; + break; + default: + fggmstr = "Unknown error in graphics mode???"; /* dunno if it is possible, MSDN does not mention any other error */ + break; + } + + if ( !success ) + { + /* I'd rather get info whats going on in my program than wonder about */ + /* what magic happens behind my back, its lib for devels after all ;) */ + + /* append display mode to error to make things more informative */ + sprintf(displayMode,"%s Problem with requested mode: %lux%lu:%lu@%lu", fggmstr, devModeRequested->dmPelsWidth, devModeRequested->dmPelsHeight, devModeRequested->dmBitsPerPel, devModeRequested->dmDisplayFrequency); + fgWarning(displayMode); + } + + return success; +} + +/* + * Remembers the current visual settings, so that + * we can change them and restore later... + */ +void fgPlatformRememberState( void ) +{ + /* Grab the current desktop settings... */ + EnumDisplaySettings( fgDisplay.pDisplay.DisplayName, ENUM_CURRENT_SETTINGS, + &fgDisplay.pDisplay.DisplayMode ); + + /* Make sure we will be restoring all settings needed */ + fgDisplay.pDisplay.DisplayMode.dmFields |= + DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY; + +} + +/* + * Restores the previously remembered visual settings + */ +void fgPlatformRestoreState( void ) +{ + /* Restore the previously remembered desktop display settings */ + fghChangeDisplayMode(GL_FALSE,&fgDisplay.pDisplay.DisplayMode); +} + + + + +/* + * Changes the current display mode to match user's settings + */ +GLboolean fgPlatformChangeDisplayMode( GLboolean haveToTest ) +{ + DEVMODE devMode; + + /* Get current display mode */ + EnumDisplaySettings( fgDisplay.pDisplay.DisplayName, ENUM_CURRENT_SETTINGS, &devMode ); + devMode.dmFields = 0; + + if (fgState.GameModeSize.X!=-1) + { + devMode.dmPelsWidth = fgState.GameModeSize.X; + devMode.dmFields |= DM_PELSWIDTH; + } + if (fgState.GameModeSize.Y!=-1) + { + devMode.dmPelsHeight = fgState.GameModeSize.Y; + devMode.dmFields |= DM_PELSHEIGHT; + } + if (fgState.GameModeDepth!=-1) + { + devMode.dmBitsPerPel = fgState.GameModeDepth; + devMode.dmFields |= DM_BITSPERPEL; + } + if (fgState.GameModeRefresh!=-1) + { + devMode.dmDisplayFrequency = fgState.GameModeRefresh; + devMode.dmFields |= DM_DISPLAYFREQUENCY; + } + + return fghChangeDisplayMode(haveToTest, &devMode); +} + +void fgPlatformEnterGameMode( void ) +{ +} + +void fgPlatformLeaveGameMode( void ) +{ +} diff --git a/src/mswin/fg_init_mswin.c b/src/mswin/fg_init_mswin.c new file mode 100644 index 0000000..bd20b27 --- /dev/null +++ b/src/mswin/fg_init_mswin.c @@ -0,0 +1,177 @@ +/* + * fg_init_mswin.c + * + * The Windows-specific mouse cursor related stuff. + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by John F. Fay, + * Creation date: Thu Jan 19, 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#define FREEGLUT_BUILDING_LIB +#include +#include "../fg_internal.h" + + + +extern LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, + WPARAM wParam, LPARAM lParam ); +extern void fgPlatformInitSystemTime(); +extern void fghCloseInputDevices(void); + + +/* + * A call to this function should initialize all the display stuff... + */ +void fgPlatformInitialize( const char* displayName ) +{ + WNDCLASS wc; + BOOL atom; + + /* What we need to do is to initialize the fgDisplay global structure here. */ + fgDisplay.pDisplay.Instance = GetModuleHandle( NULL ); + fgDisplay.pDisplay.DisplayName= displayName ? strdup(displayName) : 0 ; + atom = GetClassInfo( fgDisplay.pDisplay.Instance, _T("FREEGLUT"), &wc ); + + if( atom == 0 ) + { + ZeroMemory( &wc, sizeof(WNDCLASS) ); + + /* + * Each of the windows should have its own device context, and we + * want redraw events during Vertical and Horizontal Resizes by + * the user. + */ + wc.lpfnWndProc = fgPlatformWindowProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = fgDisplay.pDisplay.Instance; + wc.hIcon = LoadIcon( fgDisplay.pDisplay.Instance, _T("GLUT_ICON") ); + +#if defined(_WIN32_WCE) + wc.style = CS_HREDRAW | CS_VREDRAW; +#else + wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; + if (!wc.hIcon) + wc.hIcon = LoadIcon( NULL, IDI_WINLOGO ); +#endif + + wc.hCursor = LoadCursor( NULL, IDC_ARROW ); + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = _T("FREEGLUT"); + + /* Register the window class */ + atom = RegisterClass( &wc ); + FREEGLUT_INTERNAL_ERROR_EXIT ( atom, "Window Class Not Registered", "fgPlatformInitialize" ); + } + + /* The screen dimensions can be obtained via GetSystemMetrics() calls */ + fgDisplay.ScreenWidth = GetSystemMetrics( SM_CXSCREEN ); + fgDisplay.ScreenHeight = GetSystemMetrics( SM_CYSCREEN ); + + { + HWND desktop = GetDesktopWindow( ); + HDC context = GetDC( desktop ); + + fgDisplay.ScreenWidthMM = GetDeviceCaps( context, HORZSIZE ); + fgDisplay.ScreenHeightMM = GetDeviceCaps( context, VERTSIZE ); + + ReleaseDC( desktop, context ); + } + /* If we have a DisplayName try to use it for metrics */ + if( fgDisplay.pDisplay.DisplayName ) + { + HDC context = CreateDC(fgDisplay.pDisplay.DisplayName,0,0,0); + if( context ) + { + fgDisplay.ScreenWidth = GetDeviceCaps( context, HORZRES ); + fgDisplay.ScreenHeight = GetDeviceCaps( context, VERTRES ); + fgDisplay.ScreenWidthMM = GetDeviceCaps( context, HORZSIZE ); + fgDisplay.ScreenHeightMM = GetDeviceCaps( context, VERTSIZE ); + DeleteDC(context); + } + else + fgWarning("fgPlatformInitialize: " + "CreateDC failed, Screen size info may be incorrect\n" + "This is quite likely caused by a bad '-display' parameter"); + + } + /* Set the timer granularity to 1 ms */ + timeBeginPeriod ( 1 ); + /* Init setup to deal with timer wrap, can't query system time before this is done */ + fgPlatformInitSystemTime(); + /* Get start time */ + fgState.Time = fgSystemTime(); + + + fgState.Initialised = GL_TRUE; + + /* Avoid registering atexit callback on Win32 as it can result in an + * access violation due to calling into a module which has been + * unloaded. + * Any cleanup isn't needed on Windows anyway, the OS takes care of it. + * see: http://blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx + */ +/* atexit(fgDeinitialize); */ + + /* InputDevice uses GlutTimerFunc(), so fgState.Initialised must be TRUE */ + fgInitialiseInputDevices(); +} + + + +/* Platform-Specific Deinitialization Functions: */ +void fgPlatformDeinitialiseInputDevices ( void ) +{ +#if !defined(_WIN32_WCE) + fghCloseInputDevices (); +#endif /* !defined(_WIN32_WCE) */ + fgState.JoysticksInitialised = GL_FALSE; + fgState.InputDevsInitialised = GL_FALSE; +} + +void fgPlatformCloseDisplay ( void ) +{ + if( fgDisplay.pDisplay.DisplayName ) + { + free( fgDisplay.pDisplay.DisplayName ); + fgDisplay.pDisplay.DisplayName = NULL; + } + + /* Reset the timer granularity */ + timeEndPeriod ( 1 ); +} + +void fgPlatformDestroyContext ( SFG_PlatformDisplay pDisplay, SFG_WindowContextType MContext ) +{ + /* Do nothing -- this is required for X11 */ +} + +/* -- PLATFORM-SPECIFIC INTERFACE FUNCTION -------------------------------------------------- */ + +void (__cdecl *__glutExitFunc)( int return_value ) = NULL; + +void FGAPIENTRY __glutInitWithExit( int *pargc, char **argv, void (__cdecl *exit_function)(int) ) +{ + __glutExitFunc = exit_function; + glutInit(pargc, argv); +} + diff --git a/src/mswin/fg_input_devices_mswin.c b/src/mswin/fg_input_devices_mswin.c new file mode 100644 index 0000000..1c769e0 --- /dev/null +++ b/src/mswin/fg_input_devices_mswin.c @@ -0,0 +1,129 @@ +/* + * fg_input_devices_mswin.c + * + * The Windows-specific mouse cursor related stuff. + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by John F. Fay, + * Creation date: Sat Jan 21, 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "../fg_internal.h" + +#include +#include + +struct _serialport { + HANDLE fh; + COMMTIMEOUTS timeouts_save; + DCB dcb_save; +}; + +typedef struct _serialport SERIALPORT; + +/* Serial Port Prototypes */ +SERIALPORT *fg_serial_open ( const char *device ); +void fg_serial_close ( SERIALPORT *port ); +int fg_serial_getchar ( SERIALPORT *port ); +int fg_serial_putchar ( SERIALPORT *port, unsigned char ch ); +void fg_serial_flush ( SERIALPORT *port ); + + +void fgPlatformRegisterDialDevice ( const char *dial_device ) +{ + if (!dial_device){ + static char devname[256]; + DWORD size=sizeof(devname); + DWORD type = REG_SZ; + HKEY key; + if (RegOpenKeyA(HKEY_LOCAL_MACHINE,"SOFTWARE\\FreeGLUT",&key)==ERROR_SUCCESS) { + if (RegQueryValueExA(key,"DialboxSerialPort",NULL,&type,(LPBYTE)devname,&size)==ERROR_SUCCESS){ + dial_device=devname; + } + RegCloseKey(key); + } + } +} + + +/* Serial Port Functions */ +SERIALPORT *fg_serial_open(const char *device){ + HANDLE fh; + DCB dcb={sizeof(DCB)}; + COMMTIMEOUTS timeouts; + SERIALPORT *port; + + fh = CreateFile(device,GENERIC_READ|GENERIC_WRITE,0,NULL, + OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); + if (!fh) return NULL; + + port = malloc(sizeof(SERIALPORT)); + ZeroMemory(port, sizeof(SERIALPORT)); + port->fh = fh; + + /* save current port settings */ + GetCommState(fh,&port->dcb_save); + GetCommTimeouts(fh,&port->timeouts_save); + + dcb.DCBlength=sizeof(DCB); + BuildCommDCB("96,n,8,1",&dcb); + SetCommState(fh,&dcb); + + ZeroMemory(&timeouts,sizeof(timeouts)); + timeouts.ReadTotalTimeoutConstant=1; + timeouts.WriteTotalTimeoutConstant=1; + SetCommTimeouts(fh,&timeouts); + + fg_serial_flush(port); + + return port; +} + +void fg_serial_close(SERIALPORT *port){ + if (port){ + /* restore old port settings */ + SetCommState(port->fh,&port->dcb_save); + SetCommTimeouts(port->fh,&port->timeouts_save); + CloseHandle(port->fh); + free(port); + } +} + +int fg_serial_getchar(SERIALPORT *port){ + DWORD n; + unsigned char ch; + if (!port) return EOF; + if (!ReadFile(port->fh,&ch,1,&n,NULL)) return EOF; + if (n==1) return ch; + return EOF; +} + +int fg_serial_putchar(SERIALPORT *port, unsigned char ch){ + DWORD n; + if (!port) return 0; + return WriteFile(port->fh,&ch,1,&n,NULL); +} + +void fg_serial_flush ( SERIALPORT *port ) +{ + FlushFileBuffers(port->fh); +} + diff --git a/src/mswin/fg_internal_mswin.h b/src/mswin/fg_internal_mswin.h new file mode 100644 index 0000000..59dd33d --- /dev/null +++ b/src/mswin/fg_internal_mswin.h @@ -0,0 +1,142 @@ +/* + * fg_internal_mswin.h + * + * The freeglut library private include file. + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by John F. Fay, + * Creation date: Thu Jan 19, 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef FREEGLUT_INTERNAL_MSWIN_H +#define FREEGLUT_INTERNAL_MSWIN_H + + +/* All Win32 headers depend on the huge windows.h recursive include. + * Note: Lower-case header names are used, for best cross-platform + * compatibility. + */ +#if !defined(_WIN32_WCE) +# include +# include +# include +/* CYGWIN does not have tchar.h, but has TEXT(x), defined in winnt.h. */ +# ifndef __CYGWIN__ +# include +# else +# define _TEXT(x) TEXT(x) +# define _T(x) TEXT(x) +# endif + +#endif + + +/* MinGW may lack a prototype for ChangeDisplaySettingsEx() (depending on the version?) */ +#if !defined(ChangeDisplaySettingsEx) +LONG WINAPI ChangeDisplaySettingsExA(LPCSTR,LPDEVMODEA,HWND,DWORD,LPVOID); +LONG WINAPI ChangeDisplaySettingsExW(LPCWSTR,LPDEVMODEW,HWND,DWORD,LPVOID); +# ifdef UNICODE +# define ChangeDisplaySettingsEx ChangeDisplaySettingsExW +# else +# define ChangeDisplaySettingsEx ChangeDisplaySettingsExA +# endif +#endif + + +/* Structure Definitions */ + +typedef struct tagSFG_PlatformDisplay SFG_PlatformDisplay; +struct tagSFG_PlatformDisplay +{ + HINSTANCE Instance; /* The application's instance */ + DEVMODE DisplayMode; /* Desktop's display settings */ + char *DisplayName; /* Display name for multi display support*/ +}; + +/* + * Make "freeglut" window handle and context types so that we don't need so + * much conditionally-compiled code later in the library. + */ +typedef HWND SFG_WindowHandleType; +typedef HGLRC SFG_WindowContextType; +typedef HPALETTE SFG_WindowColormapType; + +typedef struct tagSFG_PlatformContext SFG_PlatformContext; +struct tagSFG_PlatformContext +{ + HDC Device; /* The window's device context */ +}; + + +/* Window's state description. This structure should be kept portable. */ +typedef struct tagSFG_PlatformWindowState SFG_PlatformWindowState; +struct tagSFG_PlatformWindowState +{ + RECT OldRect; /* window rect - stored before the window is made fullscreen */ + DWORD OldStyle; /* window style - stored before the window is made fullscreen */ + DWORD OldStyleEx; /* window Ex style - stored before the window is made fullscreen */ + BOOL OldMaximized; /* window maximized state - stored before the window is made fullscreen */ + + BOOL MouseTracking; /* Needed for generating GLUT_ENTERED and GLUT_LEFT entry func callbacks on windows */ + + /* Need to store window titles to emulate + * glutSetIconTitle/glutSetWindowTitle as Windows has only + * one title associated with a window and we need to swap + * them out based on the window's iconic state + */ + char* WindowTitle; + char* IconTitle; +}; + + + +/* Joystick-Specific Definitions */ +#if !defined(_WIN32_WCE) +# define _JS_MAX_AXES 8 +typedef struct tagSFG_PlatformJoystick SFG_PlatformJoystick; +struct tagSFG_PlatformJoystick +{ + JOYCAPS jsCaps; + JOYINFOEX js; + UINT js_id; +}; +#endif + + +/* Menu font and color definitions */ +#define FREEGLUT_MENU_FONT GLUT_BITMAP_8_BY_13 + +#define FREEGLUT_MENU_PEN_FORE_COLORS {0.0f, 0.0f, 0.0f, 1.0f} +#define FREEGLUT_MENU_PEN_BACK_COLORS {0.85f, 0.85f, 0.85f, 1.0f} +#define FREEGLUT_MENU_PEN_HFORE_COLORS {1.0f, 1.0f, 1.0f, 1.0f} +#define FREEGLUT_MENU_PEN_HBACK_COLORS {0.15f, 0.15f, 0.45f, 1.0f} + + +/* -- PRIVATE FUNCTION DECLARATIONS ---------------------------------------- */ +/* Spaceball device functions, defined in fg_spaceball_mswin.c */ +//Added by Jinrong Xie 12/24/2014 +int fgIsSpaceballWinEvent(HWND hwnd, WPARAM wParam, LPARAM lParam); +void fgSpaceballHandleWinEvent(HWND hwnd, WPARAM wParam, LPARAM lParam); + +/* Function to be called on exit */ +extern void (__cdecl *__glutExitFunc)( int return_value ); + + +#endif /* FREEGLUT_INTERNAL_MSWIN_H */ diff --git a/src/mswin/fg_joystick_mswin.c b/src/mswin/fg_joystick_mswin.c new file mode 100644 index 0000000..e38c21a --- /dev/null +++ b/src/mswin/fg_joystick_mswin.c @@ -0,0 +1,264 @@ +/* + * fg_joystick_mswin.c + * + * The Windows-specific mouse cursor related stuff. + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by John F. Fay, + * Creation date: Sat Jan 28, 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "../fg_internal.h" + + +#if !defined(_WIN32_WCE) +# include +# include +# include + + + + +void fgPlatformJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes ) +{ + MMRESULT status; + + status = joyGetPosEx( joy->pJoystick.js_id, &joy->pJoystick.js ); + + if ( status != JOYERR_NOERROR ) + { + joy->error = GL_TRUE; + return; + } + + if ( buttons ) + *buttons = joy->pJoystick.js.dwButtons; + + if ( axes ) + { + /* + * WARNING - Fall through case clauses!! + */ + switch ( joy->num_axes ) + { + case 8: + /* Generate two POV axes from the POV hat angle. + * Low 16 bits of js.dwPOV gives heading (clockwise from ahead) in + * hundredths of a degree, or 0xFFFF when idle. + */ + if ( ( joy->pJoystick.js.dwPOV & 0xFFFF ) == 0xFFFF ) + { + axes [ 6 ] = 0.0; + axes [ 7 ] = 0.0; + } + else + { + /* This is the contentious bit: how to convert angle to X/Y. + * wk: I know of no define for PI that we could use here: + * SG_PI would pull in sg, M_PI is undefined for MSVC + * But the accuracy of the value of PI is very unimportant at + * this point. + */ + float s = (float) sin ( ( joy->pJoystick.js.dwPOV & 0xFFFF ) * ( 0.01 * 3.1415926535f / 180.0f ) ); + float c = (float) cos ( ( joy->pJoystick.js.dwPOV & 0xFFFF ) * ( 0.01 * 3.1415926535f / 180.0f ) ); + + /* Convert to coordinates on a square so that North-East + * is (1,1) not (.7,.7), etc. + * s and c cannot both be zero so we won't divide by zero. + */ + if ( fabs ( s ) < fabs ( c ) ) + { + axes [ 6 ] = ( c < 0.0 ) ? -s/c : s/c ; + axes [ 7 ] = ( c < 0.0 ) ? -1.0f : 1.0f; + } + else + { + axes [ 6 ] = ( s < 0.0 ) ? -1.0f : 1.0f; + axes [ 7 ] = ( s < 0.0 ) ? -c/s : c/s ; + } + } + + case 6: axes[5] = (float) joy->pJoystick.js.dwVpos; + case 5: axes[4] = (float) joy->pJoystick.js.dwUpos; + case 4: axes[3] = (float) joy->pJoystick.js.dwRpos; + case 3: axes[2] = (float) joy->pJoystick.js.dwZpos; + case 2: axes[1] = (float) joy->pJoystick.js.dwYpos; + case 1: axes[0] = (float) joy->pJoystick.js.dwXpos; + } + } +} + + + +/* Inspired by + http://msdn.microsoft.com/archive/en-us/dnargame/html/msdn_sidewind3d.asp + */ +# if FREEGLUT_LIB_PRAGMAS +# pragma comment (lib, "advapi32.lib") +# endif + +static int fghJoystickGetOEMProductName ( SFG_Joystick* joy, char *buf, int buf_sz ) +{ + char buffer [ 256 ]; + + char OEMKey [ 256 ]; + + HKEY hKey; + DWORD dwcb; + LONG lr; + + if ( joy->error ) + return 0; + + /* Open .. MediaResources\CurrentJoystickSettings */ + _snprintf ( buffer, sizeof(buffer), "%s\\%s\\%s", + REGSTR_PATH_JOYCONFIG, joy->pJoystick.jsCaps.szRegKey, + REGSTR_KEY_JOYCURR ); + + lr = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey); + + if ( lr != ERROR_SUCCESS ) return 0; + + /* Get OEM Key name */ + dwcb = sizeof(OEMKey); + + /* JOYSTICKID1-16 is zero-based; registry entries for VJOYD are 1-based. */ + _snprintf ( buffer, sizeof(buffer), "Joystick%d%s", joy->pJoystick.js_id + 1, REGSTR_VAL_JOYOEMNAME ); + + lr = RegQueryValueEx ( hKey, buffer, 0, 0, (LPBYTE) OEMKey, &dwcb); + RegCloseKey ( hKey ); + + if ( lr != ERROR_SUCCESS ) return 0; + + /* Open OEM Key from ...MediaProperties */ + _snprintf ( buffer, sizeof(buffer), "%s\\%s", REGSTR_PATH_JOYOEM, OEMKey ); + + lr = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey ); + + if ( lr != ERROR_SUCCESS ) return 0; + + /* Get OEM Name */ + dwcb = buf_sz; + + lr = RegQueryValueEx ( hKey, REGSTR_VAL_JOYOEMNAME, 0, 0, (LPBYTE) buf, + &dwcb ); + RegCloseKey ( hKey ); + + if ( lr != ERROR_SUCCESS ) return 0; + + return 1; +} + + +void fgPlatformJoystickOpen( SFG_Joystick* joy ) +{ + int i = 0; + + joy->pJoystick.js.dwFlags = JOY_RETURNALL; + joy->pJoystick.js.dwSize = sizeof( joy->pJoystick.js ); + + memset( &joy->pJoystick.jsCaps, 0, sizeof( joy->pJoystick.jsCaps ) ); + + joy->error = + ( joyGetDevCaps( joy->pJoystick.js_id, &joy->pJoystick.jsCaps, sizeof( joy->pJoystick.jsCaps ) ) != + JOYERR_NOERROR ); + + if( joy->pJoystick.jsCaps.wNumAxes == 0 ) + { + joy->num_axes = 0; + joy->error = GL_TRUE; + } + else + { + /* Device name from jsCaps is often "Microsoft PC-joystick driver", + * at least for USB. Try to get the real name from the registry. + */ + if ( ! fghJoystickGetOEMProductName( joy, joy->name, + sizeof( joy->name ) ) ) + { + fgWarning( "JS: Failed to read joystick name from registry" ); + strncpy( joy->name, joy->pJoystick.jsCaps.szPname, sizeof( joy->name ) ); + } + + /* Windows joystick drivers may provide any combination of + * X,Y,Z,R,U,V,POV - not necessarily the first n of these. + */ + if( joy->pJoystick.jsCaps.wCaps & JOYCAPS_HASPOV ) + { + joy->num_axes = _JS_MAX_AXES; + joy->min[ 7 ] = -1.0; joy->max[ 7 ] = 1.0; /* POV Y */ + joy->min[ 6 ] = -1.0; joy->max[ 6 ] = 1.0; /* POV X */ + } + else + joy->num_axes = 6; + + joy->min[ 5 ] = ( float )joy->pJoystick.jsCaps.wVmin; + joy->max[ 5 ] = ( float )joy->pJoystick.jsCaps.wVmax; + joy->min[ 4 ] = ( float )joy->pJoystick.jsCaps.wUmin; + joy->max[ 4 ] = ( float )joy->pJoystick.jsCaps.wUmax; + joy->min[ 3 ] = ( float )joy->pJoystick.jsCaps.wRmin; + joy->max[ 3 ] = ( float )joy->pJoystick.jsCaps.wRmax; + joy->min[ 2 ] = ( float )joy->pJoystick.jsCaps.wZmin; + joy->max[ 2 ] = ( float )joy->pJoystick.jsCaps.wZmax; + joy->min[ 1 ] = ( float )joy->pJoystick.jsCaps.wYmin; + joy->max[ 1 ] = ( float )joy->pJoystick.jsCaps.wYmax; + joy->min[ 0 ] = ( float )joy->pJoystick.jsCaps.wXmin; + joy->max[ 0 ] = ( float )joy->pJoystick.jsCaps.wXmax; + } + + /* Guess all the rest judging on the axes extremals */ + for( i = 0; i < joy->num_axes; i++ ) + { + joy->center [ i ] = ( joy->max[ i ] + joy->min[ i ] ) * 0.5f; + joy->dead_band[ i ] = 0.0f; + joy->saturate [ i ] = 1.0f; + } +} + + + +void fgPlatformJoystickInit( SFG_Joystick *fgJoystick[], int ident ) +{ + switch( ident ) + { + case 0: + fgJoystick[ ident ]->pJoystick.js_id = JOYSTICKID1; + fgJoystick[ ident ]->error = GL_FALSE; + break; + case 1: + fgJoystick[ ident ]->pJoystick.js_id = JOYSTICKID2; + fgJoystick[ ident ]->error = GL_FALSE; + break; + default: + fgJoystick[ ident ]->num_axes = 0; + fgJoystick[ ident ]->error = GL_TRUE; + return; + } +} + + + +void fgPlatformJoystickClose ( int ident ) +{ + /* Do nothing special */ +} +#endif + diff --git a/src/mswin/fg_main_mswin.c b/src/mswin/fg_main_mswin.c new file mode 100644 index 0000000..ed88061 --- /dev/null +++ b/src/mswin/fg_main_mswin.c @@ -0,0 +1,1788 @@ +/* + * fg_main_mswin.c + * + * The Windows-specific mouse cursor related stuff. + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by John F. Fay, + * Creation date: Sat Jan 21, 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "../fg_internal.h" + +extern void fghRedrawWindow ( SFG_Window *window ); +extern void fghRedrawWindowAndChildren ( SFG_Window *window ); +extern void fghOnReshapeNotify(SFG_Window *window, int width, int height, GLboolean forceNotify); +extern void fghOnPositionNotify(SFG_Window *window, int x, int y, GLboolean forceNotify); +extern void fghComputeWindowRectFromClientArea_QueryWindow( RECT *clientRect, const SFG_Window *window, BOOL posIsOutside ); +extern void fghGetClientArea( RECT *clientRect, const SFG_Window *window, BOOL posIsOutside ); + +extern void fgNewWGLCreateContext( SFG_Window* window ); +extern GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly, + unsigned char layer_type ); + +extern void fgPlatformCheckMenuDeactivate(HWND newFocusWnd); + +#ifdef WM_TOUCH +typedef BOOL (WINAPI *pGetTouchInputInfo)(HTOUCHINPUT,UINT,PTOUCHINPUT,int); +typedef BOOL (WINAPI *pCloseTouchInputHandle)(HTOUCHINPUT); +static pGetTouchInputInfo fghGetTouchInputInfo = (pGetTouchInputInfo)0xDEADBEEF; +static pCloseTouchInputHandle fghCloseTouchInputHandle = (pCloseTouchInputHandle)0xDEADBEEF; +#endif + +#ifdef _WIN32_WCE +typedef struct GXDisplayProperties GXDisplayProperties; +typedef struct GXKeyList GXKeyList; +#include + +typedef struct GXKeyList (*GXGETDEFAULTKEYS)(int); +typedef int (*GXOPENINPUT)(); + +GXGETDEFAULTKEYS GXGetDefaultKeys_ = NULL; +GXOPENINPUT GXOpenInput_ = NULL; + +struct GXKeyList gxKeyList; +#endif /* _WIN32_WCE */ + +#ifdef _DEBUG +/* + * WM_ message to string, for debugging + * This is taken from the 8.0 SDK, so Windows 8 API and everything earlier is included + */ +struct WM_MESSAGE_MAP +{ + UINT nMsg; + LPCSTR lpszMsg; +}; +#define DEFINE_MESSAGE(wm){ wm, #wm } +static struct WM_MESSAGE_MAP allMessages[] = +{ + DEFINE_MESSAGE(WM_NULL), + DEFINE_MESSAGE(WM_CREATE), + DEFINE_MESSAGE(WM_DESTROY), + DEFINE_MESSAGE(WM_MOVE), + DEFINE_MESSAGE(WM_SIZE), + + DEFINE_MESSAGE(WM_ACTIVATE), + DEFINE_MESSAGE(WM_SETFOCUS), + DEFINE_MESSAGE(WM_KILLFOCUS), + DEFINE_MESSAGE(WM_ENABLE), + DEFINE_MESSAGE(WM_SETREDRAW), + DEFINE_MESSAGE(WM_SETTEXT), + DEFINE_MESSAGE(WM_GETTEXT), + DEFINE_MESSAGE(WM_GETTEXTLENGTH), + DEFINE_MESSAGE(WM_PAINT), + DEFINE_MESSAGE(WM_CLOSE), +# ifndef _WIN32_WCE + DEFINE_MESSAGE(WM_QUERYENDSESSION), + DEFINE_MESSAGE(WM_QUERYOPEN), + DEFINE_MESSAGE(WM_ENDSESSION), +# endif + DEFINE_MESSAGE(WM_QUIT), + DEFINE_MESSAGE(WM_ERASEBKGND), + DEFINE_MESSAGE(WM_SYSCOLORCHANGE), + DEFINE_MESSAGE(WM_SHOWWINDOW), + DEFINE_MESSAGE(WM_WININICHANGE), + + DEFINE_MESSAGE(WM_DEVMODECHANGE), + DEFINE_MESSAGE(WM_ACTIVATEAPP), + DEFINE_MESSAGE(WM_FONTCHANGE), + DEFINE_MESSAGE(WM_TIMECHANGE), + DEFINE_MESSAGE(WM_CANCELMODE), + DEFINE_MESSAGE(WM_SETCURSOR), + DEFINE_MESSAGE(WM_MOUSEACTIVATE), + DEFINE_MESSAGE(WM_CHILDACTIVATE), + DEFINE_MESSAGE(WM_QUEUESYNC), + + DEFINE_MESSAGE(WM_GETMINMAXINFO), + + DEFINE_MESSAGE(WM_PAINTICON), + DEFINE_MESSAGE(WM_ICONERASEBKGND), + DEFINE_MESSAGE(WM_NEXTDLGCTL), + DEFINE_MESSAGE(WM_SPOOLERSTATUS), + DEFINE_MESSAGE(WM_DRAWITEM), + DEFINE_MESSAGE(WM_MEASUREITEM), + DEFINE_MESSAGE(WM_DELETEITEM), + DEFINE_MESSAGE(WM_VKEYTOITEM), + DEFINE_MESSAGE(WM_CHARTOITEM), + DEFINE_MESSAGE(WM_SETFONT), + DEFINE_MESSAGE(WM_GETFONT), + DEFINE_MESSAGE(WM_SETHOTKEY), + DEFINE_MESSAGE(WM_GETHOTKEY), + DEFINE_MESSAGE(WM_QUERYDRAGICON), + DEFINE_MESSAGE(WM_COMPAREITEM), +# if(WINVER >= 0x0500) +# ifndef _WIN32_WCE + DEFINE_MESSAGE(WM_GETOBJECT), + # endif +# endif /* WINVER >= 0x0500 */ + DEFINE_MESSAGE(WM_COMPACTING), + DEFINE_MESSAGE(WM_COMMNOTIFY), + DEFINE_MESSAGE(WM_WINDOWPOSCHANGING), + DEFINE_MESSAGE(WM_WINDOWPOSCHANGED), + + DEFINE_MESSAGE(WM_POWER), + + DEFINE_MESSAGE(WM_COPYDATA), + DEFINE_MESSAGE(WM_CANCELJOURNAL), + +# if(WINVER >= 0x0400) + DEFINE_MESSAGE(WM_NOTIFY), + DEFINE_MESSAGE(WM_INPUTLANGCHANGEREQUEST), + DEFINE_MESSAGE(WM_INPUTLANGCHANGE), + DEFINE_MESSAGE(WM_TCARD), + DEFINE_MESSAGE(WM_HELP), + DEFINE_MESSAGE(WM_USERCHANGED), + DEFINE_MESSAGE(WM_NOTIFYFORMAT), + + DEFINE_MESSAGE(WM_CONTEXTMENU), + DEFINE_MESSAGE(WM_STYLECHANGING), + DEFINE_MESSAGE(WM_STYLECHANGED), + DEFINE_MESSAGE(WM_DISPLAYCHANGE), + DEFINE_MESSAGE(WM_GETICON), + DEFINE_MESSAGE(WM_SETICON), +# endif /* WINVER >= 0x0400 */ + + DEFINE_MESSAGE(WM_NCCREATE), + DEFINE_MESSAGE(WM_NCDESTROY), + DEFINE_MESSAGE(WM_NCCALCSIZE), + DEFINE_MESSAGE(WM_NCHITTEST), + DEFINE_MESSAGE(WM_NCPAINT), + DEFINE_MESSAGE(WM_NCACTIVATE), + DEFINE_MESSAGE(WM_GETDLGCODE), +# ifndef _WIN32_WCE + DEFINE_MESSAGE(WM_SYNCPAINT), +# endif + DEFINE_MESSAGE(WM_NCMOUSEMOVE), + DEFINE_MESSAGE(WM_NCLBUTTONDOWN), + DEFINE_MESSAGE(WM_NCLBUTTONUP), + DEFINE_MESSAGE(WM_NCLBUTTONDBLCLK), + DEFINE_MESSAGE(WM_NCRBUTTONDOWN), + DEFINE_MESSAGE(WM_NCRBUTTONUP), + DEFINE_MESSAGE(WM_NCRBUTTONDBLCLK), + DEFINE_MESSAGE(WM_NCMBUTTONDOWN), + DEFINE_MESSAGE(WM_NCMBUTTONUP), + DEFINE_MESSAGE(WM_NCMBUTTONDBLCLK), + + + +# if(_WIN32_WINNT >= 0x0500) && defined(WM_NCXBUTTONDOWN) + DEFINE_MESSAGE(WM_NCXBUTTONDOWN), + DEFINE_MESSAGE(WM_NCXBUTTONUP), + DEFINE_MESSAGE(WM_NCXBUTTONDBLCLK), +# endif /* _WIN32_WINNT >= 0x0500 */ + + +# if(_WIN32_WINNT >= 0x0501) && defined(WM_INPUT_DEVICE_CHANGE) + DEFINE_MESSAGE(WM_INPUT_DEVICE_CHANGE), +# endif /* _WIN32_WINNT >= 0x0501 */ + +# if(_WIN32_WINNT >= 0x0501) + DEFINE_MESSAGE(WM_INPUT), +# endif /* _WIN32_WINNT >= 0x0501 */ + + DEFINE_MESSAGE(WM_KEYDOWN), + DEFINE_MESSAGE(WM_KEYUP), + DEFINE_MESSAGE(WM_CHAR), + DEFINE_MESSAGE(WM_DEADCHAR), + DEFINE_MESSAGE(WM_SYSKEYDOWN), + DEFINE_MESSAGE(WM_SYSKEYUP), + DEFINE_MESSAGE(WM_SYSCHAR), + DEFINE_MESSAGE(WM_SYSDEADCHAR), +# if(_WIN32_WINNT >= 0x0501) + DEFINE_MESSAGE(WM_UNICHAR), +# endif /* _WIN32_WINNT >= 0x0501 */ + +# if(WINVER >= 0x0400) + DEFINE_MESSAGE(WM_IME_STARTCOMPOSITION), + DEFINE_MESSAGE(WM_IME_ENDCOMPOSITION), + DEFINE_MESSAGE(WM_IME_COMPOSITION), + DEFINE_MESSAGE(WM_IME_KEYLAST), +# endif /* WINVER >= 0x0400 */ + + DEFINE_MESSAGE(WM_INITDIALOG), + DEFINE_MESSAGE(WM_COMMAND), + DEFINE_MESSAGE(WM_SYSCOMMAND), + DEFINE_MESSAGE(WM_TIMER), + DEFINE_MESSAGE(WM_HSCROLL), + DEFINE_MESSAGE(WM_VSCROLL), + DEFINE_MESSAGE(WM_INITMENU), + DEFINE_MESSAGE(WM_INITMENUPOPUP), +# if(WINVER >= 0x0601) + DEFINE_MESSAGE(WM_GESTURE), + DEFINE_MESSAGE(WM_GESTURENOTIFY), +# endif /* WINVER >= 0x0601 */ + DEFINE_MESSAGE(WM_MENUSELECT), + DEFINE_MESSAGE(WM_MENUCHAR), + DEFINE_MESSAGE(WM_ENTERIDLE), +# if(WINVER >= 0x0500) +# ifndef _WIN32_WCE + DEFINE_MESSAGE(WM_MENURBUTTONUP), + DEFINE_MESSAGE(WM_MENUDRAG), + DEFINE_MESSAGE(WM_MENUGETOBJECT), + DEFINE_MESSAGE(WM_UNINITMENUPOPUP), + DEFINE_MESSAGE(WM_MENUCOMMAND), + +# if(_WIN32_WINNT >= 0x0500) && defined(WM_CHANGEUISTATE) + DEFINE_MESSAGE(WM_CHANGEUISTATE), + DEFINE_MESSAGE(WM_UPDATEUISTATE), + DEFINE_MESSAGE(WM_QUERYUISTATE), +# endif /* _WIN32_WINNT >= 0x0500 */ + +# endif +# endif /* WINVER >= 0x0500 */ + + DEFINE_MESSAGE(WM_CTLCOLORMSGBOX), + DEFINE_MESSAGE(WM_CTLCOLOREDIT), + DEFINE_MESSAGE(WM_CTLCOLORLISTBOX), + DEFINE_MESSAGE(WM_CTLCOLORBTN), + DEFINE_MESSAGE(WM_CTLCOLORDLG), + DEFINE_MESSAGE(WM_CTLCOLORSCROLLBAR), + DEFINE_MESSAGE(WM_CTLCOLORSTATIC), +# define MN_GETHMENU 0x01E1 + + DEFINE_MESSAGE(WM_MOUSEMOVE), + DEFINE_MESSAGE(WM_LBUTTONDOWN), + DEFINE_MESSAGE(WM_LBUTTONUP), + DEFINE_MESSAGE(WM_LBUTTONDBLCLK), + DEFINE_MESSAGE(WM_RBUTTONDOWN), + DEFINE_MESSAGE(WM_RBUTTONUP), + DEFINE_MESSAGE(WM_RBUTTONDBLCLK), + DEFINE_MESSAGE(WM_MBUTTONDOWN), + DEFINE_MESSAGE(WM_MBUTTONUP), + DEFINE_MESSAGE(WM_MBUTTONDBLCLK), +# if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400) + DEFINE_MESSAGE(WM_MOUSEWHEEL), +# endif +# if (_WIN32_WINNT >= 0x0500) && defined(WM_XBUTTONDOWN) + DEFINE_MESSAGE(WM_XBUTTONDOWN), + DEFINE_MESSAGE(WM_XBUTTONUP), + DEFINE_MESSAGE(WM_XBUTTONDBLCLK), +# endif +# if (_WIN32_WINNT >= 0x0600) + DEFINE_MESSAGE(WM_MOUSEHWHEEL), +# endif + + + + DEFINE_MESSAGE(WM_PARENTNOTIFY), + DEFINE_MESSAGE(WM_ENTERMENULOOP), + DEFINE_MESSAGE(WM_EXITMENULOOP), + +# if(WINVER >= 0x0400) + DEFINE_MESSAGE(WM_NEXTMENU), + DEFINE_MESSAGE(WM_SIZING), + DEFINE_MESSAGE(WM_CAPTURECHANGED), + DEFINE_MESSAGE(WM_MOVING), +# endif /* WINVER >= 0x0400 */ + +# if(WINVER >= 0x0400) + DEFINE_MESSAGE(WM_POWERBROADCAST), + DEFINE_MESSAGE(WM_DEVICECHANGE), +# endif /* WINVER >= 0x0400 */ + + DEFINE_MESSAGE(WM_MDICREATE), + DEFINE_MESSAGE(WM_MDIDESTROY), + DEFINE_MESSAGE(WM_MDIACTIVATE), + DEFINE_MESSAGE(WM_MDIRESTORE), + DEFINE_MESSAGE(WM_MDINEXT), + DEFINE_MESSAGE(WM_MDIMAXIMIZE), + DEFINE_MESSAGE(WM_MDITILE), + DEFINE_MESSAGE(WM_MDICASCADE), + DEFINE_MESSAGE(WM_MDIICONARRANGE), + DEFINE_MESSAGE(WM_MDIGETACTIVE), + + + DEFINE_MESSAGE(WM_MDISETMENU), + DEFINE_MESSAGE(WM_ENTERSIZEMOVE), + DEFINE_MESSAGE(WM_EXITSIZEMOVE), + DEFINE_MESSAGE(WM_DROPFILES), + DEFINE_MESSAGE(WM_MDIREFRESHMENU), + +# if(WINVER >= 0x0602) + DEFINE_MESSAGE(WM_POINTERDEVICECHANGE), + DEFINE_MESSAGE(WM_POINTERDEVICEINRANGE), + DEFINE_MESSAGE(WM_POINTERDEVICEOUTOFRANGE), +# endif /* WINVER >= 0x0602 */ + +# if(WINVER >= 0x0601) + DEFINE_MESSAGE(WM_TOUCH), +# endif /* WINVER >= 0x0601 */ + +# if(WINVER >= 0x0602) + DEFINE_MESSAGE(WM_NCPOINTERUPDATE), + DEFINE_MESSAGE(WM_NCPOINTERDOWN), + DEFINE_MESSAGE(WM_NCPOINTERUP), + DEFINE_MESSAGE(WM_POINTERUPDATE), + DEFINE_MESSAGE(WM_POINTERDOWN), + DEFINE_MESSAGE(WM_POINTERUP), + DEFINE_MESSAGE(WM_POINTERENTER), + DEFINE_MESSAGE(WM_POINTERLEAVE), + DEFINE_MESSAGE(WM_POINTERACTIVATE), + DEFINE_MESSAGE(WM_POINTERCAPTURECHANGED), + DEFINE_MESSAGE(WM_TOUCHHITTESTING), + DEFINE_MESSAGE(WM_POINTERWHEEL), + DEFINE_MESSAGE(WM_POINTERHWHEEL), +# endif /* WINVER >= 0x0602 */ + + +# if(WINVER >= 0x0400) + DEFINE_MESSAGE(WM_IME_SETCONTEXT), + DEFINE_MESSAGE(WM_IME_NOTIFY), + DEFINE_MESSAGE(WM_IME_CONTROL), + DEFINE_MESSAGE(WM_IME_COMPOSITIONFULL), + DEFINE_MESSAGE(WM_IME_SELECT), + DEFINE_MESSAGE(WM_IME_CHAR), +# endif /* WINVER >= 0x0400 */ +# if(WINVER >= 0x0500) + DEFINE_MESSAGE(WM_IME_REQUEST), +# endif /* WINVER >= 0x0500 */ +# if(WINVER >= 0x0400) + DEFINE_MESSAGE(WM_IME_KEYDOWN), + DEFINE_MESSAGE(WM_IME_KEYUP), +# endif /* WINVER >= 0x0400 */ + +# if((_WIN32_WINNT >= 0x0400) || (WINVER >= 0x0500)) + DEFINE_MESSAGE(WM_MOUSEHOVER), + DEFINE_MESSAGE(WM_MOUSELEAVE), +# endif +# if(WINVER >= 0x0500) && defined(WM_NCMOUSEHOVER) + DEFINE_MESSAGE(WM_NCMOUSEHOVER), + DEFINE_MESSAGE(WM_NCMOUSELEAVE), +# endif /* WINVER >= 0x0500 */ + +# if(_WIN32_WINNT >= 0x0501) + DEFINE_MESSAGE(WM_WTSSESSION_CHANGE), +# endif /* _WIN32_WINNT >= 0x0501 */ + + DEFINE_MESSAGE(WM_CUT), + DEFINE_MESSAGE(WM_COPY), + DEFINE_MESSAGE(WM_PASTE), + DEFINE_MESSAGE(WM_CLEAR), + DEFINE_MESSAGE(WM_UNDO), + DEFINE_MESSAGE(WM_RENDERFORMAT), + DEFINE_MESSAGE(WM_RENDERALLFORMATS), + DEFINE_MESSAGE(WM_DESTROYCLIPBOARD), + DEFINE_MESSAGE(WM_DRAWCLIPBOARD), + DEFINE_MESSAGE(WM_PAINTCLIPBOARD), + DEFINE_MESSAGE(WM_VSCROLLCLIPBOARD), + DEFINE_MESSAGE(WM_SIZECLIPBOARD), + DEFINE_MESSAGE(WM_ASKCBFORMATNAME), + DEFINE_MESSAGE(WM_CHANGECBCHAIN), + DEFINE_MESSAGE(WM_HSCROLLCLIPBOARD), + DEFINE_MESSAGE(WM_QUERYNEWPALETTE), + DEFINE_MESSAGE(WM_PALETTEISCHANGING), + DEFINE_MESSAGE(WM_PALETTECHANGED), + DEFINE_MESSAGE(WM_HOTKEY), + +# if(WINVER >= 0x0400) + DEFINE_MESSAGE(WM_PRINT), + DEFINE_MESSAGE(WM_PRINTCLIENT), +# endif /* WINVER >= 0x0400 */ + +# if(_WIN32_WINNT >= 0x0500) && defined(WM_APPCOMMAND) + DEFINE_MESSAGE(WM_APPCOMMAND), +# endif /* _WIN32_WINNT >= 0x0500 */ + +# if(_WIN32_WINNT >= 0x0501) + DEFINE_MESSAGE(WM_THEMECHANGED), +# endif /* _WIN32_WINNT >= 0x0501 */ + + +# if(_WIN32_WINNT >= 0x0501) && defined(WM_CLIPBOARDUPDATE) + DEFINE_MESSAGE(WM_CLIPBOARDUPDATE), +# endif /* _WIN32_WINNT >= 0x0501 */ + +# if(_WIN32_WINNT >= 0x0600) + DEFINE_MESSAGE(WM_DWMCOMPOSITIONCHANGED), + DEFINE_MESSAGE(WM_DWMNCRENDERINGCHANGED), + DEFINE_MESSAGE(WM_DWMCOLORIZATIONCOLORCHANGED), + DEFINE_MESSAGE(WM_DWMWINDOWMAXIMIZEDCHANGE), +# endif /* _WIN32_WINNT >= 0x0600 */ + +# if(_WIN32_WINNT >= 0x0601) + DEFINE_MESSAGE(WM_DWMSENDICONICTHUMBNAIL), + DEFINE_MESSAGE(WM_DWMSENDICONICLIVEPREVIEWBITMAP), +# endif /* _WIN32_WINNT >= 0x0601 */ + + +# if(WINVER >= 0x0600) + DEFINE_MESSAGE(WM_GETTITLEBARINFOEX), +# endif /* WINVER >= 0x0600 */ + { 0, NULL, } /* end of message list */ +}; +#undef DEFINE_MESSAGE + +char* WMMsg2Str(DWORD dwMessage) +{ + struct WM_MESSAGE_MAP* pMapMsg = allMessages; + for (/*null*/; pMapMsg->lpszMsg != NULL; pMapMsg++) + { + if (pMapMsg->nMsg == dwMessage ) + { + return (char *)pMapMsg->lpszMsg; + } + } + return ""; +} +#endif /* _DEBUG */ + + +/* Get system time, taking special precautions against 32bit timer wrap. + We use timeGetTime and not GetTickCount because of its better stability, + and because we can increase its granularity (to 1 ms in + fgPlatformInitialize). For that reason we can't use GetTickCount64 which + wouldn't have the wrap issue. + Credit: this is based on code in glibc (https://mail.gnome.org/archives/commits-list/2011-November/msg04588.html) + */ +static fg_time_t lastTime32 = 0; +static fg_time_t timeEpoch = 0; +void fgPlatformInitSystemTime() +{ +#if defined(_WIN32_WCE) + lastTime32 = GetTickCount(); +#else + lastTime32 = timeGetTime(); +#endif +} +fg_time_t fgPlatformSystemTime ( void ) +{ + fg_time_t currTime32; +#if defined(_WIN32_WCE) + currTime32 = GetTickCount(); +#else + currTime32 = timeGetTime(); +#endif + /* Check if we just wrapped */ + if (currTime32 < lastTime32) + timeEpoch++; + + lastTime32 = currTime32; + + return currTime32 | timeEpoch << 32; +} + + +void fgPlatformSleepForEvents( fg_time_t msec ) +{ + MsgWaitForMultipleObjects( 0, NULL, FALSE, (DWORD) msec, QS_ALLINPUT ); +} + + +void fgPlatformProcessSingleEvent ( void ) +{ + MSG stMsg; + + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMainLoopEvent" ); + + while( PeekMessage( &stMsg, NULL, 0, 0, PM_NOREMOVE ) ) + { + if( GetMessage( &stMsg, NULL, 0, 0 ) == 0 ) + { + if( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT ) + { + fgDeinitialize( ); + exit( 0 ); + } + else if( fgState.ActionOnWindowClose == GLUT_ACTION_GLUTMAINLOOP_RETURNS ) + fgState.ExecState = GLUT_EXEC_STATE_STOP; + + return; + } + + TranslateMessage( &stMsg ); + DispatchMessage( &stMsg ); + } +} + + + +static void fghPlatformOnWindowStatusNotify(SFG_Window *window, GLboolean visState, GLboolean forceNotify) +{ + GLboolean notify = GL_FALSE; + SFG_Window* child; + + if (window->State.Visible != visState) + { + window->State.Visible = visState; + + /* If top level window (not a subwindow/child), and icon title text available, switch titles based on visibility state */ + if (!window->Parent && window->State.pWState.IconTitle) + { + if (visState) + /* visible, set window title */ + SetWindowText( window->Window.Handle, window->State.pWState.WindowTitle ); + else + /* not visible, set icon title */ + SetWindowText( window->Window.Handle, window->State.pWState.IconTitle ); + } + + notify = GL_TRUE; + } + + if (notify || forceNotify) + { + SFG_Window *saved_window = fgStructure.CurrentWindow; + + /* On win32 we only have two states, window displayed and window not displayed (iconified) + * We map these to GLUT_FULLY_RETAINED and GLUT_HIDDEN respectively. + */ + INVOKE_WCB( *window, WindowStatus, ( visState ? GLUT_FULLY_RETAINED:GLUT_HIDDEN ) ); + fgSetWindow( saved_window ); + } + + /* Also set windowStatus/visibility state for children */ + for( child = ( SFG_Window * )window->Children.First; + child; + child = ( SFG_Window * )child->Node.Next ) + { + fghPlatformOnWindowStatusNotify(child, visState, GL_FALSE); /* No need to propagate forceNotify. Childs get this from their own INIT_WORK */ + } +} + +void fgPlatformMainLoopPreliminaryWork ( void ) +{ + /* no-op */ +} + + +/* + * Determine a GLUT modifier mask based on MS-WINDOWS system info. + */ +static int fgPlatformGetModifiers (void) +{ + return + ( ( ( GetKeyState( VK_LSHIFT ) < 0 ) || + ( GetKeyState( VK_RSHIFT ) < 0 )) ? GLUT_ACTIVE_SHIFT : 0 ) | + ( ( ( GetKeyState( VK_LCONTROL ) < 0 ) || + ( GetKeyState( VK_RCONTROL ) < 0 )) ? GLUT_ACTIVE_CTRL : 0 ) | + ( ( ( GetKeyState( VK_LMENU ) < 0 ) || + ( GetKeyState( VK_RMENU ) < 0 )) ? GLUT_ACTIVE_ALT : 0 ) | + ( ( ( GetKeyState( VK_LWIN ) < 0 ) || + ( GetKeyState( VK_RWIN ) < 0 )) ? GLUT_ACTIVE_SUPER : 0 ); +} + +/* Check whether a button (VK_*BUTTON) is currently depressed. Returns + * non-zero (not necessarily 1) if yes. */ +static SHORT fgGetKeyState(int vKey) +{ + /* MSDN says: "If the high-order bit is 1, the key is down; otherwise, it is up". */ + return GetKeyState(vKey) & 0xFF00; +} + +static LRESULT fghWindowProcKeyPress(SFG_Window *window, UINT uMsg, GLboolean keydown, WPARAM wParam, LPARAM lParam) +{ + static unsigned char lControl = 0, lShift = 0, lAlt = 0, + rControl = 0, rShift = 0, rAlt = 0; + + int keypress = -1; + + /* if keydown, check for repeat */ + /* If repeat is globally switched off, it cannot be switched back on per window. + * But if it is globally switched on, it can be switched off per window. This matches + * GLUT's behavior on X11, but not Nate Robbins' win32 GLUT, as he didn't implement the + * global state switch. + */ + if( keydown && ( fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE ) && (HIWORD(lParam) & KF_REPEAT) ) + return 1; + + /* Remember the current modifiers state so user can query it from their callback */ + fgState.Modifiers = fgPlatformGetModifiers( ); + + /* Convert the Win32 keystroke codes to GLUTtish way */ +# define FG_KEY(a,b) case a: keypress = b; break; + + switch( wParam ) + { + FG_KEY( VK_F1, GLUT_KEY_F1 ); + FG_KEY( VK_F2, GLUT_KEY_F2 ); + FG_KEY( VK_F3, GLUT_KEY_F3 ); + FG_KEY( VK_F4, GLUT_KEY_F4 ); + FG_KEY( VK_F5, GLUT_KEY_F5 ); + FG_KEY( VK_F6, GLUT_KEY_F6 ); + FG_KEY( VK_F7, GLUT_KEY_F7 ); + FG_KEY( VK_F8, GLUT_KEY_F8 ); + FG_KEY( VK_F9, GLUT_KEY_F9 ); + FG_KEY( VK_F10, GLUT_KEY_F10 ); + FG_KEY( VK_F11, GLUT_KEY_F11 ); + FG_KEY( VK_F12, GLUT_KEY_F12 ); + FG_KEY( VK_PRIOR, GLUT_KEY_PAGE_UP ); + FG_KEY( VK_NEXT, GLUT_KEY_PAGE_DOWN ); + FG_KEY( VK_HOME, GLUT_KEY_HOME ); + FG_KEY( VK_END, GLUT_KEY_END ); + FG_KEY( VK_LEFT, GLUT_KEY_LEFT ); + FG_KEY( VK_UP, GLUT_KEY_UP ); + FG_KEY( VK_RIGHT, GLUT_KEY_RIGHT ); + FG_KEY( VK_DOWN, GLUT_KEY_DOWN ); + FG_KEY( VK_INSERT, GLUT_KEY_INSERT ); + FG_KEY( VK_LWIN, GLUT_KEY_SUPER_L ); + FG_KEY( VK_RWIN, GLUT_KEY_SUPER_R ); + + /* handle control, alt and shift. For GLUT, we want to distinguish between left and right presses. + * The VK_L* & VK_R* left and right Alt, Ctrl and Shift virtual keys are however only used as parameters to GetAsyncKeyState() and GetKeyState() + * so when we get an alt, shift or control keypress here, we manually check whether it was the left or the right + */ +#define FG_KEY_EVENT(winKey,glutKey,keyStateVar)\ + if (!keyStateVar && fgGetKeyState ( winKey ))\ + {\ + keypress = glutKey;\ + keyStateVar = 1;\ + }\ + else if (keyStateVar && !fgGetKeyState ( winKey ))\ + {\ + keypress = glutKey;\ + keyStateVar = 0;\ + } + case VK_CONTROL: + FG_KEY_EVENT(VK_LCONTROL,GLUT_KEY_CTRL_L,lControl); + FG_KEY_EVENT(VK_RCONTROL,GLUT_KEY_CTRL_R,rControl); + break; + case VK_SHIFT: + FG_KEY_EVENT(VK_LSHIFT,GLUT_KEY_SHIFT_L,lShift); + FG_KEY_EVENT(VK_RSHIFT,GLUT_KEY_SHIFT_R,rShift); + break; + case VK_MENU: + FG_KEY_EVENT(VK_LMENU,GLUT_KEY_ALT_L,lAlt); + FG_KEY_EVENT(VK_RMENU,GLUT_KEY_ALT_R,rAlt); + break; +#undef KEY_EVENT + + case VK_DELETE: + /* The delete key should be treated as an ASCII keypress: */ + if (keydown) + INVOKE_WCB( *window, Keyboard, + ( 127, window->State.MouseX, window->State.MouseY ) + ); + else + INVOKE_WCB( *window, KeyboardUp, + ( 127, window->State.MouseX, window->State.MouseY ) + ); + break; + +#if !defined(_WIN32_WCE) + default: + /* keydown displayable characters are handled with WM_CHAR message, but no corresponding up is generated. So get that here. */ + if (!keydown) + { + BYTE state[ 256 ]; + WORD code[ 2 ]; + + GetKeyboardState( state ); + + if( ToAscii( (UINT)wParam, 0, state, code, 0 ) == 1 ) + wParam=code[ 0 ]; + + INVOKE_WCB( *window, KeyboardUp, + ( (char)(wParam & 0xFF), /* and with 0xFF to indicate to runtime that we want to strip out higher bits - otherwise we get a runtime error when "Smaller Type Checks" is enabled */ + window->State.MouseX, window->State.MouseY ) + ); + } +#endif + } + +#if defined(_WIN32_WCE) + if(keydown && !(lParam & 0x40000000)) /* Prevent auto-repeat */ + { + if(wParam==(unsigned)gxKeyList.vkRight) + keypress = GLUT_KEY_RIGHT; + else if(wParam==(unsigned)gxKeyList.vkLeft) + keypress = GLUT_KEY_LEFT; + else if(wParam==(unsigned)gxKeyList.vkUp) + keypress = GLUT_KEY_UP; + else if(wParam==(unsigned)gxKeyList.vkDown) + keypress = GLUT_KEY_DOWN; + else if(wParam==(unsigned)gxKeyList.vkA) + keypress = GLUT_KEY_F1; + else if(wParam==(unsigned)gxKeyList.vkB) + keypress = GLUT_KEY_F2; + else if(wParam==(unsigned)gxKeyList.vkC) + keypress = GLUT_KEY_F3; + else if(wParam==(unsigned)gxKeyList.vkStart) + keypress = GLUT_KEY_F4; + } +#endif + + if(keypress != -1) { + if(keydown) { + INVOKE_WCB(*window, Special, + (keypress, window->State.MouseX, window->State.MouseY)); + } else { + INVOKE_WCB(*window, SpecialUp, + (keypress, window->State.MouseX, window->State.MouseY)); + } + } + + fgState.Modifiers = INVALID_MODIFIERS; + + /* SYSKEY events should be sent to default window proc for system to handle them */ + if (uMsg==WM_SYSKEYDOWN || uMsg==WM_SYSKEYUP) + return DefWindowProc( window->Window.Handle, uMsg, wParam, lParam ); + else + return 1; +} + +SFG_Window* fghWindowUnderCursor(SFG_Window *window) +{ + /* Check if the current window that the mouse is over is a child window + * of the window the message was sent to. Some events only sent to main window, + * and when handling some messages, we need to make sure that we process + * callbacks on the child window instead. This mirrors how GLUT does things. + * returns either the original window or the found child. + */ + if (window && window->Children.First) /* This window has childs */ + { + HWND hwnd; + SFG_Window* child_window; + + /* Get mouse position at time of message */ + DWORD mouse_pos_dw = GetMessagePos(); + POINT mouse_pos; + mouse_pos.x = GET_X_LPARAM(mouse_pos_dw); + mouse_pos.y = GET_Y_LPARAM(mouse_pos_dw); + ScreenToClient( window->Window.Handle, &mouse_pos ); + + hwnd = ChildWindowFromPoint(window->Window.Handle, mouse_pos); + if (hwnd && hwnd!=window->Window.Handle) /* can be NULL if mouse outside parent by the time we get here, or can be same as parent if we didn't find a child */ + { + child_window = fgWindowByHandle(hwnd); + if (child_window) /* Verify we got a FreeGLUT window */ + { + /* ChildWindowFromPoint only searches immediate children, so search again to see if actually in grandchild or further descendant */ + window = fghWindowUnderCursor(child_window); + } + } + } + + return window; +} + +/* + * The window procedure for handling Win32 events + */ +LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + SFG_Window *window; + LRESULT lRet = 1; + static int setCaptureActive = 0; + + FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED ( "Event Handler" ) ; + + window = fgWindowByHandle( hWnd ); + + if ( ( window == NULL ) && ( uMsg != WM_CREATE ) ) + return DefWindowProc( hWnd, uMsg, wParam, lParam ); + + /* printf ( "Window %3d message %s (<%04x>) %12d %12d\n", window?window->ID:0, + WMMsg2Str(uMsg), uMsg, wParam, lParam ); */ + + switch( uMsg ) + { + case WM_CREATE: + /* The window structure is passed as the creation structure parameter... */ + window = (SFG_Window *) (((LPCREATESTRUCT) lParam)->lpCreateParams); + FREEGLUT_INTERNAL_ERROR_EXIT ( ( window != NULL ), "Cannot create window", + "fgPlatformWindowProc" ); + + window->Window.Handle = hWnd; + window->Window.pContext.Device = GetDC( hWnd ); + if( window->IsMenu ) + { + unsigned int current_DisplayMode = fgState.DisplayMode; + fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH; +#if !defined(_WIN32_WCE) + fgSetupPixelFormat( window, GL_FALSE, PFD_MAIN_PLANE ); +#endif + fgState.DisplayMode = current_DisplayMode; + + if( fgStructure.MenuContext ) + wglMakeCurrent( window->Window.pContext.Device, + fgStructure.MenuContext->MContext + ); + else + { + fgStructure.MenuContext = + (SFG_MenuContext *)malloc( sizeof(SFG_MenuContext) ); + fgStructure.MenuContext->MContext = + wglCreateContext( window->Window.pContext.Device ); + } + + /* window->Window.Context = wglGetCurrentContext (); */ + window->Window.Context = wglCreateContext( window->Window.pContext.Device ); + } + else + { +#if !defined(_WIN32_WCE) + fgSetupPixelFormat( window, GL_FALSE, PFD_MAIN_PLANE ); +#endif + + if( ! fgState.UseCurrentContext ) + window->Window.Context = + wglCreateContext( window->Window.pContext.Device ); + else + { + window->Window.Context = wglGetCurrentContext( ); + if( ! window->Window.Context ) + window->Window.Context = + wglCreateContext( window->Window.pContext.Device ); + } + +#if !defined(_WIN32_WCE) + fgNewWGLCreateContext( window ); +#endif + } + + ReleaseDC( window->Window.Handle, window->Window.pContext.Device ); + +#if defined(_WIN32_WCE) + /* Take over button handling */ + { + HINSTANCE dxDllLib=LoadLibrary(_T("gx.dll")); + if (dxDllLib) + { + GXGetDefaultKeys_=(GXGETDEFAULTKEYS)GetProcAddress(dxDllLib, _T("?GXGetDefaultKeys@@YA?AUGXKeyList@@H@Z")); + GXOpenInput_=(GXOPENINPUT)GetProcAddress(dxDllLib, _T("?GXOpenInput@@YAHXZ")); + } + + if(GXOpenInput_) + (*GXOpenInput_)(); + if(GXGetDefaultKeys_) + gxKeyList = (*GXGetDefaultKeys_)(GX_LANDSCAPEKEYS); + } + +#endif /* defined(_WIN32_WCE) */ + break; + + case WM_SIZE: + /* printf("WM_SIZE (ID: %i): wParam: %i, new size: %ix%i \n",window->ID,wParam,LOWORD(lParam),HIWORD(lParam)); */ + + /* Update visibility state of the window */ + if (wParam==SIZE_MINIMIZED) + fghPlatformOnWindowStatusNotify(window,GL_FALSE,GL_FALSE); + else if ((wParam==SIZE_RESTORED || wParam == SIZE_MAXIMIZED) && !window->State.Visible) + fghPlatformOnWindowStatusNotify(window,GL_TRUE,GL_FALSE); + + /* Check window visible, we don't want do anything when we get a WM_SIZE because the user or glutIconifyWindow minimized the window */ + if( window->State.Visible ) + { + int width, height; +#if defined(_WIN32_WCE) + width = HIWORD(lParam); + height = LOWORD(lParam); +#else + width = LOWORD(lParam); + height = HIWORD(lParam); +#endif /* defined(_WIN32_WCE) */ + + /* Update state and call callback, if there was a change */ + fghOnReshapeNotify(window, width, height, GL_FALSE); + } + + /* according to docs, should return 0 */ + lRet = 0; + break; + + case WM_SIZING: + { + /* User resize-dragging the window, call reshape callback and + * force redisplay so display keeps running during dragging. + * Screen still wont update when not moving the cursor though... + */ + RECT rect; + /* PRECT prect = (PRECT) lParam; + printf("WM_SIZING: nc-area: %i,%i\n",prect->right-prect->left,prect->bottom-prect->top); */ + /* Get client area, the rect in lParam is including non-client area. */ + fghGetClientArea(&rect,window,FALSE); + + /* We'll get a WM_SIZE as well, but as state has + * already been updated here, the fghOnReshapeNotify + * in the handler for that message doesn't do anything. + */ + fghOnReshapeNotify(window, rect.right-rect.left, rect.bottom-rect.top, GL_FALSE); + + /* Now directly call the drawing function to update + * window and window's childs. + * This mimics the WM_PAINT messages that are received during + * resizing. Note that we don't have a WM_MOVING handler + * as move-dragging doesn't generate WM_MOVE or WM_PAINT + * messages until the mouse is released. + */ + fghRedrawWindowAndChildren(window); + } + + /* according to docs, should return TRUE */ + lRet = TRUE; + break; + + case WM_MOVE: + { + /* Check window is minimized, we don't want to call the position callback when the user or glutIconifyWindow minimized the window */ + if (!IsIconic(window->Window.Handle)) + { + RECT windowRect; + + /* lParam contains coordinates of top-left of client area. + * Get top-left of non-client area of window, matching coordinates of + * glutInitPosition and glutPositionWindow, but not those of + * glutGet(GLUT_WINDOW_X) and glutGet(GLUT_WINDOW_Y), which return + * top-left of client area. + */ + GetWindowRect( window->Window.Handle, &windowRect ); + + if (window->Parent) + { + /* For child window, we should return relative to upper-left + * of parent's client area. + */ + POINT topleft; + topleft.x = windowRect.left; + topleft.y = windowRect.top; + + ScreenToClient(window->Parent->Window.Handle,&topleft); + windowRect.left = topleft.x; + windowRect.top = topleft.y; + } + + /* Update state and call callback, if there was a change */ + fghOnPositionNotify(window, windowRect.left, windowRect.top, GL_FALSE); + } + } + + /* according to docs, should return 0 */ + lRet = 0; + break; + + case WM_SETFOCUS: + /*printf("WM_SETFOCUS: %p\n", window );*/ + lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); + + SetActiveWindow( window->Window.Handle ); + UpdateWindow ( hWnd ); + + break; + + case WM_KILLFOCUS: + /*printf("WM_KILLFOCUS: %p\n", window ); */ + lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); + + /* Check if there are any open menus that need to be closed */ + fgPlatformCheckMenuDeactivate((HWND)wParam); + break; + + case WM_MOUSEACTIVATE: + /* Clicks should not activate the menu. + * Especially important when clicking on a menu's submenu item which has no effect. + */ + /*printf("WM_MOUSEACTIVATE\n");*/ + if (window->IsMenu) + lRet = MA_NOACTIVATEANDEAT; + else + lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); + break; + + case WM_NCLBUTTONDOWN: + case WM_NCMBUTTONDOWN: + case WM_NCRBUTTONDOWN: + { + SFG_Menu *menu; + if (fgState.ActiveMenus && (menu = fgGetActiveMenu())) + /* user clicked non-client area of window while a menu is open. Close menu */ + fgDeactivateMenu(menu->ParentWindow); + + /* and always pass to DefWindowProc */ + lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); + } + break; + +#if 0 + case WM_ACTIVATE: + /* printf("WM_ACTIVATE: %x (ID: %i) %d %d\n",lParam, window->ID, HIWORD(wParam), LOWORD(wParam)); */ + if (LOWORD(wParam) != WA_INACTIVE) + { +/* printf("WM_ACTIVATE: fgSetCursor( %p, %d)\n", window, + window->State.Cursor ); */ + fgSetCursor( window, window->State.Cursor ); + } + + lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); + break; +#endif + + case WM_SETCURSOR: +/* printf ( "Cursor event %x %x %x %x\n", window, window->State.Cursor, lParam, wParam ) ; */ + if( LOWORD( lParam ) == HTCLIENT ) + { + if (!window->State.pWState.MouseTracking) + { + TRACKMOUSEEVENT tme; + + /* Cursor just entered window, set cursor look */ + fgSetCursor ( window, window->State.Cursor ) ; + + /* If an EntryFunc callback is specified by the user, also + * invoke that callback and start mouse tracking so that + * we get a WM_MOUSELEAVE message + */ + if (FETCH_WCB( *window, Entry )) + { + SFG_Window* saved_window = fgStructure.CurrentWindow; + INVOKE_WCB( *window, Entry, ( GLUT_ENTERED ) ); + fgSetWindow(saved_window); + + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = window->Window.Handle; + TrackMouseEvent(&tme); + + window->State.pWState.MouseTracking = TRUE; + } + } + } + else + /* Only pass non-client WM_SETCURSOR to DefWindowProc, or we get WM_SETCURSOR on parents of children as well */ + lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); + break; + + case WM_MOUSELEAVE: + { + /* NB: This message is only received when a EntryFunc callback + * is specified by the user, as that is the only condition under + * which mouse tracking is setup in WM_SETCURSOR handler above + */ + SFG_Window* saved_window = fgStructure.CurrentWindow; + INVOKE_WCB( *window, Entry, ( GLUT_LEFT ) ); + fgSetWindow(saved_window); + + window->State.pWState.MouseTracking = FALSE; + lRet = 0; /* As per docs, must return zero */ + } + break; + + case WM_SHOWWINDOW: + /* printf("WM_SHOWWINDOW, shown? %i, source: %i\n",wParam,lParam); */ + if (wParam) + { + fghPlatformOnWindowStatusNotify(window, GL_TRUE, GL_FALSE); + window->State.WorkMask |= GLUT_DISPLAY_WORK; + } + else + { + fghPlatformOnWindowStatusNotify(window, GL_FALSE, GL_FALSE); + window->State.WorkMask &= ~GLUT_DISPLAY_WORK; + } + break; + + case WM_PAINT: + { + RECT rect; + + /* As per docs, upon receiving WM_PAINT, first check if the update region is not empty before you call BeginPaint */ + if (GetUpdateRect(hWnd,&rect,FALSE)) + { + /* Dummy begin/end paint to validate rect that needs + * redrawing, then signal that a redisplay is needed. + * This allows us full control about when we do any + * redrawing, and is the same as what original GLUT + * does. + */ + PAINTSTRUCT ps; + BeginPaint( hWnd, &ps ); + EndPaint( hWnd, &ps ); + + window->State.WorkMask |= GLUT_DISPLAY_WORK; + } + lRet = 0; /* As per docs, should return 0 */ + } + break; + + case WM_CLOSE: + fgDestroyWindow ( window ); + if ( fgState.ActionOnWindowClose != GLUT_ACTION_CONTINUE_EXECUTION ) + PostQuitMessage(0); + break; + + case WM_DESTROY: + /* + * The window already got destroyed, so don't bother with it. + */ + return 0; + + case WM_MOUSEMOVE: + { + /* Per docs, use LOWORD/HIWORD for WinCE and GET_X_LPARAM/GET_Y_LPARAM for desktop windows */ +#if defined(_WIN32_WCE) + window->State.MouseX = 320-HIWORD( lParam ); /* XXX: Docs say x should be loword and y hiword? */ + window->State.MouseY = LOWORD( lParam ); +#else + window->State.MouseX = GET_X_LPARAM( lParam ); + window->State.MouseY = GET_Y_LPARAM( lParam ); +#endif /* defined(_WIN32_WCE) */ + /* Restrict to [-32768, 32767] to match X11 behaviour */ + /* See comment in "freeglut_developer" mailing list 10/4/04 */ + if ( window->State.MouseX > 32767 ) window->State.MouseX -= 65536; + if ( window->State.MouseY > 32767 ) window->State.MouseY -= 65536; + + if ( window->ActiveMenu ) + { + fgUpdateMenuHighlight( window->ActiveMenu ); + break; + } + + fgState.Modifiers = fgPlatformGetModifiers( ); + + if( ( wParam & MK_LBUTTON ) || + ( wParam & MK_MBUTTON ) || + ( wParam & MK_RBUTTON ) ) + INVOKE_WCB( *window, Motion, ( window->State.MouseX, + window->State.MouseY ) ); + else + INVOKE_WCB( *window, Passive, ( window->State.MouseX, + window->State.MouseY ) ); + + fgState.Modifiers = INVALID_MODIFIERS; + } + break; + + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + { + GLboolean pressed = GL_TRUE; + int button; + + /* Per docs, use LOWORD/HIWORD for WinCE and GET_X_LPARAM/GET_Y_LPARAM for desktop windows */ +#if defined(_WIN32_WCE) + window->State.MouseX = 320-HIWORD( lParam ); /* XXX: Docs say x should be loword and y hiword? */ + window->State.MouseY = LOWORD( lParam ); +#else + window->State.MouseX = GET_X_LPARAM( lParam ); + window->State.MouseY = GET_Y_LPARAM( lParam ); +#endif /* defined(_WIN32_WCE) */ + + /* Restrict to [-32768, 32767] to match X11 behaviour */ + /* See comment in "freeglut_developer" mailing list 10/4/04 */ + if ( window->State.MouseX > 32767 ) window->State.MouseX -= 65536; + if ( window->State.MouseY > 32767 ) window->State.MouseY -= 65536; + + switch( uMsg ) + { + case WM_LBUTTONDOWN: + pressed = GL_TRUE; + button = GLUT_LEFT_BUTTON; + break; + case WM_MBUTTONDOWN: + pressed = GL_TRUE; + button = GLUT_MIDDLE_BUTTON; + break; + case WM_RBUTTONDOWN: + pressed = GL_TRUE; + button = GLUT_RIGHT_BUTTON; + break; + case WM_LBUTTONUP: + pressed = GL_FALSE; + button = GLUT_LEFT_BUTTON; + break; + case WM_MBUTTONUP: + pressed = GL_FALSE; + button = GLUT_MIDDLE_BUTTON; + break; + case WM_RBUTTONUP: + pressed = GL_FALSE; + button = GLUT_RIGHT_BUTTON; + break; + default: + pressed = GL_FALSE; + button = -1; + break; + } + +#if !defined(_WIN32_WCE) + if( GetSystemMetrics( SM_SWAPBUTTON ) ) + { + if( button == GLUT_LEFT_BUTTON ) + button = GLUT_RIGHT_BUTTON; + else + if( button == GLUT_RIGHT_BUTTON ) + button = GLUT_LEFT_BUTTON; + } +#endif /* !defined(_WIN32_WCE) */ + + if( button == -1 ) + return DefWindowProc( hWnd, uMsg, lParam, wParam ); + + /* + * Do not execute the application's mouse callback if a menu + * is hooked to this button. In that case an appropriate + * private call should be generated. + */ + if( fgCheckActiveMenu( window, button, pressed, + window->State.MouseX, window->State.MouseY ) ) + break; + + /* Set capture so that the window captures all the mouse messages + * + * The mouse is not released from the window until all buttons have + * been released, even if the user presses a button in another window. + * This is consistent with the behavior on X11. + */ + if ( pressed == GL_TRUE ) + { + if (!setCaptureActive) + SetCapture ( window->Window.Handle ) ; + setCaptureActive = 1; /* Set to false in WM_CAPTURECHANGED handler */ + } + else if (!fgGetKeyState(VK_LBUTTON) && !fgGetKeyState(VK_MBUTTON) && !fgGetKeyState(VK_RBUTTON)) + /* Make sure all mouse buttons are released before releasing capture */ + ReleaseCapture () ; + + if( ! FETCH_WCB( *window, Mouse ) ) + break; + + fgSetWindow( window ); + fgState.Modifiers = fgPlatformGetModifiers( ); + + INVOKE_WCB( + *window, Mouse, + ( button, + pressed ? GLUT_DOWN : GLUT_UP, + window->State.MouseX, + window->State.MouseY + ) + ); + + fgState.Modifiers = INVALID_MODIFIERS; + + /* As per docs, should return zero */ + lRet = 0; + } + break; + + case WM_MOUSEWHEEL: + { + int wheel_number = 0; /* Only one scroll wheel on windows */ +#if defined(_WIN32_WCE) + int modkeys = LOWORD(wParam); + short ticks = (short)HIWORD(wParam); + /* commented out as should not be needed here, mouse motion is processed in WM_MOUSEMOVE first: + xPos = LOWORD(lParam); -- straight from docs, not consistent with mouse nutton and mouse motion above (which i think is wrong) + yPos = HIWORD(lParam); + */ +#else + /* int modkeys = GET_KEYSTATE_WPARAM( wParam ); */ + short ticks = HIWORD( wParam ); + /* commented out as should not be needed here, mouse motion is processed in WM_MOUSEMOVE first: + window->State.MouseX = GET_X_LPARAM( lParam ); + window->State.MouseY = GET_Y_LPARAM( lParam ); + */ +#endif /* defined(_WIN32_WCE) */ + + window = fghWindowUnderCursor(window); + + fgState.MouseWheelTicks += ticks; + if ( abs ( fgState.MouseWheelTicks ) >= WHEEL_DELTA ) + { + int direction = ( fgState.MouseWheelTicks > 0 ) ? 1 : -1; + + if( ! FETCH_WCB( *window, MouseWheel ) && + ! FETCH_WCB( *window, Mouse ) ) + break; + + fgSetWindow( window ); + fgState.Modifiers = fgPlatformGetModifiers( ); + + while( abs ( fgState.MouseWheelTicks ) >= WHEEL_DELTA ) + { + if( FETCH_WCB( *window, MouseWheel ) ) + INVOKE_WCB( *window, MouseWheel, + ( wheel_number, + direction, + window->State.MouseX, + window->State.MouseY + ) + ); + else /* No mouse wheel, call the mouse button callback twice */ + { + /* + * Map wheel zero to button 3 and 4; +1 to 3, -1 to 4 + * " " one +1 to 5, -1 to 6, ... + * + * XXX The below assumes that you have no more than 3 mouse + * XXX buttons. Sorry. + */ + int button = wheel_number * 2 + 3; + if( direction < 0 ) + ++button; + INVOKE_WCB( *window, Mouse, + ( button, GLUT_DOWN, + window->State.MouseX, window->State.MouseY ) + ); + INVOKE_WCB( *window, Mouse, + ( button, GLUT_UP, + window->State.MouseX, window->State.MouseY ) + ); + } + + fgState.MouseWheelTicks -= WHEEL_DELTA * direction; + } + + fgState.Modifiers = INVALID_MODIFIERS; + } + /* Per docs, should return zero */ + lRet = 0; + } + break ; + + case WM_SYSKEYDOWN: + case WM_KEYDOWN: + { + window = fghWindowUnderCursor(window); + lRet = fghWindowProcKeyPress(window,uMsg,GL_TRUE,wParam,lParam); + } + break; + + case WM_SYSKEYUP: + case WM_KEYUP: + { + window = fghWindowUnderCursor(window); + lRet = fghWindowProcKeyPress(window,uMsg,GL_FALSE,wParam,lParam); + } + break; + + case WM_SYSCHAR: + case WM_CHAR: + { + window = fghWindowUnderCursor(window); + + if( (fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE) && (HIWORD(lParam) & KF_REPEAT) ) + break; + + fgState.Modifiers = fgPlatformGetModifiers( ); + INVOKE_WCB( *window, Keyboard, + ( (char)wParam, + window->State.MouseX, window->State.MouseY ) + ); + fgState.Modifiers = INVALID_MODIFIERS; + } + break; + + case WM_CAPTURECHANGED: + if (!lParam || !fgWindowByHandle((HWND)lParam)) + /* Capture released or capture taken by non-FreeGLUT window */ + setCaptureActive = 0; + /* Docs advise a redraw */ + InvalidateRect( hWnd, NULL, GL_FALSE ); + UpdateWindow(hWnd); + lRet = 0; /* Per docs, should return zero */ + break; + +#if !defined(_WIN32_WCE) + case WM_SYNCPAINT: /* 0x0088 */ + /* Another window has moved, need to update this one */ + window->State.WorkMask |= GLUT_DISPLAY_WORK; + lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); + /* Help screen says this message must be passed to "DefWindowProc" */ + break; + + case WM_DISPLAYCHANGE: /* 0x007E */ + /* The system display resolution/depth has changed */ + fgDisplay.ScreenWidth = LOWORD(lParam); + fgDisplay.ScreenHeight = HIWORD(lParam); + break; + + case WM_SYSCOMMAND : /* 0x0112 */ + { + /* + * We have received a system command message. Try to act on it. + * The commands are passed in through the "wParam" parameter: + * The least significant digit seems to be which edge of the window + * is being used for a resize event: + * 4 3 5 + * 1 2 + * 7 6 8 + * Congratulations and thanks to Richard Rauch for figuring this out.. + */ + switch ( wParam & 0xfff0 ) + { + case SC_SIZE : + break ; + + case SC_MOVE : + break ; + + case SC_MINIMIZE : + /* User has clicked on the "-" to minimize the window */ + /* Turning off the visibility is handled in WM_SIZE handler */ + + break ; + + case SC_MAXIMIZE : + break ; + + case SC_NEXTWINDOW : + break ; + + case SC_PREVWINDOW : + break ; + + case SC_CLOSE : + /* Followed very closely by a WM_CLOSE message */ + break ; + + case SC_VSCROLL : + break ; + + case SC_HSCROLL : + break ; + + case SC_MOUSEMENU : + break ; + + case SC_KEYMENU : + break ; + + case SC_ARRANGE : + break ; + + case SC_RESTORE : + break ; + + case SC_TASKLIST : + break ; + + case SC_SCREENSAVE : + break ; + + case SC_HOTKEY : + break ; + +#if(WINVER >= 0x0400) + case SC_DEFAULT : + break ; + + case SC_MONITORPOWER : + break ; + + case SC_CONTEXTHELP : + break ; +#endif /* WINVER >= 0x0400 */ + + default: +#if _DEBUG + fgWarning( "Unknown wParam type 0x%x", wParam ); +#endif + break; + } + } +#endif /* !defined(_WIN32_WCE) */ + + /* We need to pass the message on to the operating system as well */ + lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); + break; + +#ifdef WM_TOUCH + /* handle multi-touch messages */ + case WM_TOUCH: + { + unsigned int numInputs = (unsigned int)wParam; + unsigned int i = 0; + TOUCHINPUT* ti = (TOUCHINPUT*)malloc( sizeof(TOUCHINPUT)*numInputs); + + if (fghGetTouchInputInfo == (pGetTouchInputInfo)0xDEADBEEF) { + fghGetTouchInputInfo = (pGetTouchInputInfo)GetProcAddress(GetModuleHandle("user32"),"GetTouchInputInfo"); + fghCloseTouchInputHandle = (pCloseTouchInputHandle)GetProcAddress(GetModuleHandle("user32"),"CloseTouchInputHandle"); + } + + if (!fghGetTouchInputInfo) { + free( (void*)ti ); + break; + } + + if (fghGetTouchInputInfo( (HTOUCHINPUT)lParam, numInputs, ti, sizeof(TOUCHINPUT) )) { + /* Handle each contact point */ + for (i = 0; i < numInputs; ++i ) { + + POINT tp; + tp.x = TOUCH_COORD_TO_PIXEL(ti[i].x); + tp.y = TOUCH_COORD_TO_PIXEL(ti[i].y); + ScreenToClient( hWnd, &tp ); + + ti[i].dwID = ti[i].dwID * 2; + + if (ti[i].dwFlags & TOUCHEVENTF_DOWN) { + INVOKE_WCB( *window, MultiEntry, ( ti[i].dwID, GLUT_ENTERED ) ); + INVOKE_WCB( *window, MultiButton, ( ti[i].dwID, tp.x, tp.y, 0, GLUT_DOWN ) ); + } else if (ti[i].dwFlags & TOUCHEVENTF_MOVE) { + INVOKE_WCB( *window, MultiMotion, ( ti[i].dwID, tp.x, tp.y ) ); + } else if (ti[i].dwFlags & TOUCHEVENTF_UP) { + INVOKE_WCB( *window, MultiButton, ( ti[i].dwID, tp.x, tp.y, 0, GLUT_UP ) ); + INVOKE_WCB( *window, MultiEntry, ( ti[i].dwID, GLUT_LEFT ) ); + } + } + } + fghCloseTouchInputHandle((HTOUCHINPUT)lParam); + free( (void*)ti ); + lRet = 0; /*DefWindowProc( hWnd, uMsg, wParam, lParam );*/ + break; + } +#endif + +#ifdef WM_INPUT + case WM_INPUT: + /* Added by Jinrong Xie for SpaceNavigator support on Windows. Dec 2014 */ + if (fgHasSpaceball()) + { + fgSpaceballHandleWinEvent(hWnd, wParam, lParam); + } + break; +#endif + default: + /* Handle unhandled messages */ + lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); + break; + } + + return lRet; +} + + +/* deal with work list items */ +void fgPlatformInitWork(SFG_Window* window) +{ + RECT windowRect; + + /* Notify windowStatus/visibility */ + fghPlatformOnWindowStatusNotify(window, window->State.Visible, GL_TRUE); + + /* get and notify window's position */ + GetWindowRect(window->Window.Handle,&windowRect); + fghOnPositionNotify(window, windowRect.left, windowRect.top, GL_TRUE); + + /* get and notify window's size */ + GetClientRect(window->Window.Handle,&windowRect); + fghOnReshapeNotify(window, windowRect.right-windowRect.left, windowRect.bottom-windowRect.top, GL_TRUE); +} + +/* On windows we can position, resize and change z order at the same time */ +void fgPlatformPosResZordWork(SFG_Window* window, unsigned int workMask) +{ + UINT flags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOZORDER; + HWND insertAfter = HWND_TOP; + RECT clientRect; + +#if !defined(_WIN32_WCE) /* FIXME: what about WinCE */ + if (workMask & GLUT_FULL_SCREEN_WORK) + { + /* This asks us to toggle fullscreen mode */ + flags |= SWP_FRAMECHANGED; + + if (window->State.IsFullscreen) + { + /* If we are fullscreen, resize the current window back to its original size */ + /* printf("OldRect %i,%i to %i,%i\n",window->State.pWState.OldRect.left,window->State.pWState.OldRect.top,window->State.pWState.OldRect.right,window->State.pWState.OldRect.bottom); */ + + /* restore style of window before making it fullscreen */ + SetWindowLong(window->Window.Handle, GWL_STYLE, window->State.pWState.OldStyle); + SetWindowLong(window->Window.Handle, GWL_EXSTYLE, window->State.pWState.OldStyleEx); + + /* Then set up resize/reposition, unless user already queued up reshape/position work */ + if (!(workMask & GLUT_POSITION_WORK)) + { + workMask |= GLUT_POSITION_WORK; + window->State.DesiredXpos = window->State.pWState.OldRect.left; + window->State.DesiredYpos = window->State.pWState.OldRect.top; + } + if (!(workMask & GLUT_SIZE_WORK)) + { + workMask |= GLUT_SIZE_WORK; + window->State.DesiredWidth = window->State.pWState.OldRect.right - window->State.pWState.OldRect.left; + window->State.DesiredHeight = window->State.pWState.OldRect.bottom - window->State.pWState.OldRect.top; + } + + /* We'll finish off the fullscreen operation below after the other GLUT_POSITION_WORK|GLUT_SIZE_WORK|GLUT_ZORDER_WORK */ + } + else + { + /* we are currently not fullscreen, go to fullscreen: + * remove window decoration and then maximize + */ + RECT rect; + HMONITOR hMonitor; + MONITORINFO mi; + DWORD newStyle; + + /* save current window rect, style, exstyle and maximized state */ + window->State.pWState.OldMaximized = !!IsZoomed(window->Window.Handle); + if (window->State.pWState.OldMaximized) + /* We force the window into restored mode before going + * fullscreen because Windows doesn't seem to hide the + * taskbar if the window is in the maximized state. + */ + SendMessage(window->Window.Handle, WM_SYSCOMMAND, SC_RESTORE, 0); + + fghGetClientArea( &window->State.pWState.OldRect, window, GL_TRUE ); + window->State.pWState.OldStyle = GetWindowLong(window->Window.Handle, GWL_STYLE); + window->State.pWState.OldStyleEx = GetWindowLong(window->Window.Handle, GWL_EXSTYLE); + + /* remove decorations from style */ + newStyle = window->State.pWState.OldStyle & ~(WS_CAPTION | WS_THICKFRAME); + if (fgState.DisplayMode & GLUT_STEREO) + { + /* stereo mode does not engage on nVidia stereo buffers. This kills child + windows, but we make the guess that those are rare for stereo windows. */ + newStyle |= WS_POPUP; + } + SetWindowLong(window->Window.Handle, GWL_STYLE, newStyle); + SetWindowLong(window->Window.Handle, GWL_EXSTYLE, + window->State.pWState.OldStyleEx & ~(WS_EX_DLGMODALFRAME | + WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE)); + + /* For fullscreen mode, find the monitor that is covered the most + * by the window and get its rect as the resize target. + */ + hMonitor= MonitorFromWindow(window->Window.Handle, MONITOR_DEFAULTTONEAREST); + mi.cbSize = sizeof(mi); + GetMonitorInfo(hMonitor, &mi); + rect = mi.rcMonitor; + + /* then setup window resize, overwriting other work queued on the window */ + window->State.WorkMask |= GLUT_POSITION_WORK | GLUT_SIZE_WORK; + window->State.WorkMask &= ~GLUT_ZORDER_WORK; + window->State.DesiredXpos = rect.left; + window->State.DesiredYpos = rect.top; + window->State.DesiredWidth = rect.right - rect.left; + window->State.DesiredHeight = rect.bottom - rect.top; + } + } +#endif /*!defined(_WIN32_WCE) */ + + /* Now deal with normal position, reshape and z order requests (some might have been set when handling GLUT_FULLSCREEN_WORK above */ + { + /* get rect describing window's current position and size, + * in screen coordinates and in FreeGLUT format + * (size (right-left, bottom-top) is client area size, top and left + * are outside of window including decorations). + */ + fghGetClientArea( &clientRect, window, TRUE ); + + if (workMask & GLUT_POSITION_WORK) + { + flags &= ~SWP_NOMOVE; + + /* Move rect so that top-left is at requested position */ + /* This also automatically makes sure that child window requested coordinates are relative + * to top-left of parent's client area (needed input for SetWindowPos on child windows), + * so no need to further correct rect for child windows below (childs don't have decorations either). + */ + OffsetRect(&clientRect,window->State.DesiredXpos-clientRect.left,window->State.DesiredYpos-clientRect.top); + } + if (workMask & GLUT_SIZE_WORK) + { + flags &= ~SWP_NOSIZE; + + /* Note on maximizing behavior of Windows: the resize borders are off + * the screen such that the client area extends all the way from the + * leftmost corner to the rightmost corner to maximize screen real + * estate. A caption is still shown however to allow interaction with + * the window controls. This is default behavior of Windows that + * FreeGLUT sticks with. To alter, one would have to check if + * WS_MAXIMIZE style is set when a resize event is triggered, and + * then manually correct the windowRect to put the borders back on + * screen. + */ + + /* Set new size of window, WxH specify client area */ + clientRect.right = clientRect.left + window->State.DesiredWidth; + clientRect.bottom = clientRect.top + window->State.DesiredHeight; + } + if (workMask & GLUT_ZORDER_WORK) + { + flags &= ~SWP_NOZORDER; + + /* Could change this to push it down or up one window at a time with some + * more code using GetWindow with GW_HWNDPREV and GW_HWNDNEXT. + * What would be consistent with X11? Win32 GLUT does what we do here... + */ + if (window->State.DesiredZOrder < 0) + insertAfter = HWND_BOTTOM; + } + } + + /* Adjust for window decorations + * Child windows don't have decoration, so no need to correct + */ + if (!window->Parent) + /* get the window rect from this to feed to SetWindowPos, correct for window decorations */ + fghComputeWindowRectFromClientArea_QueryWindow(&clientRect,window,TRUE); + + /* Do the requested positioning, moving, and z order push/pop. */ + SetWindowPos( window->Window.Handle, + insertAfter, + clientRect.left, clientRect.top, + clientRect.right - clientRect.left, + clientRect.bottom- clientRect.top, + flags + ); + + /* Finish off the fullscreen operation we were doing, if any */ + if (workMask & GLUT_FULL_SCREEN_WORK) + { + if (window->State.IsFullscreen) + { + /* leaving fullscreen, restore maximized state, if any */ + if (window->State.pWState.OldMaximized) + SendMessage(window->Window.Handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0); + + window->State.IsFullscreen = GL_FALSE; + } + else + window->State.IsFullscreen = GL_TRUE; + } +} + + +void fgPlatformVisibilityWork(SFG_Window* window) +{ + /* Visibility status of window gets updated in the WM_SHOWWINDOW and WM_SIZE handlers */ + int cmdShow = 0; + SFG_Window *win = window; + switch (window->State.DesiredVisibility) + { + case DesireHiddenState: + cmdShow = SW_HIDE; + break; + case DesireIconicState: + cmdShow = SW_MINIMIZE; + /* Call on top-level window */ + while (win->Parent) + win = win->Parent; + break; + case DesireNormalState: + if (win->IsMenu && !fgStructure.GameModeWindow) + cmdShow = SW_SHOWNA; /* Just show, don't activate window if its a menu. Only exception is when there is a gamemode window as the menu would pop under it when we do this... */ + else + cmdShow = SW_SHOW; + break; + } + + ShowWindow( win->Window.Handle, cmdShow ); +} diff --git a/src/mswin/fg_menu_mswin.c b/src/mswin/fg_menu_mswin.c new file mode 100644 index 0000000..646d5ab --- /dev/null +++ b/src/mswin/fg_menu_mswin.c @@ -0,0 +1,113 @@ +/* + * fg_menu_mswin.c + * + * The Windows-specific mouse cursor related stuff. + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by John F. Fay, + * Creation date: Sun Jan 22, 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#define FREEGLUT_BUILDING_LIB +#include +#include "../fg_internal.h" + + +extern void fgEnumMenus( FGCBMenuEnumerator enumCallback, SFG_Enumerator* enumerator ); + + + +GLvoid fgPlatformGetGameModeVMaxExtent( SFG_Window* window, int* x, int* y ) +{ + *x = glutGet ( GLUT_SCREEN_WIDTH ); + *y = glutGet ( GLUT_SCREEN_HEIGHT ); +} + +static void fghcbIsActiveMenu(SFG_Menu *menu, + SFG_Enumerator *enumerator) +{ + if (enumerator->found) + return; + + /* Check the menu's active and the one we are searching for. */ + if (menu->IsActive && menu->Window->Window.Handle==(HWND)enumerator->data) + { + enumerator->found = GL_TRUE; + enumerator->data = (void*) menu; + return; + } +} + +void fgPlatformCheckMenuDeactivate(HWND newFocusWnd) +{ + /* User/system switched application focus. + * If we have an open menu, close it. + * If the window that got focus is an active + * menu window, don't do anything. This occurs + * as it is sadly necessary to do an activating + * ShowWindow() for the menu to pop up over the + * gamemode window. + * If the window that got focus is the gamemode + * window, the menus pop under it. Bring them + * back in view in this special case. + */ + SFG_Menu* menu = NULL; + SFG_Enumerator enumerator; + + if ( fgState.ActiveMenus ) + { + /* see if there is an active menu whose window matches the one that got focus */ + enumerator.found = GL_FALSE; + enumerator.data = (void*) newFocusWnd; + fgEnumMenus(fghcbIsActiveMenu, &enumerator); + if (enumerator.found) + menu = (SFG_Menu*) enumerator.data; + + if ( !menu ) + { + /* window that got focus was not one of the active menus. That means we'll + * close the active menu's unless the window that got focus was their parent */ + menu = fgGetActiveMenu(); + + if (newFocusWnd != menu->ParentWindow->Window.Handle) + { + /* focus shifted to another window than the menu's parent, close menus */ + fgDeactivateMenu(menu->ParentWindow); + return; + } + } + } +} + + + +/* -- PLATFORM-SPECIFIC INTERFACE FUNCTION -------------------------------------------------- */ + +int FGAPIENTRY __glutCreateMenuWithExit( void(* callback)( int ), void (__cdecl *exit_function)(int) ) +{ + __glutExitFunc = exit_function; + return glutCreateMenu( callback ); +} + +int FGAPIENTRY __glutCreateMenuUcallWithExit(void(*callback)(int, void*), void(__cdecl *exit_function)(int), void* user_data) +{ + __glutExitFunc = exit_function; + return glutCreateMenuUcall(callback, user_data); +} diff --git a/src/mswin/fg_spaceball_mswin.c b/src/mswin/fg_spaceball_mswin.c new file mode 100644 index 0000000..63fa35c --- /dev/null +++ b/src/mswin/fg_spaceball_mswin.c @@ -0,0 +1,199 @@ +/* + * fg_spaceball_mswin.c + * + * Spaceball support for Windows + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by Evan Felix + * Creation date: Sat Feb 4, 2012 + * + * Copyright (c) 2014 Jinrong Xie. All Rights Reserved. + * Written by Jinrong Xie + * Modification date: Wed Dec 24, 2014 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Modified by Jinrong Xie 12/24/2014 + * for Space Navigator support on Windows. + * This code is enhanced by at least supporting 3Dconnexion's + * six degree of freedom navigator. + */ + +#if(_WIN32_WINNT >= 0x0501) + +#include +#include +#include "../fg_internal.h" + +enum { + SPNAV_EVENT_ANY, + SPNAV_EVENT_MOTION_TRANSLATION, + SPNAV_EVENT_MOTION_ROTATION, + SPNAV_EVENT_BUTTON /* includes both press and release */ +}; + +extern int fg_sball_initialized; +unsigned int __fgSpaceKeystate = 0; +RAWINPUTDEVICE __fgSpaceball = { 0x01, 0x08, 0x00, 0x00 }; + +void fgPlatformInitializeSpaceball(void) +{ + HWND hwnd; + fg_sball_initialized = 1; + if (!fgStructure.CurrentWindow) + { + fg_sball_initialized = 0; + return; + } + hwnd = fgStructure.CurrentWindow->Window.Handle; + + { + BOOL ok; + UINT cbSize = sizeof(__fgSpaceball); + __fgSpaceball.hwndTarget = hwnd; + ok = RegisterRawInputDevices(&__fgSpaceball, 1, cbSize); + + if (!ok){ + __fgSpaceball.hwndTarget = NULL; + fg_sball_initialized = 0; + } + } +} + +void fgPlatformSpaceballClose(void) +{ + return; +} + +int fgPlatformHasSpaceball(void) +{ + return __fgSpaceball.hwndTarget ? 1 : 0; +} + +int fgPlatformSpaceballNumButtons(void) +{ + return 0; +} + +void fgPlatformSpaceballSetWindow(SFG_Window *window) +{ + return; +} + +int fgIsSpaceballWinEvent(HWND hwnd, WPARAM wParam, LPARAM lParam) +{ + return 0; +} + +void fgSpaceballHandleWinEvent(HWND hwnd, WPARAM wParam, LPARAM lParam) +{ + #define LOGITECH_VENDOR_ID 0x46d + HRAWINPUT hRawInput = (HRAWINPUT)lParam; + UINT inputCode = (UINT)wParam; + UINT size; + BYTE *rawInputBuffer; + PRAWINPUT pRawInput; + UINT res; + RID_DEVICE_INFO sRidDeviceInfo; + + if (!fg_sball_initialized) + { + fgPlatformInitializeSpaceball(); + if (!fg_sball_initialized) + { + return; + } + } + + res = GetRawInputData(hRawInput, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)); + if (res == -1) + return; + + rawInputBuffer = malloc(size * sizeof *rawInputBuffer); + pRawInput = (PRAWINPUT)rawInputBuffer; + + res = GetRawInputData(hRawInput, RID_INPUT, pRawInput, &size, sizeof(RAWINPUTHEADER)); + if (res == -1) + return; + if (pRawInput->header.dwType != RIM_TYPEHID) + return; + + sRidDeviceInfo.cbSize = sizeof(RID_DEVICE_INFO); + size = sizeof(RID_DEVICE_INFO); + res = GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_DEVICEINFO, &sRidDeviceInfo, &size); + if (res == -1) + return; + { + SFG_Window* window = fgWindowByHandle(hwnd); + if ((window == NULL)) + return; + + if (sRidDeviceInfo.hid.dwVendorId == LOGITECH_VENDOR_ID) + { + // Motion data comes in two parts: motion type and + // displacement/rotation along three axis. + // Orientation is a right handed coordinate system with + // X goes right, Y goes up and Z goes towards viewer, e.g. + // the one used in OpenGL + if (pRawInput->data.hid.bRawData[0] == + SPNAV_EVENT_MOTION_TRANSLATION) + { // Translation vector + short* pnData = (short*)(&pRawInput->data.hid.bRawData[1]); + short X = pnData[0]; + short Y = -pnData[2]; + short Z = pnData[1]; + INVOKE_WCB(*window, SpaceMotion, (X, Y, Z)); + } + else if (pRawInput->data.hid.bRawData[0] == + SPNAV_EVENT_MOTION_ROTATION) + { // Axis aligned rotation vector + short* pnData = (short*)(&pRawInput->data.hid.bRawData[1]); + short rX = pnData[0]; + short rY = -pnData[2]; + short rZ = pnData[1]; + INVOKE_WCB(*window, SpaceRotation, (rX, rY, rZ)); + } + else if (pRawInput->data.hid.bRawData[0] == + SPNAV_EVENT_BUTTON) + { // State of the keys + unsigned long dwKeystate = *(unsigned long*)(&pRawInput->data.hid.bRawData[1]); + unsigned int state = GLUT_UP; + if (FETCH_WCB(*window, SpaceButton)) + { + int i; + for (i = 0; i < 32; i++) + { + unsigned long stateBefore = __fgSpaceKeystate&(1 << i); + unsigned long stateNow = dwKeystate&(1 << i); + + if (stateBefore && !stateNow) + INVOKE_WCB(*window, SpaceButton, (stateBefore, GLUT_UP)); + if (!stateBefore && stateNow) + INVOKE_WCB(*window, SpaceButton, (stateNow, GLUT_DOWN)); + + } + } + __fgSpaceKeystate = dwKeystate; + } + } + } +} + +#endif diff --git a/src/mswin/fg_state_mswin.c b/src/mswin/fg_state_mswin.c new file mode 100644 index 0000000..ce4b31c --- /dev/null +++ b/src/mswin/fg_state_mswin.c @@ -0,0 +1,380 @@ +/* + * fg_state_mswin.c + * + * The Windows-specific state query methods. + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by John F. Fay, + * Creation date: Sun Jan 22, 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "../fg_internal.h" + + +extern GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly, + unsigned char layer_type ); + +/* + * Helper functions for getting client area from the window rect + * and the window rect from the client area given the style of the window + * (or a valid window pointer from which the style can be queried). + */ +extern void fghGetClientArea( RECT *clientRect, const SFG_Window *window, BOOL posIsOutside ); +extern void fghGetStyleFromWindow( const SFG_Window *window, DWORD *windowStyle, DWORD *windowExStyle ); +extern void fghComputeWindowRectFromClientArea_UseStyle( RECT *clientRect, const DWORD windowStyle, const DWORD windowExStyle, BOOL posIsOutside ); + + +/* The following include file is available from SGI but is not standard: + * #include + * So we copy the necessary parts out of it to support the multisampling query + */ +#ifndef WGL_SAMPLES_ARB +#define WGL_SAMPLES_ARB 0x2042 +#endif +#ifndef WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB +#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9 +#endif + +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); + +#if defined(_WIN32_WCE) +# include +# ifdef FREEGLUT_LIB_PRAGMAS +# pragma comment( lib, "Aygshell.lib" ) +# endif +#endif /* defined(_WIN32_WCE) */ + + + +int fgPlatformGlutGet ( GLenum eWhat ) +{ + int returnValue ; + GLboolean boolValue ; + + int nsamples = 0; + + switch( eWhat ) + { + case GLUT_WINDOW_NUM_SAMPLES: + glGetIntegerv(WGL_SAMPLES_ARB, &nsamples); + return nsamples; + + /* Handle the OpenGL inquiries */ + case GLUT_WINDOW_RGBA: +#if defined(_WIN32_WCE) + boolValue = (GLboolean)0; /* WinCE doesn't support this feature */ +#else + glGetBooleanv ( GL_RGBA_MODE, &boolValue ); + returnValue = boolValue ? 1 : 0; +#endif + return returnValue; + case GLUT_WINDOW_DOUBLEBUFFER: +#if defined(_WIN32_WCE) + boolValue = (GLboolean)0; /* WinCE doesn't support this feature */ +#else + glGetBooleanv ( GL_DOUBLEBUFFER, &boolValue ); + returnValue = boolValue ? 1 : 0; +#endif + return returnValue; + case GLUT_WINDOW_STEREO: +#if defined(_WIN32_WCE) + boolValue = (GLboolean)0; /* WinCE doesn't support this feature */ +#else + glGetBooleanv ( GL_STEREO, &boolValue ); + returnValue = boolValue ? 1 : 0; +#endif + return returnValue; + + case GLUT_WINDOW_RED_SIZE: + glGetIntegerv ( GL_RED_BITS, &returnValue ); + return returnValue; + case GLUT_WINDOW_GREEN_SIZE: + glGetIntegerv ( GL_GREEN_BITS, &returnValue ); + return returnValue; + case GLUT_WINDOW_BLUE_SIZE: + glGetIntegerv ( GL_BLUE_BITS, &returnValue ); + return returnValue; + case GLUT_WINDOW_ALPHA_SIZE: + glGetIntegerv ( GL_ALPHA_BITS, &returnValue ); + return returnValue; + case GLUT_WINDOW_ACCUM_RED_SIZE: +#if defined(_WIN32_WCE) + returnValue = 0; /* WinCE doesn't support this feature */ +#else + glGetIntegerv ( GL_ACCUM_RED_BITS, &returnValue ); +#endif + return returnValue; + case GLUT_WINDOW_ACCUM_GREEN_SIZE: +#if defined(_WIN32_WCE) + returnValue = 0; /* WinCE doesn't support this feature */ +#else + glGetIntegerv ( GL_ACCUM_GREEN_BITS, &returnValue ); +#endif + return returnValue; + case GLUT_WINDOW_ACCUM_BLUE_SIZE: +#if defined(_WIN32_WCE) + returnValue = 0; /* WinCE doesn't support this feature */ +#else + glGetIntegerv ( GL_ACCUM_BLUE_BITS, &returnValue ); +#endif + return returnValue; + case GLUT_WINDOW_ACCUM_ALPHA_SIZE: +#if defined(_WIN32_WCE) + returnValue = 0; /* WinCE doesn't support this feature */ +#else + glGetIntegerv ( GL_ACCUM_ALPHA_BITS, &returnValue ); +#endif + return returnValue; + case GLUT_WINDOW_DEPTH_SIZE: + glGetIntegerv ( GL_DEPTH_BITS, &returnValue ); + return returnValue; + + case GLUT_WINDOW_BUFFER_SIZE: + { + PIXELFORMATDESCRIPTOR pfd; + HDC hdc = fgStructure.CurrentWindow->Window.pContext.Device; + int iPixelFormat = GetPixelFormat( hdc ); + DescribePixelFormat(hdc, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); + + returnValue = pfd.cColorBits; + if (pfd.iPixelType==PFD_TYPE_RGBA) + returnValue += pfd.cAlphaBits; + + return returnValue; + } + case GLUT_WINDOW_STENCIL_SIZE: + glGetIntegerv ( GL_STENCIL_BITS, &returnValue ); + return returnValue; + + case GLUT_WINDOW_X: + case GLUT_WINDOW_Y: + { + /* + * NB: + * - When you create a window with position (x,y) and size + * (w,h), the upper left hand corner of the outside of the + * window is at (x,y) and the size of the drawable area is + * (w,h). + * - When you query the size and position of the window--as + * is happening here for Windows--"freeglut" will return + * the size of the drawable area--the (w,h) that you + * specified when you created the window--and the coordinates + * of the upper left hand corner of the drawable area, i.e. + * of the client rect--which is NOT the (x,y) you specified. + */ + + RECT winRect; + POINT topLeft = {0,0}; + + freeglut_return_val_if_fail( fgStructure.CurrentWindow != NULL, 0 ); + +#if defined(_WIN32_WCE) + GetWindowRect( fgStructure.CurrentWindow->Window.Handle, &winRect); +#else + ClientToScreen(fgStructure.CurrentWindow->Window.Handle, &topLeft); + + if (fgStructure.CurrentWindow->Parent) + /* For child window, we should return relative to upper-left + * of parent's client area. + */ + ScreenToClient(fgStructure.CurrentWindow->Parent->Window.Handle,&topLeft); + + winRect.left = topLeft.x; + winRect.top = topLeft.y; +#endif /* defined(_WIN32_WCE) */ + + switch( eWhat ) + { + case GLUT_WINDOW_X: return winRect.left; + case GLUT_WINDOW_Y: return winRect.top ; + } + } + break; + + case GLUT_WINDOW_WIDTH: + case GLUT_WINDOW_HEIGHT: + { + RECT winRect; + freeglut_return_val_if_fail( fgStructure.CurrentWindow != NULL, 0 ); + + GetClientRect( fgStructure.CurrentWindow->Window.Handle, &winRect); + + switch( eWhat ) + { + case GLUT_WINDOW_WIDTH: return winRect.right-winRect.left; + case GLUT_WINDOW_HEIGHT: return winRect.bottom-winRect.top; + } + } + break; + + case GLUT_WINDOW_BORDER_WIDTH : + case GLUT_WINDOW_BORDER_HEIGHT : +#if defined(_WIN32_WCE) + return 0; +#else + { + /* We can't get the border width or header height in the simple way + * with some calls to GetSystemMetrics. We'd then have to assume which + * elements are present for a given decoration, and such calculations + * wouldn't be valid for every version of Windows. The below should be + * robust. */ + int borderWidth, captionHeight; + DWORD windowStyle, windowExStyle; + RECT clientRect, winRect; + + /* Get style of window, or default style */ + fghGetStyleFromWindow( fgStructure.CurrentWindow, &windowStyle, &windowExStyle ); + /* Get client area if we have a current window, else use dummy rect */ + /* Also get window rect (including non-client area) */ + if (fgStructure.CurrentWindow && fgStructure.CurrentWindow->Window.Handle) + { + fghGetClientArea(&clientRect,fgStructure.CurrentWindow, FALSE); + GetWindowRect(fgStructure.CurrentWindow->Window.Handle,&winRect); + } + else + { + SetRect(&clientRect,0,0,200,200); + CopyRect(&winRect,&clientRect); + fghComputeWindowRectFromClientArea_UseStyle(&winRect,windowStyle,windowExStyle,FALSE); + } + + /* Calculate border width by taking width of whole window minus width of client area and divide by two + * NB: we assume horizontal and vertical borders have the same size, which should always be the case + * unless the user bypassed FreeGLUT and messed with the windowstyle himself. + * Once borderwidth is known, account for it when comparing height of window to height of client area. + * all other extra pixels are assumed to be atop the window, forming the caption. + */ + borderWidth = ((winRect.right-winRect.left)-(clientRect.right-clientRect.left))/2; + captionHeight = (winRect.bottom-winRect.top)-(clientRect.bottom-clientRect.top)-borderWidth; /* include top border in caption height */ + + switch( eWhat ) + { + case GLUT_WINDOW_BORDER_WIDTH: + return borderWidth; + case GLUT_WINDOW_BORDER_HEIGHT: + return captionHeight; + } + } +#endif /* defined(_WIN32_WCE) */ + + case GLUT_DISPLAY_MODE_POSSIBLE: +#if defined(_WIN32_WCE) + return 0; +#else + return fgSetupPixelFormat( fgStructure.CurrentWindow, GL_TRUE, + PFD_MAIN_PLANE ); +#endif /* defined(_WIN32_WCE) */ + + + case GLUT_WINDOW_FORMAT_ID: +#if !defined(_WIN32_WCE) + if( fgStructure.CurrentWindow != NULL ) + return GetPixelFormat( fgStructure.CurrentWindow->Window.pContext.Device ); +#endif /* defined(_WIN32_WCE) */ + return 0; + + case GLUT_WINDOW_SRGB: + if( fgStructure.CurrentWindow != NULL ) { + static int attr = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB; + static PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB; + HDC hdc = fgStructure.CurrentWindow->Window.pContext.Device; + int ipixfmt = GetPixelFormat(hdc); + int val; + + if(!wglGetPixelFormatAttribivARB) { + if(!(wglGetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)wglGetProcAddress("wglGetPixelFormatAttribivARB"))) { + return 0; + } + } + if(wglGetPixelFormatAttribivARB(hdc, ipixfmt, 0, 1, &attr, &val)) { + return val; + } + } + return 0; + + case GLUT_WINDOW_COLORMAP_SIZE: + if(!fgStructure.CurrentWindow) { + return 0; + } + return fgStructure.CurrentWindow->Window.cmap_size; + + default: + fgWarning( "glutGet(): missing enum handle %d", eWhat ); + break; + } + + return -1; +} + + +int fgPlatformGlutDeviceGet ( GLenum eWhat ) +{ + switch( eWhat ) + { + case GLUT_HAS_KEYBOARD: + /* + * Win32 is assumed a keyboard, and this cannot be queried, + * except for WindowsCE. + */ +#if defined(_WIN32_CE) + return ( GetKeyboardStatus() & KBDI_KEYBOARD_PRESENT ) ? 1 : 0; +# if FREEGLUT_LIB_PRAGMAS +# pragma comment (lib,"Kbdui.lib") +# endif + +#else + return 1; +#endif + + case GLUT_HAS_MOUSE: + /* + * MS Windows can be booted without a mouse. + */ + return GetSystemMetrics( SM_MOUSEPRESENT ); + + case GLUT_NUM_MOUSE_BUTTONS: +# if defined(_WIN32_WCE) + return 1; +# else + return GetSystemMetrics( SM_CMOUSEBUTTONS ); +# endif + + default: + fgWarning( "glutDeviceGet(): missing enum handle %d", eWhat ); + return -1; + break; + } +} + +/* + * This is for querying the number of supported auxiliary or multisample + * buffers for a (the current?) display mode. + * see http://old.nabble.com/-GLX--glutGetModeValues-to13514723.html#a13514723 + * Not currently implemented, but we should be able to query the relevant + * info using + * http://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt + * (if supported on the executing machine!) + */ +int *fgPlatformGlutGetModeValues(GLenum eWhat, int *size) +{ + *size = 0; + return NULL; +} diff --git a/src/mswin/fg_structure_mswin.c b/src/mswin/fg_structure_mswin.c new file mode 100644 index 0000000..7f61697 --- /dev/null +++ b/src/mswin/fg_structure_mswin.c @@ -0,0 +1,34 @@ +/* + * fg_structure_mswin.c + * + * The Windows-specific mouse cursor related stuff. + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by John F. Fay, + * Creation date: Sun Jan 22, 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "../fg_internal.h" + + +void fgPlatformCreateWindow ( SFG_Window *window ) +{ +} diff --git a/src/mswin/fg_window_mswin.c b/src/mswin/fg_window_mswin.c new file mode 100644 index 0000000..d4f3c72 --- /dev/null +++ b/src/mswin/fg_window_mswin.c @@ -0,0 +1,890 @@ +/* + * fg_window_mswin.c + * + * The Windows-specific mouse cursor related stuff. + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by John F. Fay, + * Creation date: Sun Jan 22, 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#define FREEGLUT_BUILDING_LIB +#include +#include "../fg_internal.h" + + +/* The following include file is available from SGI but is not standard: + * #include + * So we copy the necessary parts out of it. + * XXX: should local definitions for extensions be put in a separate include file? + */ +typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); + +typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); + +#define WGL_DRAW_TO_WINDOW_ARB 0x2001 +#define WGL_ACCELERATION_ARB 0x2003 +#define WGL_SUPPORT_OPENGL_ARB 0x2010 +#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_COLOR_BITS_ARB 0x2014 +#define WGL_ALPHA_BITS_ARB 0x201B +#define WGL_DEPTH_BITS_ARB 0x2022 +#define WGL_STENCIL_BITS_ARB 0x2023 +#define WGL_FULL_ACCELERATION_ARB 0x2027 + +#define WGL_SAMPLE_BUFFERS_ARB 0x2041 +#define WGL_SAMPLES_ARB 0x2042 + +#define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0 + +#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9 + +#ifndef WGL_ARB_create_context +#define WGL_ARB_create_context 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern HGLRC WINAPI wglCreateContextAttribsARB (HDC, HGLRC, const int *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int *attribList); + +#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 +#define WGL_CONTEXT_FLAGS_ARB 0x2094 +#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 + +#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 +#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 + +#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 + +#define ERROR_INVALID_VERSION_ARB 0x2095 +#define ERROR_INVALID_PROFILE_ARB 0x2096 +#endif +/* End of copying the necessary parts out of it. */ + +#ifdef WM_TOUCH +typedef BOOL (WINAPI *pRegisterTouchWindow)(HWND,ULONG); +static pRegisterTouchWindow fghRegisterTouchWindow = (pRegisterTouchWindow)0xDEADBEEF; +#endif + + +/* + * Setup the pixel format for a Win32 window + */ + +#if defined(_WIN32_WCE) +static wchar_t* fghWstrFromStr(const char* str) +{ + int i,len=strlen(str); + wchar_t* wstr = (wchar_t*)malloc(2*len+2); + for(i=0; iWindow.pContext.Device, window->Window.Context ); + + if ( !fghIsExtensionSupported( window->Window.pContext.Device, "WGL_ARB_create_context" ) ) + { + /* wglCreateContextAttribsARB not found, yet the user has requested the new context creation */ + fgWarning( "OpenGL >2.1 context requested but wglCreateContextAttribsARB is not available! Falling back to legacy context creation" ); + /* Legacy context already created at this point in WM_CREATE path of fgPlatformWindowProc, just return */ + return; + } + + /* new context creation */ + fghFillContextAttributes( attributes ); + + wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress( "wglCreateContextAttribsARB" ); + if ( wglCreateContextAttribsARB == NULL ) + { + /* wglCreateContextAttribsARB not found, yet the user has requested the new context creation */ + fgWarning( "OpenGL >2.1 context requested but wglCreateContextAttribsARB is not available! Falling back to legacy context creation" ); + /* Legacy context already created at this point in WM_CREATE path of fgPlatformWindowProc, just return */ + return; + } + + context = wglCreateContextAttribsARB( window->Window.pContext.Device, 0, attributes ); + if ( context == NULL ) + { + fghContextCreationError(); + } + + wglMakeCurrent( NULL, NULL ); + wglDeleteContext( window->Window.Context ); + window->Window.Context = context; +} + +#if !defined(_WIN32_WCE) + +static void fghFillPFD(PIXELFORMATDESCRIPTOR *ppfd, HDC hdc, unsigned char layer_type) +{ + int flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; + if(fgState.DisplayMode & GLUT_DOUBLE) { + flags |= PFD_DOUBLEBUFFER; + } + if(fgState.DisplayMode & GLUT_STEREO) { + flags |= PFD_STEREO; + } + + /* Specify which pixel format do we opt for... */ + memset(ppfd, 0, sizeof *ppfd); + ppfd->nSize = sizeof *ppfd; + ppfd->nVersion = 1; + ppfd->dwFlags = flags; + + if(fgState.DisplayMode & GLUT_INDEX) { + ppfd->iPixelType = PFD_TYPE_COLORINDEX; + ppfd->cColorBits = 8; + } else { + ppfd->iPixelType = PFD_TYPE_RGBA; + ppfd->cColorBits = 24; + } + if(fgState.DisplayMode & GLUT_ALPHA) { + ppfd->cAlphaBits = 8; + } + + ppfd->cAccumBits = (fgState.DisplayMode & GLUT_ACCUM) ? 1 : 0; + + /* Hmmm, or 32/0 instead of 24/8? */ + if(fgState.DisplayMode & GLUT_DEPTH) { + ppfd->cDepthBits = 24; + } + if(fgState.DisplayMode & GLUT_STENCIL) { + ppfd->cStencilBits = 8; + } + + ppfd->cAuxBuffers = (BYTE)fghNumberOfAuxBuffersRequested(); + ppfd->iLayerType = layer_type; +} + +static void fghFillPixelFormatAttributes( int *attributes, const PIXELFORMATDESCRIPTOR *ppfd ) +{ + int where = 0; + + ATTRIB_VAL( WGL_DRAW_TO_WINDOW_ARB, GL_TRUE ); + ATTRIB_VAL( WGL_SUPPORT_OPENGL_ARB, GL_TRUE ); + ATTRIB_VAL( WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB ); + + ATTRIB_VAL( WGL_COLOR_BITS_ARB, ppfd->cColorBits ); + ATTRIB_VAL( WGL_ALPHA_BITS_ARB, ppfd->cAlphaBits ); + ATTRIB_VAL( WGL_DEPTH_BITS_ARB, ppfd->cDepthBits ); + ATTRIB_VAL( WGL_STENCIL_BITS_ARB, ppfd->cStencilBits ); + + ATTRIB_VAL( WGL_DOUBLE_BUFFER_ARB, ( fgState.DisplayMode & GLUT_DOUBLE ) != 0 ); + + if ( fgState.DisplayMode & GLUT_SRGB ) { + ATTRIB_VAL( WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, TRUE ); + } + + ATTRIB_VAL( WGL_SAMPLE_BUFFERS_ARB, GL_TRUE ); + ATTRIB_VAL( WGL_SAMPLES_ARB, fgState.SampleNumber ); + ATTRIB( 0 ); +} +#endif + +GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly, + unsigned char layer_type ) +{ +#if defined(_WIN32_WCE) + return GL_TRUE; +#else + PIXELFORMATDESCRIPTOR pfd; + int pixelformat; + HDC current_hDC; + GLboolean success = GL_FALSE; + + if (checkOnly) + current_hDC = CreateDC(TEXT("DISPLAY"), NULL ,NULL ,NULL); + else + current_hDC = window->Window.pContext.Device; + + fghFillPFD(&pfd, current_hDC, layer_type); + if(!(pixelformat = ChoosePixelFormat(current_hDC, &pfd))) { + return 0; + } + + /* windows hack for multismapling/sRGB */ + if ( ( fgState.DisplayMode & GLUT_MULTISAMPLE ) || + ( fgState.DisplayMode & GLUT_SRGB ) ) + { + HGLRC rc, rc_before=wglGetCurrentContext(); + HWND hWnd; + HDC hDC, hDC_before=wglGetCurrentDC(); + WNDCLASS wndCls; + + /* create a dummy window */ + ZeroMemory(&wndCls, sizeof(wndCls)); + wndCls.lpfnWndProc = DefWindowProc; + wndCls.hInstance = fgDisplay.pDisplay.Instance; + wndCls.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; + wndCls.lpszClassName = _T("FREEGLUT_dummy"); + RegisterClass( &wndCls ); + + hWnd=CreateWindow(_T("FREEGLUT_dummy"), _T(""), WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW , 0,0,0,0, 0, 0, fgDisplay.pDisplay.Instance, 0 ); + hDC=GetDC(hWnd); + SetPixelFormat(hDC, pixelformat, &pfd); + + rc = wglCreateContext( hDC ); + wglMakeCurrent(hDC, rc); + + if ( fghIsExtensionSupported( hDC, "WGL_ARB_multisample" ) ) + { + PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARBProc = + (PFNWGLCHOOSEPIXELFORMATARBPROC) wglGetProcAddress("wglChoosePixelFormatARB"); + if ( wglChoosePixelFormatARBProc ) + { + int attributes[100]; + int iPixelFormat; + BOOL bValid; + float fAttributes[] = { 0, 0 }; + UINT numFormats; + fghFillPixelFormatAttributes(attributes, &pfd); + bValid = wglChoosePixelFormatARBProc(hDC, attributes, fAttributes, 1, &iPixelFormat, &numFormats); + + if ( bValid && numFormats > 0 ) + { + pixelformat = iPixelFormat; + } + } + } + + wglMakeCurrent( hDC_before, rc_before); + wglDeleteContext(rc); + ReleaseDC(hWnd, hDC); + DestroyWindow(hWnd); + UnregisterClass(_T("FREEGLUT_dummy"), fgDisplay.pDisplay.Instance); + } + + if(pixelformat) { + DescribePixelFormat(current_hDC, pixelformat, sizeof pfd, &pfd); + + if(fgState.DisplayMode & GLUT_INDEX) { + if(pfd.iPixelType == PFD_TYPE_RGBA) goto end; + } else { + if(pfd.iPixelType == PFD_TYPE_COLORINDEX) goto end; + } + } + + success = ( pixelformat != 0 ) && ( checkOnly || SetPixelFormat( current_hDC, pixelformat, &pfd) ); + +end: + if(checkOnly) { + DeleteDC(current_hDC); + } + + return success; +#endif /* defined(_WIN32_WCE) */ +} + + + +void fgPlatformSetWindow ( SFG_Window *window ) +{ + if ( window != fgStructure.CurrentWindow ) + { + if( fgStructure.CurrentWindow ) + ReleaseDC( fgStructure.CurrentWindow->Window.Handle, + fgStructure.CurrentWindow->Window.pContext.Device ); + + if ( window ) + { + window->Window.pContext.Device = GetDC( window->Window.Handle ); + wglMakeCurrent( + window->Window.pContext.Device, + window->Window.Context + ); + } + } +} + + +void fghGetDefaultWindowStyle(DWORD *flags) +{ + if ( fgState.DisplayMode & GLUT_BORDERLESS ) + { + /* no window decorations needed, no-op */ + } + else if ( fgState.DisplayMode & GLUT_CAPTIONLESS ) + /* only window decoration is a border, no title bar or buttons */ + (*flags) |= WS_DLGFRAME; + else + /* window decoration are a border, title bar and buttons. */ + (*flags) |= WS_OVERLAPPEDWINDOW; +} + +/* Get window style and extended window style of a FreeGLUT window + * If the window pointer or the window handle is NULL, a fully + * decorated window (caption and border) is assumed. + */ +void fghGetStyleFromWindow( const SFG_Window *window, DWORD *windowStyle, DWORD *windowExStyle ) +{ + if (window && window->Window.Handle) + { + *windowStyle = GetWindowLong(window->Window.Handle, GWL_STYLE); + *windowExStyle = GetWindowLong(window->Window.Handle, GWL_EXSTYLE); + } + else + { + *windowStyle = 0; + fghGetDefaultWindowStyle(windowStyle); + /* WindowExStyle==0 is fine/default, exStyle is currently only used for menu windows */ + *windowExStyle = 0; + } +} + +/* Computes position of corners of window Rect (outer position including + * decorations) based on the provided client rect and based on the style + * of the window in question. + * If posIsOutside is set to true, the input client Rect is taken to follow + * freeGLUT's window specification convention in which the top-left corner + * is at the outside of the window, while the size + * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable + * area. + */ +void fghComputeWindowRectFromClientArea_UseStyle( RECT *clientRect, const DWORD windowStyle, const DWORD windowExStyle, BOOL posIsOutside ) +{ + RECT windowRect = {0,0,0,0}; + CopyRect(&windowRect,clientRect); + + /* Get rect including non-client area */ + AdjustWindowRectEx(&windowRect,windowStyle,FALSE,windowExStyle); + + /* Move window right and down by non-client area extent on left and top, if wanted */ + if (posIsOutside) + { + windowRect.right += clientRect->left-windowRect.left; + windowRect.bottom += clientRect->top -windowRect.top; + windowRect.left = clientRect->left; + windowRect.top = clientRect->top; + } + + /* done, copy windowRect to output */ + CopyRect(clientRect,&windowRect); +} + +/* Computes position of corners of window Rect (outer position including + * decorations) based on the provided client rect and based on the style + * of the window in question. If the window pointer or the window handle + * is NULL, a fully decorated window (caption and border) is assumed. + * Furthermore, if posIsOutside is set to true, the input client Rect is + * taken to follow freeGLUT's window specification convention in which the + * top-left corner is at the outside of the window, while the size + * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable + * area. +*/ +void fghComputeWindowRectFromClientArea_QueryWindow( RECT *clientRect, const SFG_Window *window, BOOL posIsOutside ) +{ + DWORD windowStyle = 0, windowExStyle = 0; + fghGetStyleFromWindow(window,&windowStyle,&windowExStyle); + + fghComputeWindowRectFromClientArea_UseStyle(clientRect, windowStyle, windowExStyle, posIsOutside); +} + +/* Gets the rect describing the client area (drawable area) of the + * specified window. Output is position of corners of client area (drawable area) on the screen. + * Does not touch clientRect if window pointer or window handle is NULL. + * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable area. + * if posIsOutside is true, the output client Rect will follow freeGLUT's window + * specification convention in which the top-left corner is at the outside of + * the window, while the size (rect.right-rect.left,rect.bottom-rect.top) remains to be the + * size of the drawable area. + */ +void fghGetClientArea( RECT *clientRect, const SFG_Window *window, BOOL posIsOutside ) +{ + POINT topLeftClient = {0,0}; + + freeglut_return_if_fail((window && window->Window.Handle)); + + /* Get size of client rect */ + GetClientRect(window->Window.Handle, clientRect); + if (posIsOutside) + { + RECT windowRect; + /* Get position of outside of window, including decorations */ + GetWindowRect(window->Window.Handle,&windowRect); + /* Add top-left offset */ + OffsetRect(clientRect,windowRect.left,windowRect.top); + } + else + { + /* Get position of top-left of client area on the screen */ + ClientToScreen(window->Window.Handle,&topLeftClient); + /* Add top-left offset */ + OffsetRect(clientRect,topLeftClient.x,topLeftClient.y); + } +} + + +#if(WINVER >= 0x500) +typedef struct +{ + int *x; + int *y; + const char *name; +} m_proc_t; + +static BOOL CALLBACK m_proc(HMONITOR mon, + HDC hdc, + LPRECT rect, + LPARAM data) +{ + m_proc_t *dp=(m_proc_t *)data; + MONITORINFOEX info; + BOOL res; + info.cbSize=sizeof(info); + res=GetMonitorInfo(mon,(LPMONITORINFO)&info); + if( res ) + { + if( strcmp(dp->name,info.szDevice)==0 ) + { + *(dp->x)=info.rcMonitor.left; + *(dp->y)=info.rcMonitor.top; + return FALSE; + } + } + return TRUE; +} + +/* + * this function returns the origin of the screen identified by + * fgDisplay.pDisplay.DisplayName, and 0 otherwise. + * This is used in fgOpenWindow to open the gamemode window on the screen + * identified by the -display command line argument. The function should + * not be called otherwise. + */ + +static void get_display_origin(int *xp,int *yp) +{ + *xp = 0; + *yp = 0; + + if( fgDisplay.pDisplay.DisplayName ) + { + m_proc_t st; + st.x=xp; + st.y=yp; + st.name=fgDisplay.pDisplay.DisplayName; + EnumDisplayMonitors(0,0,m_proc,(LPARAM)&st); + } +} +#else +#pragma message( "-display parameter only works if compiled with WINVER >= 0x0500") + +static void get_display_origin(int *xp,int *yp) +{ + *xp = 0; + *yp = 0; + + if( fgDisplay.pDisplay.DisplayName ) + { + fgWarning( "for working -display support FreeGLUT must be compiled with WINVER >= 0x0500"); + } +} +#endif + + + +/* + * Opens a window. Requires a SFG_Window object created and attached + * to the freeglut structure. OpenGL context is created here. + */ +void fgPlatformOpenWindow( SFG_Window* window, const char* title, + GLboolean positionUse, int x, int y, + GLboolean sizeUse, int w, int h, + GLboolean gameMode, GLboolean isSubWindow ) +{ + + WNDCLASS wc; + DWORD flags = 0; + DWORD exFlags = 0; + BOOL atom; + HDC dc; + + /* Grab the window class we have registered on glutInit(): */ + atom = GetClassInfo( fgDisplay.pDisplay.Instance, _T("FREEGLUT"), &wc ); + FREEGLUT_INTERNAL_ERROR_EXIT ( atom, "Window Class Info Not Found", + "fgOpenWindow" ); + + /* Determine window style flags*/ + if( gameMode ) + { + FREEGLUT_INTERNAL_ERROR_EXIT ( window->Parent == NULL, + "Game mode being invoked on a subwindow", + "fgOpenWindow" ); + + /* + * Set the window creation flags appropriately to make the window + * entirely visible: + */ + flags = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE; + } + else + { + flags = WS_CLIPSIBLINGS | WS_CLIPCHILDREN; + + /* + * There's a small difference between creating the top, child and + * menu windows + */ + if ( window->IsMenu ) + { + flags |= WS_POPUP; + exFlags |= WS_EX_TOOLWINDOW; + } +#if defined(_WIN32_WCE) + /* no decorations for windows CE */ +#else + /* if this is not a subwindow (child), set its style based on the requested window decorations */ + else if( window->Parent == NULL ) + fghGetDefaultWindowStyle(&flags); +#endif + else + /* subwindows always have no decoration, but are marked as a child window to the OS */ + flags |= WS_CHILD; + } + + /* determine window size and position */ + if( gameMode ) + { + /* if in gamemode, query the origin of specified by the -display + * command line parameter (if any) and offset the upper-left corner + * of the window so we create the window on that screen. + * The -display argument doesn't do anything if not trying to enter + * gamemode. + */ + int xoff=0, yoff=0; + get_display_origin(&xoff,&yoff); + x += xoff; + y += yoff; + } + if( !positionUse ) + { + x = CW_USEDEFAULT; + y = CW_USEDEFAULT; + } + if( !sizeUse ) + { + w = CW_USEDEFAULT; + h = CW_USEDEFAULT; + } +#if !defined(_WIN32_WCE) /* no decorations for windows CE, so nothing to do */ + else + { + RECT windowRect; + /* + * Update the window dimensions, taking the window decorations + * into account. FreeGLUT is to create the window with the + * topleft outside corner at (x,y) and with client area + * dimensions (w,h). + * note: don't need to do this when w=h=CW_USEDEFAULT, so in the + * if( sizeUse ) here is convenient. + */ + windowRect.left = x; + windowRect.top = y; + windowRect.right = x+w; + windowRect.bottom = y+h; + + fghComputeWindowRectFromClientArea_UseStyle(&windowRect,flags,exFlags,TRUE); + + /* NB: w and h are now width and height of window including non-client area! */ + w = windowRect.right - windowRect.left; + h = windowRect.bottom- windowRect.top; + } +#endif /* !defined(_WIN32_WCE) */ + +#if defined(_WIN32_WCE) + { + wchar_t* wstr = fghWstrFromStr(title); + + window->Window.Handle = CreateWindow( + _T("FREEGLUT"), + wstr, + WS_VISIBLE | WS_POPUP, + 0,0, 240,320, + NULL, + NULL, + fgDisplay.pDisplay.Instance, + (LPVOID) window + ); + + free(wstr); + + SHFullScreen(window->Window.Handle, SHFS_HIDESTARTICON); + SHFullScreen(window->Window.Handle, SHFS_HIDESIPBUTTON); + SHFullScreen(window->Window.Handle, SHFS_HIDETASKBAR); + MoveWindow(window->Window.Handle, 0, 0, 240, 320, TRUE); + ShowWindow(window->Window.Handle, SW_SHOW); + UpdateWindow(window->Window.Handle); + } +#else + window->Window.Handle = CreateWindowEx( + exFlags, + _T("FREEGLUT"), + title, + flags, + x, y, w, h, + (HWND) window->Parent == NULL ? NULL : window->Parent->Window.Handle, + (HMENU) NULL, + fgDisplay.pDisplay.Instance, + (LPVOID) window + ); +#endif /* defined(_WIN32_WCE) */ + + /* WM_CREATE message got sent and was handled by window proc */ + + if( !( window->Window.Handle ) ) + fgError( "Failed to create a window (%s)!", title ); + + /* Store title */ + window->State.pWState.WindowTitle = strdup(title); + +#if !defined(_WIN32_WCE) + /* Need to set requested style again, apparently Windows doesn't listen when requesting windows without title bar or borders */ + SetWindowLong(window->Window.Handle, GWL_STYLE, flags); + SetWindowPos(window->Window.Handle, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); +#endif /* defined(_WIN32_WCE) */ + + /* Make a menu window always on top - fix Feature Request 947118 */ + if(window->IsMenu || gameMode) { + SetWindowPos(window->Window.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + } + + dc = window->Window.pContext.Device; + /* for color index mode, create a palette */ + if(fgState.DisplayMode & GLUT_INDEX) { + char buf[sizeof(LOGPALETTE) + 255 * sizeof(PALETTEENTRY)]; + LOGPALETTE *logipal = (LOGPALETTE*)buf; + + GetSystemPaletteEntries(dc, 0, 256, logipal->palPalEntry); + + logipal->palVersion = 0x300; + logipal->palNumEntries = 256; + + if(!(window->Window.cmap = CreatePalette(logipal))) { + fgError("Failed to create palette in indexed mode"); + } + SelectPalette(dc, window->Window.cmap, 0); + RealizePalette(dc); + + window->Window.cmap_size = 256; + } else { + int cur_bpp = GetDeviceCaps(dc, BITSPIXEL) * GetDeviceCaps(dc, PLANES); + if(cur_bpp <= 8) { + /* for RGB mode we also need a palette if we're running in a palettized mode */ + /* XXX we'll just assume 256 colors for now. */ + int i; + char buf[sizeof(LOGPALETTE) + 255 * sizeof(PALETTEENTRY)]; + LOGPALETTE *logipal = (LOGPALETTE*)buf; + + logipal->palVersion = 0x300; + logipal->palNumEntries = 256; + + for(i=0; i<256; i++) { + int r = i & 7; + int g = (i >> 3) & 7; + int b = (i >> 5) & 3; + + logipal->palPalEntry[i].peRed = (r << 5) | (r << 2) | (r >> 1); + logipal->palPalEntry[i].peGreen = (g << 5) | (g << 2) | (g >> 1); + logipal->palPalEntry[i].peBlue = (b << 6) | (b << 4) | (b << 2) | b; + logipal->palPalEntry[i].peFlags = PC_NOCOLLAPSE; + } + + if(!(window->Window.cmap = CreatePalette(logipal))) { + fgWarning("Failed to create palette in RGB mode on %d bpp display, colors might be wrong\n", cur_bpp); + } else { + SelectPalette(dc, window->Window.cmap, 0); + RealizePalette(dc); + } + window->Window.cmap_size = 256; + } + } + + /* Enable multitouch: additional flag TWF_FINETOUCH, TWF_WANTPALM */ + #ifdef WM_TOUCH + if (fghRegisterTouchWindow == (pRegisterTouchWindow)0xDEADBEEF) + fghRegisterTouchWindow = (pRegisterTouchWindow)GetProcAddress(GetModuleHandle("user32"),"RegisterTouchWindow"); + if (fghRegisterTouchWindow) + fghRegisterTouchWindow( window->Window.Handle, TWF_FINETOUCH | TWF_WANTPALM ); + #endif + +#if defined(_WIN32_WCE) + ShowWindow( window->Window.Handle, SW_SHOW ); +#else + if (!window->IsMenu) /* Don't show window after creation if its a menu */ + { + BOOL iconic = fgState.ForceIconic && !gameMode && !isSubWindow; + ShowWindow( window->Window.Handle, + iconic ? SW_SHOWMINIMIZED : SW_SHOWNORMAL ); + } +#endif /* defined(_WIN32_WCE) */ + + ShowCursor( TRUE ); +} + + +/* + * Closes a window, destroying the frame and OpenGL context + */ +void fgPlatformCloseWindow( SFG_Window* window ) +{ + /* Make sure we don't close a window with current context active */ + if( fgStructure.CurrentWindow == window ) + wglMakeCurrent( NULL, NULL ); + + /* + * Step through the list of windows. If the rendering context + * is not being used by another window, then we delete it. + */ + { + int used = FALSE ; + SFG_Window *iter ; + + for( iter = (SFG_Window *)fgStructure.Windows.First; + iter; + iter = (SFG_Window *)iter->Node.Next ) + { + if( ( iter->Window.Context == window->Window.Context ) && + ( iter != window ) ) + used = TRUE; + } + + if( ! used ) + wglDeleteContext( window->Window.Context ); + } + + DestroyWindow( window->Window.Handle ); + + /* clean up copied title text(s) */ + if (window->State.pWState.WindowTitle) + free(window->State.pWState.WindowTitle); + if (window->State.pWState.IconTitle) + free(window->State.pWState.IconTitle); +} + +/* + * Hide's specified window. For windows, currently only used + * to immediately hide menu windows... + */ +void fgPlatformHideWindow( SFG_Window* window ) +{ + ShowWindow(window->Window.Handle, SW_HIDE); +} + + +/* + * Set the current window's title + */ +void fgPlatformGlutSetWindowTitle( const char* title ) +{ +#ifdef _WIN32_WCE + { + wchar_t* wstr = fghWstrFromStr(title); + SetWindowText( fgStructure.CurrentWindow->Window.Handle, wstr ); + free(wstr); + } +#else + if (!IsIconic(fgStructure.CurrentWindow->Window.Handle)) + SetWindowText( fgStructure.CurrentWindow->Window.Handle, title ); +#endif + + /* Make copy of string to refer to later */ + if (fgStructure.CurrentWindow->State.pWState.WindowTitle) + free(fgStructure.CurrentWindow->State.pWState.WindowTitle); + fgStructure.CurrentWindow->State.pWState.WindowTitle = strdup(title); +} + +/* + * Set the current window's iconified title + */ +void fgPlatformGlutSetIconTitle( const char* title ) +{ +#ifndef _WIN32_WCE + if (IsIconic(fgStructure.CurrentWindow->Window.Handle)) + SetWindowText( fgStructure.CurrentWindow->Window.Handle, title ); +#endif + + /* Make copy of string to refer to later */ + if (fgStructure.CurrentWindow->State.pWState.IconTitle) + free(fgStructure.CurrentWindow->State.pWState.IconTitle); + fgStructure.CurrentWindow->State.pWState.IconTitle = strdup(title); +} + + +/* -- PLATFORM-SPECIFIC INTERFACE FUNCTION -------------------------------------------------- */ + +int FGAPIENTRY __glutCreateWindowWithExit( const char *title, void (__cdecl *exit_function)(int) ) +{ + __glutExitFunc = exit_function; + return glutCreateWindow( title ); +} + diff --git a/src/util/xparsegeometry_repl.c b/src/util/xparsegeometry_repl.c new file mode 100644 index 0000000..a059369 --- /dev/null +++ b/src/util/xparsegeometry_repl.c @@ -0,0 +1,162 @@ +#include + +/* + * Everything down to the end of the next two functions is copied from the X sources. + */ + +/* + +Copyright 1985, 1986, 1987,1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#include "xparsegeometry_repl.h" + +/* + * XParseGeometry parses strings of the form + * "=x{+-}{+-}", where + * width, height, xoffset, and yoffset are unsigned integers. + * Example: "=80x24+300-49" + * The equal sign is optional. + * It returns a bitmask that indicates which of the four values + * were actually found in the string. For each value found, + * the corresponding argument is updated; for each value + * not found, the corresponding argument is left unchanged. + */ + +static int +ReadInteger(char *string, char **NextString) +{ + register int Result = 0; + int Sign = 1; + + if (*string == '+') + string++; + else if (*string == '-') + { + string++; + Sign = -1; + } + for (; (*string >= '0') && (*string <= '9'); string++) + { + Result = (Result * 10) + (*string - '0'); + } + *NextString = string; + if (Sign >= 0) + return Result; + else + return -Result; +} + +int XParseGeometry ( + const char *string, + int *x, + int *y, + unsigned int *width, /* RETURN */ + unsigned int *height) /* RETURN */ +{ + int mask = NoValue; + register char *strind; + unsigned int tempWidth = 0, tempHeight = 0; + int tempX = 0, tempY = 0; + char *nextCharacter; + + if ( (string == NULL) || (*string == '\0')) + return mask; + if (*string == '=') + string++; /* ignore possible '=' at beg of geometry spec */ + + strind = (char *)string; + if (*strind != '+' && *strind != '-' && *strind != 'x') { + tempWidth = ReadInteger(strind, &nextCharacter); + if (strind == nextCharacter) + return 0; + strind = nextCharacter; + mask |= WidthValue; + } + + if (*strind == 'x' || *strind == 'X') { + strind++; + tempHeight = ReadInteger(strind, &nextCharacter); + if (strind == nextCharacter) + return 0; + strind = nextCharacter; + mask |= HeightValue; + } + + if ((*strind == '+') || (*strind == '-')) { + if (*strind == '-') { + strind++; + tempX = -ReadInteger(strind, &nextCharacter); + if (strind == nextCharacter) + return 0; + strind = nextCharacter; + mask |= XNegative; + } + else + { + strind++; + tempX = ReadInteger(strind, &nextCharacter); + if (strind == nextCharacter) + return 0; + strind = nextCharacter; + } + mask |= XValue; + if ((*strind == '+') || (*strind == '-')) { + if (*strind == '-') { + strind++; + tempY = -ReadInteger(strind, &nextCharacter); + if (strind == nextCharacter) + return 0; + strind = nextCharacter; + mask |= YNegative; + } + else + { + strind++; + tempY = ReadInteger(strind, &nextCharacter); + if (strind == nextCharacter) + return 0; + strind = nextCharacter; + } + mask |= YValue; + } + } + + /* If strind isn't at the end of the string the it's an invalid + geometry specification. */ + + if (*strind != '\0') return 0; + + if (mask & XValue) + *x = tempX; + if (mask & YValue) + *y = tempY; + if (mask & WidthValue) + *width = tempWidth; + if (mask & HeightValue) + *height = tempHeight; + return mask; +} diff --git a/src/util/xparsegeometry_repl.h b/src/util/xparsegeometry_repl.h new file mode 100644 index 0000000..75ebad1 --- /dev/null +++ b/src/util/xparsegeometry_repl.h @@ -0,0 +1,50 @@ +/* + * Copied from the X sources. + */ + +/* + +Copyright 1985, 1986, 1987,1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifndef XPARSEGEOMETRY_REPL_H +#define XPARSEGEOMETRY_REPL_H + +#define NoValue 0x0000 +#define XValue 0x0001 +#define YValue 0x0002 +#define WidthValue 0x0004 +#define HeightValue 0x0008 +#define AllValues 0x000F +#define XNegative 0x0010 +#define YNegative 0x0020 + +extern int XParseGeometry (const char *string, /* INPUT */ + int *x, int *y, /* RETURN */ + unsigned int *width, unsigned int *height); /* RETURN */ + + +#endif diff --git a/src/wayland/fg_cursor_wl.c b/src/wayland/fg_cursor_wl.c new file mode 100644 index 0000000..0543bcc --- /dev/null +++ b/src/wayland/fg_cursor_wl.c @@ -0,0 +1,137 @@ +/* + * fg_cursor_wl.c + * + * The Wayland-specific mouse cursor related stuff. + * + * Copyright (c) 2015 Manuel Bachmann. All Rights Reserved. + * Written by Manuel Bachmann, + * Creation date: Thur Mar 19, 2015 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * MANUEL BACHMANN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include "../fg_internal.h" + +/* + * Note: The arrangement of the table below depends on the fact that + * the "normal" GLUT_CURSOR_* values start a 0 and are consecutive. + */ +static char* cursorList[] = { + "UNSUPPORTED", /* GLUT_CURSOR_RIGHT_ARROW */ + "left_ptr", /* GLUT_CURSOR_LEFT_ARROW */ + "hand1", /* GLUT_CURSOR_INFO */ + "UNSUPPORTED", /* GLUT_CURSOR_DESTROY */ + "UNSUPPORTED", /* GLUT_CURSOR_HELP */ + "UNSUPPORTED", /* GLUT_CURSOR_CYCLE */ + "UNSUPPORTED", /* GLUT_CURSOR_SPRAY */ + "watch", /* GLUT_CURSOR_WAIT */ + "xterm", /* GLUT_CURSOR_TEXT */ + "grabbing", /* GLUT_CURSOR_CROSSHAIR */ + "UNSUPPORTED", /* GLUT_CURSOR_UP_DOWN */ + "UNSUPPORTED", /* GLUT_CURSOR_LEFT_RIGHT */ + "top_side", /* GLUT_CURSOR_TOP_SIDE */ + "bottom_side", /* GLUT_CURSOR_BOTTOM_SIDE */ + "left_side", /* GLUT_CURSOR_LEFT_SIDE */ + "right_side", /* GLUT_CURSOR_RIGHT_SIDE */ + "top_left_corner", /* GLUT_CURSOR_TOP_LEFT_CORNER */ + "top_right_corner", /* GLUT_CURSOR_TOP_RIGHT_CORNER */ + "bottom_right_corner", /* GLUT_CURSOR_BOTTOM_RIGHT_CORNER */ + "bottom_left_corner" /* GLUT_CURSOR_BOTTOM_LEFT_CORNER */ +}; + +void fgPlatformSetCursor ( SFG_Window *window, int cursorID ) +{ + /* + * XXX FULL_CROSSHAIR demotes to plain CROSSHAIR. Old GLUT allows + * for this, but if there is a system that easily supports a full- + * window (or full-screen) crosshair, we might consider it. + */ + int cursorIDToUse = + ( cursorID == GLUT_CURSOR_FULL_CROSSHAIR ) ? GLUT_CURSOR_CROSSHAIR : cursorID; + + char* cursor; + + if( ( cursorIDToUse >= 0 ) && + ( cursorIDToUse < sizeof( cursorList ) / sizeof( cursorList[0] ) ) ) { + + cursor = cursorList[cursorIDToUse]; + + /* if the type is UNSUPPORTED, fall back to GLUT_CURSOR_LEFT_ARROW */ + if ( ! strcmp( cursor, "UNSUPPORTED" ) ) + { + fgWarning( "glutSetCursor(): cursor type unsupported under Wayland : %d", + cursorIDToUse ); + cursor = "left_ptr"; + } + } else { + switch( cursorIDToUse ) + { + case GLUT_CURSOR_NONE: + case GLUT_CURSOR_INHERIT: + cursor = NULL; + break; + + default: + fgError( "Unknown cursor type: %d", cursorIDToUse ); + return; + } + } + + if ( cursorIDToUse == GLUT_CURSOR_INHERIT ) { + if( window->Parent ) + window->Window.pContext.cursor = + window->Parent->Window.pContext.cursor; + } else { + window->Window.pContext.cursor = wl_cursor_theme_get_cursor( + fgDisplay.pDisplay.cursor_theme, + cursor ); + if ( ! window->Window.pContext.cursor ) + fgError( "Failed to create cursor" ); + } +} + + +void fgPlatformWarpPointer ( int x, int y ) +{ + /* unsupported under Wayland */ + fgWarning( "glutWarpPointer(): function unsupported under Wayland" ); +} + +void fghPlatformGetCursorPos(const SFG_Window *window, GLboolean client, SFG_XYUse *mouse_pos) +{ + /* Get current pointer location relative to top-left of client area of window (if client is true and window is not NULL) + * We cannot get current pointer location in screen coordinates under Wayland, so inform the user and return -1 is this case + */ + + if (client && window) + { + mouse_pos->X = window->State.MouseX; + mouse_pos->Y = window->State.MouseY; + } + else + { + fgWarning( "glutGetCursorPos(): cannot get screen position under Wayland" ); + mouse_pos->X = -1; + mouse_pos->Y = -1; + } + + mouse_pos->Use = GL_TRUE; +} + diff --git a/src/wayland/fg_ext_wl.c b/src/wayland/fg_ext_wl.c new file mode 100644 index 0000000..f32f325 --- /dev/null +++ b/src/wayland/fg_ext_wl.c @@ -0,0 +1,49 @@ +/* + * fg_ext_wl.c + * + * Wayland-specific functions related to OpenGL extensions. + * + * Copyright (c) 2015 Manuel Bachmann. All Rights Reserved. + * Written by Manuel Bachmann, + * Creation date: Wed Mar 25 2015 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * MANUEL BACHMANN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include "../fg_internal.h" + +GLUTproc fgPlatformGetGLUTProcAddress( const char* procName ) +{ + /* optimization: quick initial check */ + if( strncmp( procName, "glut", 4 ) != 0 ) + return NULL; + +#define CHECK_NAME(x) if( strcmp( procName, #x ) == 0) return (GLUTproc)x; + CHECK_NAME(glutJoystickFunc); + CHECK_NAME(glutForceJoystickFunc); + CHECK_NAME(glutGameModeString); + CHECK_NAME(glutEnterGameMode); + CHECK_NAME(glutLeaveGameMode); + CHECK_NAME(glutGameModeGet); +#undef CHECK_NAME + + return NULL; +} + diff --git a/src/wayland/fg_gamemode_wl.c b/src/wayland/fg_gamemode_wl.c new file mode 100644 index 0000000..293cf03 --- /dev/null +++ b/src/wayland/fg_gamemode_wl.c @@ -0,0 +1,161 @@ +/* + * fg_gamemode_wl.c + * + * The game mode handling code. + * + * Copyright (c) 2015 Manuel Bachmann. All Rights Reserved. + * Written by Manuel Bachmann, + * Creation date: Sun Mar 23 2015 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * MANUEL BACHMANN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "../fg_internal.h" + +/* Pointer locking is a Weston-specific WIP protocol (for now) + * + * #include "pointer-lock-client-protocol.h" + * #include "relative-pointer-client-protocol.h" + * + * static struct _wl_relative_pointer_manager* relative_pointer_manager; + * static struct _wl_pointer_lock* pointer_lock; + * + * static struct _wl_relative_pointer* relative_pointer; + * static struct _wl_locked_pointer* locked_pointer; + * + * + * static void fghRelativeMotion( void* data, struct _wl_relative_pointer + * pointer, uint32_t time, + * wl_fixed_t x_w, wl_fixed_t y_w, + * wl_fixed_t x_noacc, wl_fixed_t y_noacc ) + * { + * SFG_Window* win = fgStructure.CurrentWindow; + * win->State.MouseX = wl_fixed_to_int( x_w ); + * win->State.MouseY = wl_fixed_to_int( y_w ); + * INVOKE_WCB( *win, Passive, ( win->State.MouseX, + * win->State.MouseY ) ); + * } + * static const struct _wl_relative_pointer_listener + * fghRelativeListener = + * { + * fghRelativeMotion + * }; + * + * static void fghLockedLocked( void* data, struct _wl_locked_pointer + * pointer, uint32_t serial ) + * { + * fgPlatformRememberState(); + * fgPlatformSetCursor( win, GLUT_CURSOR_NONE ): + * } + * static void fghLockedUnlocked( void* data, struct _wl_locked_pointer + * pointer ) + * { + * fgPlatformRestoreState(); + * } + * static const struct _wl_locked_pointer_listener + * fghLockedListener = + * { + * fghLockedLocked, + * fghLockedUnlocked + * }; + */ + + +static struct wl_cursor* saved_cursor; + +/* + * Remembers the current visual settings, so that + * we can change them and restore later... + */ +void fgPlatformRememberState( void ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + saved_cursor = win->Window.pContext.cursor; +} + +/* + * Restores the previously remembered visual settings + */ +void fgPlatformRestoreState( void ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + win->Window.pContext.cursor = saved_cursor; +} + +/* + * * Private function to get the virtual maximum screen extent + * */ +GLvoid fgPlatformGetGameModeVMaxExtent( SFG_Window* window, int* x, int* y ) +{ + /* + * under Wayland, just return the size of the window, + * at least until we start messing with the outputs... + */ + *x = window->State.Width; + *y = window->State.Height; +} + +/* + * Changes the current display mode to match user's settings + */ +GLboolean fgPlatformChangeDisplayMode( GLboolean haveToTest ) +{ + /* Such a protocol is being studied in Wayland */ + return GL_FALSE; +} + + +void fgPlatformEnterGameMode( void ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + struct wl_region* region; + + region = wl_compositor_create_region ( + fgDisplay.pDisplay.compositor ); + wl_region_add( region, 0, 0, + win->State.Width, + win->State.Height ); + /* + * relative_pointer = + * _wl_relative_pointer_manager_get_relative_pointer ( + * relative_pointer_manager, + * fgDisplay.pDisplay.seat ); + * _wl_relative_pointer_add_listener( relative_pointer, + * &fghRelativeListener, + * NULL ); + * locked_pointer = _wl_pointer_lock_lock_pointer ( + * pointer_lock, + * win->Window.pContext.surface, + * fgDisplay.pDisplay.seat, + * NULL); + * _wl_locked_pointer_add_listener( locked_pointer, + * &fghLockedListener, + * NULL ); + */ + wl_region_destroy( region ); +} + +void fgPlatformLeaveGameMode( void ) +{ + /* + * _wl_locked_pointer_destroy( locked_pointer ); + * _wl_relative_pointer_release( relative_pointer ); + */ +} + diff --git a/src/wayland/fg_init_wl.c b/src/wayland/fg_init_wl.c new file mode 100644 index 0000000..7b7cd6a --- /dev/null +++ b/src/wayland/fg_init_wl.c @@ -0,0 +1,134 @@ +/* + * fg_init_wl.c + * + * Various freeglut Wayland initialization functions. + * + * Copyright (c) 2015 Manuel Bachmann. All Rights Reserved. + * Written by Manuel Bachmann, + * Creation date: Tue Mar 17, 2015 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * MANUEL BACHMANN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#define FREEGLUT_BUILDING_LIB +#include +#include +#include "fg_internal.h" +#include "egl/fg_init_egl.h" + +void fgPlatformInitialiseInputDevices( void ); +void fgPlatformCloseInputDevices( void ); + + +static void fghRegistryGlobal( void* data, + struct wl_registry* registry, + uint32_t id, + const char* interface, + uint32_t version ) +{ + SFG_PlatformDisplay* pDisplay = data; + + if ( ! strcmp( interface, "wl_compositor" ) ) + pDisplay->compositor = wl_registry_bind ( registry, id, + &wl_compositor_interface, 1 ); + else if ( ! strcmp( interface, "wl_shell" ) ) + pDisplay->shell = wl_registry_bind ( registry, id, + &wl_shell_interface, 1 ); + else if ( ! strcmp( interface, "wl_seat" ) ) + pDisplay->seat = wl_registry_bind ( registry, id, + &wl_seat_interface, 1 ); + else if ( ! strcmp( interface, "wl_shm" ) ) + pDisplay->shm = wl_registry_bind ( registry, id, + &wl_shm_interface, 1 ); +} +static void fghRegistryGlobalRemove( void* data, + struct wl_registry* registry, + uint32_t id ) +{ +} +static const struct wl_registry_listener fghRegistryListener = +{ + fghRegistryGlobal, + fghRegistryGlobalRemove +}; + + +static void fghInitialiseCursorTheme(void) +{ + fgDisplay.pDisplay.cursor_theme = wl_cursor_theme_load ( + "default", 32, + fgDisplay.pDisplay.shm ); +}; + +void fgPlatformInitialize( const char* displayName ) +{ + fgDisplay.pDisplay.display = wl_display_connect( NULL ); + + if( fgDisplay.pDisplay.display == NULL ) + fgError( "failed to connect to a Wayland compositor" ); + + fgDisplay.pDisplay.registry = wl_display_get_registry( + fgDisplay.pDisplay.display ); + wl_registry_add_listener( fgDisplay.pDisplay.registry, + &fghRegistryListener, + &fgDisplay.pDisplay ); + wl_display_roundtrip( fgDisplay.pDisplay.display ); + + if( fgDisplay.pDisplay.compositor == NULL || + fgDisplay.pDisplay.shell == NULL || + fgDisplay.pDisplay.seat == NULL || + fgDisplay.pDisplay.shm == NULL ) + fgError( "failed to discover all needed compositor interfaces" ); + + fghInitialiseCursorTheme(); + + fghPlatformInitializeEGL(); + + /* Get start time */ + fgState.Time = fgSystemTime(); + + fgState.Initialised = GL_TRUE; + + atexit(fgDeinitialize); + + /* InputDevice uses GlutTimerFunc(), so fgState.Initialised must be TRUE */ + fgPlatformInitialiseInputDevices(); +} + + +void fgPlatformDeinitialiseInputDevices ( void ) +{ + fgPlatformCloseInputDevices(); + + fgState.InputDevsInitialised = GL_FALSE; +} + + +void fgPlatformCloseDisplay ( void ) +{ + wl_cursor_theme_destroy( fgDisplay.pDisplay.cursor_theme ); + + wl_shm_destroy( fgDisplay.pDisplay.shm ); + wl_seat_destroy( fgDisplay.pDisplay.seat ); + wl_shell_destroy( fgDisplay.pDisplay.shell ); + wl_compositor_destroy( fgDisplay.pDisplay.compositor ); + wl_registry_destroy( fgDisplay.pDisplay.registry ); + + wl_display_disconnect( fgDisplay.pDisplay.display ); +} + diff --git a/src/wayland/fg_input_devices_wl.c b/src/wayland/fg_input_devices_wl.c new file mode 100644 index 0000000..bb32f98 --- /dev/null +++ b/src/wayland/fg_input_devices_wl.c @@ -0,0 +1,439 @@ +/* + * fg_input_devices_wl.c + * + * Handles Wayland input devices : keyboard, pointer, touchscreen. + * + * Written by Manuel Bachmann 2015 + * + * Copyright (c) 2015 Manuel Bachmann. All Rights Reserved. + * Creation date: Thur Mar 19 2015 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * MANUEL BACHMANN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifdef __linux__ +#include +#else +#define BTN_LEFT 0x110 +#define BTN_RIGHT 0x111 +#define BTN_MIDDLE 0x112 +#endif +#include +#include +#include "../fg_internal.h" + +/* + * This function will effectively set the pointer (mouse) cursor + * depending on the GLUT_CURSOR_* choice. + */ +void fghPointerSetCursor( SFG_Window* window, + struct wl_pointer* pointer, + uint32_t serial ) +{ + struct wl_cursor_image* image; + struct wl_buffer* buffer; + + image = window->Window.pContext.cursor->images[0]; + buffer = wl_cursor_image_get_buffer( image ); + + wl_surface_attach( window->Window.pContext.cursor_surface, buffer, + 0, 0 ); + wl_surface_damage( window->Window.pContext.cursor_surface, 0, 0, + image->width, image->height ); + wl_surface_commit( window->Window.pContext.cursor_surface ); + + wl_pointer_set_cursor( pointer, serial, + window->Window.pContext.cursor_surface, + image->hotspot_x, image->hotspot_y ); +} + +/* + * This function will interpret a keyboard keysym, and call the + * possible callbacks accordingly. + */ +void fghKeyboardInterpretKeysym( SFG_Window* window, + uint32_t key, + xkb_keysym_t sym, + uint32_t state ) +{ + FGCBKeyboardUC keyboard_cb; + FGCBSpecialUC special_cb; + FGCBUserData keyboard_ud; + FGCBUserData special_ud; + char string[16]; + int special = -1; + + /* GLUT API tells us to have two separate callbacks, one for + * the ASCII translateable keypresses, and one for all the + * others, which need to be translated to GLUT_KEY_Xs... */ + if( state ) + { + keyboard_cb = (FGCBKeyboardUC)( FETCH_WCB( *window, Keyboard )); + special_cb = (FGCBSpecialUC) ( FETCH_WCB( *window, Special )); + keyboard_ud = FETCH_USER_DATA_WCB( *window, Keyboard ); + special_ud = FETCH_USER_DATA_WCB( *window, Special ); + } + else + { + keyboard_cb = (FGCBKeyboardUC)( FETCH_WCB( *window, KeyboardUp )); + special_cb = (FGCBSpecialUC) ( FETCH_WCB( *window, SpecialUp )); + keyboard_ud = FETCH_USER_DATA_WCB( *window, KeyboardUp ); + special_ud = FETCH_USER_DATA_WCB( *window, SpecialUp ); + } + + switch( sym ) + { + case XKB_KEY_F1: special = GLUT_KEY_F1; break; + case XKB_KEY_F2: special = GLUT_KEY_F2; break; + case XKB_KEY_F3: special = GLUT_KEY_F3; break; + case XKB_KEY_F4: special = GLUT_KEY_F4; break; + case XKB_KEY_F5: special = GLUT_KEY_F5; break; + case XKB_KEY_F6: special = GLUT_KEY_F6; break; + case XKB_KEY_F7: special = GLUT_KEY_F7; break; + case XKB_KEY_F8: special = GLUT_KEY_F8; break; + case XKB_KEY_F9: special = GLUT_KEY_F9; break; + case XKB_KEY_F10: special = GLUT_KEY_F10; break; + case XKB_KEY_F11: special = GLUT_KEY_F11; break; + case XKB_KEY_F12: special = GLUT_KEY_F12; break; + case XKB_KEY_Left: special = GLUT_KEY_LEFT; break; + case XKB_KEY_Right: special = GLUT_KEY_RIGHT; break; + case XKB_KEY_Up: special = GLUT_KEY_UP; break; + case XKB_KEY_Down: special = GLUT_KEY_DOWN; break; + case XKB_KEY_Page_Up: special = GLUT_KEY_PAGE_UP; break; + case XKB_KEY_Page_Down: special = GLUT_KEY_PAGE_DOWN; break; + case XKB_KEY_Home: special = GLUT_KEY_HOME; break; + case XKB_KEY_End: special = GLUT_KEY_END; break; + case XKB_KEY_Insert: special = GLUT_KEY_INSERT; break; + case XKB_KEY_Num_Lock: special = GLUT_KEY_NUM_LOCK; break; + case XKB_KEY_Begin: special = GLUT_KEY_BEGIN; break; + case XKB_KEY_Delete: special = GLUT_KEY_DELETE; break; + case XKB_KEY_Shift_L: special = GLUT_KEY_SHIFT_L; break; + case XKB_KEY_Shift_R: special = GLUT_KEY_SHIFT_R; break; + case XKB_KEY_Control_L: special = GLUT_KEY_CTRL_L; break; + case XKB_KEY_Control_R: special = GLUT_KEY_CTRL_R; break; + case XKB_KEY_Alt_L: special = GLUT_KEY_ALT_L; break; + case XKB_KEY_Alt_R: special = GLUT_KEY_ALT_R; break; + } + + if( special_cb && (special != -1) ) + { + fgSetWindow( window ); + special_cb( special, window->State.MouseX, window->State.MouseY, special_ud ); + } + else if( keyboard_cb && (special == -1) ) + { + fgSetWindow( window ); + xkb_keysym_to_utf8( sym, string, sizeof( string ) ); + keyboard_cb( string[0], window->State.MouseX, window->State.MouseY, keyboard_ud ); + } +} + + +/* + * Touchscreen section + * For now, let us pretend it is a mouse with only one button + */ +static void fghTouchDown( void* data, struct wl_touch* touch, + uint32_t serial, uint32_t time, + struct wl_surface* surface, + int32_t id, + wl_fixed_t x_w, wl_fixed_t y_w ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + win->State.MouseX = wl_fixed_to_int( x_w ); + win->State.MouseY = wl_fixed_to_int( y_w ); + INVOKE_WCB( *win, Mouse, ( GLUT_LEFT_BUTTON, + GLUT_DOWN, + win->State.MouseX, + win->State.MouseY ) ); +} +static void fghTouchUp( void* data, struct wl_touch* touch, + uint32_t serial, uint32_t time, + int32_t id ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + INVOKE_WCB( *win, Mouse, ( GLUT_LEFT_BUTTON, + GLUT_UP, + win->State.MouseX, + win->State.MouseY ) ); +} +static void fghTouchMotion( void* data, struct wl_touch* touch, + uint32_t time, int32_t id, + wl_fixed_t x_w, wl_fixed_t y_w ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + win->State.MouseX = wl_fixed_to_int( x_w ); + win->State.MouseY = wl_fixed_to_int( y_w ); + INVOKE_WCB( *win, Motion, ( win->State.MouseX, + win->State.MouseY ) ); +} +static void fghTouchFrame( void* data, struct wl_touch* touch ) +{ +} +static void fghTouchCancel( void* data, struct wl_touch* touch ) +{ +} +static const struct wl_touch_listener fghTouchListener = +{ + fghTouchDown, + fghTouchUp, + fghTouchMotion, + fghTouchFrame, + fghTouchCancel +}; + + +/* + * Pointer (mouse) section + */ +static void fghPointerEnter( void* data, struct wl_pointer* pointer, + uint32_t serial, + struct wl_surface* surface, + wl_fixed_t x_w, wl_fixed_t y_w ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + fghPointerSetCursor( win, pointer, serial ); + win->State.MouseX = wl_fixed_to_int( x_w ); + win->State.MouseY = wl_fixed_to_int( y_w ); + INVOKE_WCB( *win, Entry, ( GLUT_ENTERED ) ); +} +static void fghPointerLeave( void* data, struct wl_pointer* pointer, + uint32_t serial, + struct wl_surface* surface ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + INVOKE_WCB( *win, Entry, ( GLUT_LEFT ) ); +} +static void fghPointerMotion( void* data, struct wl_pointer* pointer, + uint32_t time, + wl_fixed_t x_w, wl_fixed_t y_w ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + win->State.MouseX = wl_fixed_to_int( x_w ); + win->State.MouseY = wl_fixed_to_int( y_w ); + + if ( win->Window.pContext.pointer_button_pressed ) + INVOKE_WCB( *win, Motion, ( win->State.MouseX, + win->State.MouseY ) ); + else + INVOKE_WCB( *win, Passive, ( win->State.MouseX, + win->State.MouseY ) ); +} +static void fghPointerButton( void* data, struct wl_pointer* pointer, + uint32_t serial, uint32_t time, + uint32_t button, uint32_t state ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + int button_f; + + switch( button ) + { + case BTN_LEFT: + button_f = GLUT_LEFT_BUTTON; + break; + case BTN_RIGHT: + button_f = GLUT_RIGHT_BUTTON; + break; + case BTN_MIDDLE: + button_f = GLUT_MIDDLE_BUTTON; + break; + } + + win->Window.pContext.pointer_button_pressed = + state ? GL_TRUE : GL_FALSE; + + INVOKE_WCB( *win, Mouse, ( button_f, + state ? GLUT_DOWN : GLUT_UP , + win->State.MouseX, + win->State.MouseY ) ); +} +static void fghPointerAxis( void* data, struct wl_pointer* pointer, + uint32_t time, uint32_t axis, + wl_fixed_t value ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + int direction = wl_fixed_to_int( value ); + + INVOKE_WCB( *win, MouseWheel, ( 0, + direction , + win->State.MouseX, + win->State.MouseY ) ); +} +static const struct wl_pointer_listener fghPointerListener = +{ + fghPointerEnter, + fghPointerLeave, + fghPointerMotion, + fghPointerButton, + fghPointerAxis +}; + + +/* + * Keyboard section + */ +static void fghKeyboardKeymap( void* data, struct wl_keyboard* keyboard, + uint32_t format, int fd, uint32_t size ) +{ + SFG_PlatformDisplay* pDisplay = data; + char* keymap_str; + struct xkb_keymap* keymap; + + keymap_str = mmap( NULL, size, PROT_READ, MAP_SHARED, fd, 0 ); + keymap = xkb_keymap_new_from_string( pDisplay->xkb_context, + keymap_str, + XKB_KEYMAP_FORMAT_TEXT_V1, + 0 ); + munmap( keymap_str, size ); + + if( pDisplay->xkb_state ) + xkb_state_unref( pDisplay->xkb_state ); + pDisplay->xkb_state = xkb_state_new( keymap ); +} +static void fghKeyboardEnter( void* data, struct wl_keyboard* keyboard, + uint32_t serial, struct wl_surface* surface, + struct wl_array* keys ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + INVOKE_WCB( *win, Entry, ( GLUT_ENTERED ) ); +} +static void fghKeyboardLeave( void* data, struct wl_keyboard* keyboard, + uint32_t serial, struct wl_surface* surface ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + INVOKE_WCB( *win, Entry, ( GLUT_LEFT ) ); +} +static void fghKeyboardKey( void* data, struct wl_keyboard* keyboard, + uint32_t serial, uint32_t time, + uint32_t key, uint32_t state ) +{ + SFG_PlatformDisplay* pDisplay = data; + SFG_Window* win = fgStructure.CurrentWindow; + const xkb_keysym_t* syms; + + xkb_state_key_get_syms( pDisplay->xkb_state, + key + 8, &syms ); + fghKeyboardInterpretKeysym( win, key, syms[0], state ); +} +static void fghKeyboardModifiers( void* data, struct wl_keyboard* keyboard, + uint32_t serial, uint32_t mods_depr, + uint32_t mods_latch, uint32_t mods_lock, + uint32_t group ) +{ +} +static const struct wl_keyboard_listener fghKeyboardListener = +{ + fghKeyboardKeymap, + fghKeyboardEnter, + fghKeyboardLeave, + fghKeyboardKey, + fghKeyboardModifiers +}; + + +/* + * Discover potential input device(s) (keyboard, pointer, touch) + */ +static void fghSeatCapabilities( void* data, + struct wl_seat* seat, + enum wl_seat_capability capabilities ) +{ + SFG_PlatformDisplay* pDisplay = data; + + if( capabilities & WL_SEAT_CAPABILITY_KEYBOARD ) + { + pDisplay->xkb_context = xkb_context_new ( 0 ); + pDisplay->keyboard = wl_seat_get_keyboard( seat ); + wl_keyboard_add_listener( pDisplay->keyboard, + &fghKeyboardListener, + pDisplay ); + } + + if( capabilities & WL_SEAT_CAPABILITY_POINTER ) + { + pDisplay->pointer = wl_seat_get_pointer( seat ); + wl_pointer_add_listener( pDisplay->pointer, + &fghPointerListener, + pDisplay ); + } + + if( capabilities & WL_SEAT_CAPABILITY_TOUCH ) + { + pDisplay->touch = wl_seat_get_touch( seat ); + wl_touch_add_listener( pDisplay->touch, + &fghTouchListener, + pDisplay ); + } +} +static const struct wl_seat_listener fghSeatListener = +{ + fghSeatCapabilities +}; + + +/* + * Try initializing the input device(s) + */ +void fgPlatformInitialiseInputDevices( void ) +{ + wl_seat_add_listener( fgDisplay.pDisplay.seat, + &fghSeatListener, + &fgDisplay.pDisplay ); + + wl_display_roundtrip( fgDisplay.pDisplay.display ); +} + +/* + * Try closing the input device(s) + */ +void fgPlatformCloseInputDevices( void ) +{ + if( fgDisplay.pDisplay.touch ) + wl_touch_destroy( fgDisplay.pDisplay.touch ); + if( fgDisplay.pDisplay.pointer ) + wl_pointer_destroy( fgDisplay.pDisplay.pointer ); + if( fgDisplay.pDisplay.keyboard ) + wl_keyboard_destroy( fgDisplay.pDisplay.keyboard ); + if( fgDisplay.pDisplay.xkb_state ) + xkb_state_unref( fgDisplay.pDisplay.xkb_state ); + if( fgDisplay.pDisplay.xkb_context ) + xkb_context_unref( fgDisplay.pDisplay.xkb_context ); +} + + +/* + * Wayland backend will not be implementing spaceball at all + */ +void fgPlatformInitializeSpaceball( void ) +{ +} +void fgPlatformSpaceballClose( void ) +{ +} +void fgPlatformSpaceballSetWindow( SFG_Window *window ) +{ +} +int fgPlatformHasSpaceball( void ) +{ + return 0; +} +int fgPlatformSpaceballNumButtons( void ) +{ + return 0; +} + diff --git a/src/wayland/fg_internal_wl.h b/src/wayland/fg_internal_wl.h new file mode 100644 index 0000000..4672d4e --- /dev/null +++ b/src/wayland/fg_internal_wl.h @@ -0,0 +1,174 @@ +/* + * fg_internal_wl.h + * + * The freeglut library private include file. + * + * Copyright (c) 2015 Manuel Bachmann. All Rights Reserved. + * Written by Manuel Bachmann, + * Creation date: Tue Mar 17, 2015 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * MANUEL BACHMANN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef FREEGLUT_INTERNAL_WL_H +#define FREEGLUT_INTERNAL_WL_H + + +/* -- PLATFORM-SPECIFIC INCLUDES ------------------------------------------- */ +#include "egl/fg_internal_egl.h" +#include +#include +#include +#include + + +/* -- GLOBAL TYPE DEFINITIONS ---------------------------------------------- */ +/* The structure used by display initialization in fg_init.c */ +typedef struct tagSFG_PlatformDisplay SFG_PlatformDisplay; +struct tagSFG_PlatformDisplay +{ + struct tagSFG_PlatformDisplayEGL egl; + + struct wl_display* display; /* The display we are being run in */ + struct wl_registry* registry; /* The global interface registry */ + struct wl_compositor* compositor; /* The compositor */ + struct wl_shell* shell; /* The shell, AKA window manager */ + struct wl_seat* seat; /* The seat, references input devices */ + + struct xkb_context* xkb_context; /* The global XKB keyboard context */ + struct xkb_state* xkb_state; /* The current XKB keyboard state */ + struct wl_keyboard* keyboard; /* The keyboard input device */ + struct wl_pointer* pointer; /* The pointer input device (mouse) */ + struct wl_touch* touch; /* The touchscreen input device */ + + struct wl_shm* shm; /* The software rendering engine */ + struct wl_cursor_theme* cursor_theme; /* The pointer cursor theme */ +}; + + +/* The structure used by window creation in fg_window.c */ +typedef struct tagSFG_PlatformContext SFG_PlatformContext; +struct tagSFG_PlatformContext +{ + struct tagSFG_PlatformContextEGL egl; + GLboolean pointer_button_pressed; + + struct wl_surface* surface; /* The drawing surface */ + struct wl_shell_surface* shsurface; /* The shell surface, has states */ + struct wl_egl_window* egl_window; /* Binding between WL/EGL surfaces */ + + struct wl_cursor* cursor; /* The active cursor */ + struct wl_surface* cursor_surface; /* The active cursor surface */ +}; + + +/* The window state description. This structure should be kept portable. */ +typedef struct tagSFG_PlatformWindowState SFG_PlatformWindowState; +struct tagSFG_PlatformWindowState +{ + int OldWidth; /* Window width from before a resize */ + int OldHeight; /* " height " " " " */ +}; + + +/* -- JOYSTICK-SPECIFIC STRUCTURES AND TYPES ------------------------------- */ +/* + * Initial defines from "js.h" starting around line 33 with the existing "fg_joystick.c" + * interspersed + */ +# ifdef HAVE_SYS_IOCTL_H +# include +# endif +# ifdef HAVE_FCNTL_H +# include +# endif + +#include +#include + +# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) +# define HAVE_USB_JS 1 + +# include +# define JS_DATA_TYPE joystick +# define JS_RETURN (sizeof(struct JS_DATA_TYPE)) +# endif + +# if defined(__linux__) +# include + +/* check the joystick driver version */ +# if defined(JS_VERSION) && JS_VERSION >= 0x010000 +# define JS_NEW +# endif +# else /* Not BSD or Linux */ +# ifndef JS_RETURN + + /* + * We'll put these values in and that should + * allow the code to at least compile when there is + * no support. The JS open routine should error out + * and shut off all the code downstream anyway and if + * the application doesn't use a joystick we'll be fine. + */ + + struct JS_DATA_TYPE + { + int buttons; + int x; + int y; + }; + +# define JS_RETURN (sizeof(struct JS_DATA_TYPE)) +# endif +# endif + +/* XXX It might be better to poll the operating system for the numbers of buttons and + * XXX axes and then dynamically allocate the arrays. + */ +# define _JS_MAX_AXES 16 +typedef struct tagSFG_PlatformJoystick SFG_PlatformJoystick; +struct tagSFG_PlatformJoystick +{ +# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) + struct os_specific_s *os; +# endif + +# ifdef JS_NEW + struct js_event js; + int tmp_buttons; + float tmp_axes [ _JS_MAX_AXES ]; +# else + struct JS_DATA_TYPE js; +# endif + + char fname [ 128 ]; + int fd; +}; + + +/* Menu font and color definitions */ +#define FREEGLUT_MENU_FONT GLUT_BITMAP_HELVETICA_18 + +#define FREEGLUT_MENU_PEN_FORE_COLORS {0.0f, 0.0f, 0.0f, 1.0f} +#define FREEGLUT_MENU_PEN_BACK_COLORS {0.70f, 0.70f, 0.70f, 1.0f} +#define FREEGLUT_MENU_PEN_HFORE_COLORS {0.0f, 0.0f, 0.0f, 1.0f} +#define FREEGLUT_MENU_PEN_HBACK_COLORS {1.0f, 1.0f, 1.0f, 1.0f} + + +#endif /* FREEGLUT_INTERNAL_WL_H */ diff --git a/src/wayland/fg_main_wl.c b/src/wayland/fg_main_wl.c new file mode 100644 index 0000000..05102e1 --- /dev/null +++ b/src/wayland/fg_main_wl.c @@ -0,0 +1,146 @@ +/* + * fg_main_wl.c + * + * The Wayland-specific windows message processing methods. + * + * Copyright (c) 2015 Manuel Bachmann. All Rights Reserved. + * Written by Manuel Bachmann, + * Creation date: Sun Mar 22 2015 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * MANUEL BACHMANN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "../fg_internal.h" +#include +#include + +void fgPlatformFullScreenToggle( SFG_Window *win ); +void fgPlatformPositionWindow( SFG_Window *window, int x, int y ); +void fgPlatformReshapeWindow( SFG_Window *window, int width, int height ); +void fgPlatformPushWindow( SFG_Window *window ); +void fgPlatformPopWindow( SFG_Window *window ); +void fgPlatformHideWindow( SFG_Window *window ); +void fgPlatformIconifyWindow( SFG_Window *window ); +void fgPlatformShowWindow( SFG_Window *window ); + + +fg_time_t fgPlatformSystemTime( void ) +{ +#ifdef CLOCK_MONOTONIC + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + return now.tv_nsec/1000000 + now.tv_sec*1000; +#elif defined(HAVE_GETTIMEOFDAY) + struct timeval now; + gettimeofday( &now, NULL ); + return now.tv_usec/1000 + now.tv_sec*1000; +#endif +} + +void fgPlatformSleepForEvents( fg_time_t msec ) +{ + struct pollfd pfd; + int err; + + pfd.fd = wl_display_get_fd( fgDisplay.pDisplay.display ); + pfd.events = POLLIN | POLLERR | POLLHUP; + + wl_display_dispatch_pending( fgDisplay.pDisplay.display ); + if ( ! wl_display_flush( fgDisplay.pDisplay.display ) ) + { + err = poll( &pfd, 1, msec ); + + if( ( -1 == err ) && ( errno != EINTR ) ) + fgWarning ( "freeglut poll() error: %d", errno ); + } +} + + +void fgPlatformProcessSingleEvent( void ) +{ + SFG_Window *win = fgStructure.CurrentWindow; + + wl_display_dispatch_pending( fgDisplay.pDisplay.display ); + INVOKE_WCB( *win, Display, ( ) ); +} + +void fgPlatformMainLoopPreliminaryWork( void ) +{ + /* Under Wayland, this is a no-op */ +} + +void fgPlatformInitWork( SFG_Window* window ) +{ + /* Under Wayland, all events happen relative to input handlers + * -> this is a no-op + */ + return; +} + +void fgPlatformPosResZordWork( SFG_Window* window, unsigned int workMask ) +{ + if( workMask & GLUT_FULL_SCREEN_WORK ) + fgPlatformFullScreenToggle( window ); + if( workMask & GLUT_POSITION_WORK ) + fgPlatformPositionWindow( window, window->State.DesiredXpos, window->State.DesiredYpos ); + if( workMask & GLUT_SIZE_WORK ) + fgPlatformReshapeWindow ( window, window->State.DesiredWidth, window->State.DesiredHeight ); + if( workMask & GLUT_ZORDER_WORK ) + { + if( window->State.DesiredZOrder < 0 ) + fgPlatformPushWindow( window ); + else + fgPlatformPopWindow( window ); + } +} + +void fgPlatformVisibilityWork( SFG_Window* window ) +{ + /* Visibility status of window gets updated in the window message handlers above + */ + SFG_Window *win = window; + switch (window->State.DesiredVisibility) + { + case DesireHiddenState: + fgPlatformHideWindow( window ); + break; + case DesireIconicState: + /* Call on top-level window */ + while (win->Parent) + win = win->Parent; + fgPlatformIconifyWindow( win ); + break; + case DesireNormalState: + fgPlatformShowWindow( window ); + break; + } +} + +/* dummy functions, not applicable on wayland */ +void fgPlatformSetColor(int idx, float r, float g, float b) +{ +} + +float fgPlatformGetColor(int idx, int comp) +{ +} + +void fgPlatformCopyColormap(int win) +{ +} diff --git a/src/wayland/fg_state_wl.c b/src/wayland/fg_state_wl.c new file mode 100644 index 0000000..06b9906 --- /dev/null +++ b/src/wayland/fg_state_wl.c @@ -0,0 +1,150 @@ +/* + * fg_state_wl.c + * + * Wayland-specific freeglut state query methods. + * + * Copyright (c) 2015 Manuel Bachmann. All Rights Reserved. + * Written by Manuel Bachmann, + * Creation date: Sun Mar 23 2015 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * MANUEL BACHMANN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" +#include "egl/fg_state_egl.h" + +int fgPlatformGlutDeviceGet ( GLenum eWhat ) +{ + switch( eWhat ) + { + case GLUT_HAS_KEYBOARD: + if( fgDisplay.pDisplay.keyboard ) + return 1; + else + return 0; + + case GLUT_HAS_MOUSE: + /* we want the touchscreen to behave like a mouse, + * so let us pretend it is one. + */ + if( fgDisplay.pDisplay.pointer || + fgDisplay.pDisplay.touch ) + return 1; + else + return 0; + + case GLUT_NUM_MOUSE_BUTTONS: + /* Wayland has no way of telling us how much buttons + * a mouse has, unless the actual event gets sent to + * the client. As we are only handling 3 buttons + * currently, return this fixed number for now. + */ + if( fgDisplay.pDisplay.pointer ) + return 3; + /* touchscreen is considered as having one button */ + else if( fgDisplay.pDisplay.touch ) + return 1; + else + return 0; + + default: + fgWarning( "glutDeviceGet(): missing enum handle %d", eWhat ); + return -1; + } +} + + +int fgPlatformGlutGet ( GLenum eWhat ) +{ + switch( eWhat ) + { + + /* + * Those calls are pointless under Wayland, so inform the user + */ + case GLUT_WINDOW_X: + case GLUT_WINDOW_Y: + { + if( fgStructure.CurrentWindow == NULL ) + { + return 0; + } + else + { + fgWarning( "glutGet(): GLUT_WINDOW_X/Y properties " + "unsupported under Wayland" ); + return -1; + } + } + + /* + * TODO : support this correctly once we will start drawing + * client-side decorations + */ + case GLUT_WINDOW_BORDER_WIDTH: + case GLUT_WINDOW_HEADER_HEIGHT: + { + if( fgStructure.CurrentWindow == NULL || + fgStructure.CurrentWindow->Parent ) + /* can't get widths/heights if no current window + * and child windows don't have borders */ + return 0; + + return 0; + } + + case GLUT_WINDOW_WIDTH: + case GLUT_WINDOW_HEIGHT: + { + if( fgStructure.CurrentWindow == NULL ) + return 0; + + switch ( eWhat ) + { + case GLUT_WINDOW_WIDTH: + return fgStructure.CurrentWindow->State.Width; + case GLUT_WINDOW_HEIGHT: + return fgStructure.CurrentWindow->State.Height; + } + } + + /* Colormap size is handled in a bit different way than all the rest */ + case GLUT_WINDOW_COLORMAP_SIZE: + { + if( fgStructure.CurrentWindow == NULL ) + { + return 0; + } + else + { + int result = 0; + if ( ! eglGetConfigAttrib( fgDisplay.pDisplay.egl.Display, + fgStructure.CurrentWindow->Window.pContext.egl.Config, + EGL_BUFFER_SIZE, &result ) ) + fgError( "eglGetConfigAttrib(EGL_BUFFER_SIZE) failed" ); + + return result; + } + } + + default: + return fghPlatformGlutGetEGL( eWhat ); + } +} + diff --git a/src/wayland/fg_structure_wl.c b/src/wayland/fg_structure_wl.c new file mode 100644 index 0000000..ad77cdd --- /dev/null +++ b/src/wayland/fg_structure_wl.c @@ -0,0 +1,40 @@ +/* + * fg_structure_wl.c + * + * Windows and menus need tree structure for Wayland + * + * Copyright (c) 2015 Manuel Bachmann. All Rights Reserved. + * Written by Manuel Bachmann, + * Creation date: Tue Mar 17, 2015 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * MANUEL BACHMANN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" +#include "egl/fg_structure_egl.h" + +extern SFG_Structure fgStructure; + +void fgPlatformCreateWindow( SFG_Window *window ) +{ + fghPlatformCreateWindowEGL( window ); + + window->State.pWState.OldHeight = window->State.pWState.OldWidth = -1; +} + diff --git a/src/wayland/fg_window_wl.c b/src/wayland/fg_window_wl.c new file mode 100644 index 0000000..e4c3da4 --- /dev/null +++ b/src/wayland/fg_window_wl.c @@ -0,0 +1,310 @@ +/* + * fg_window_wl.c + * + * Window management methods for Wayland + * + * Copyright (c) 2015 Manuel Bachmann. All Rights Reserved. + * Written by Manuel Bachmann, + * Creation date: Tue Mar 17, 2015 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * MANUEL BACHMANN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#define FREEGLUT_BUILDING_LIB +#include +#include "../fg_internal.h" +#include "egl/fg_window_egl.h" +#define fghCreateNewContext fghCreateNewContextEGL + +extern void fghOnReshapeNotify( SFG_Window *window, int width, int height, GLboolean forceNotify ); +void fgPlatformReshapeWindow( SFG_Window *window, int width, int height ); +void fgPlatformIconifyWindow( SFG_Window *window ); + + +static void fghShSurfacePing( void* data, + struct wl_shell_surface* shsurface, + uint32_t serial ) +{ + wl_shell_surface_pong( shsurface, serial ); +} +static void fghShSurfaceConfigure( void* data, + struct wl_shell_surface* shsurface, + uint32_t edges, + int32_t width, int32_t height ) +{ + SFG_Window* window = data; + fgPlatformReshapeWindow( window, width, height ); +} +static const struct wl_shell_surface_listener fghShSurfaceListener = +{ + fghShSurfacePing, + fghShSurfaceConfigure, + NULL +}; + + +static int fghToggleFullscreen(void) +{ + SFG_Window* win = fgStructure.CurrentWindow; + + if ( ! win->State.IsFullscreen ) + { + win->State.pWState.OldWidth = win->State.Width; + win->State.pWState.OldHeight = win->State.Height; + wl_shell_surface_set_fullscreen( win->Window.pContext.shsurface, + WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, + 0, NULL ); + } + else + { + fgPlatformReshapeWindow( win, win->State.pWState.OldWidth, + win->State.pWState.OldHeight ); + wl_shell_surface_set_toplevel( win->Window.pContext.shsurface ); + } + + return 0; +} + +void fgPlatformOpenWindow( SFG_Window* window, const char* title, + GLboolean positionUse, int x, int y, + GLboolean sizeUse, int w, int h, + GLboolean gameMode, GLboolean isSubWindow ) +{ + /* Save the display mode if we are creating a menu window */ + if( window->IsMenu && ( ! fgStructure.MenuContext ) ) + fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB ; + + fghChooseConfig( &window->Window.pContext.egl.Config ); + + if( ! window->Window.pContext.egl.Config ) + { + /* + * The "fghChooseConfig" returned a null meaning that the visual + * context is not available. + * Try a couple of variations to see if they will work. + */ + if( fgState.DisplayMode & GLUT_MULTISAMPLE ) + { + fgState.DisplayMode &= ~GLUT_MULTISAMPLE ; + fghChooseConfig( &window->Window.pContext.egl.Config ); + fgState.DisplayMode |= GLUT_MULTISAMPLE; + } + } + + FREEGLUT_INTERNAL_ERROR_EXIT( window->Window.pContext.egl.Config != NULL, + "EGL configuration with necessary capabilities " + "not found", "fgOpenWindow" ); + + if( ! positionUse ) + x = y = -1; /* default window position */ + if( ! sizeUse ) + w = h = 300; /* default window size */ + + /* Create the cursor */ + window->Window.pContext.cursor = wl_cursor_theme_get_cursor( + fgDisplay.pDisplay.cursor_theme, + "left_ptr" ); + window->Window.pContext.cursor_surface = wl_compositor_create_surface( + fgDisplay.pDisplay.compositor ); + + /* Create the main surface */ + window->Window.pContext.surface = wl_compositor_create_surface( + fgDisplay.pDisplay.compositor ); + + /* Create the shell surface with respects to the parent/child tree */ + window->Window.pContext.shsurface = wl_shell_get_shell_surface( + fgDisplay.pDisplay.shell, + window->Window.pContext.surface ); + wl_shell_surface_add_listener( window->Window.pContext.shsurface, + &fghShSurfaceListener, window ); + + if( title) + wl_shell_surface_set_title( window->Window.pContext.shsurface, title ); + + if( gameMode ) + { + window->State.IsFullscreen = GL_TRUE; + wl_shell_surface_set_fullscreen( window->Window.pContext.shsurface, + WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, + 0, NULL ); + } + else if( !isSubWindow && !window->IsMenu ) + { + wl_shell_surface_set_toplevel( window->Window.pContext.shsurface ); + } + else + { + wl_shell_surface_set_transient( window->Window.pContext.shsurface, + window->Parent->Window.pContext.surface, + x, y, 0 ); + } + + /* Create the Wl_EGL_Window */ + window->Window.Context = fghCreateNewContext( window ); + window->Window.pContext.egl_window = wl_egl_window_create( + window->Window.pContext.surface, + w, h); + window->Window.pContext.egl.Surface = eglCreateWindowSurface( + fgDisplay.pDisplay.egl.Display, + window->Window.pContext.egl.Config, + (EGLNativeWindowType)window->Window.pContext.egl_window, + NULL ); + eglMakeCurrent( fgDisplay.pDisplay.egl.Display, window->Window.pContext.egl.Surface, + window->Window.pContext.egl.Surface, window->Window.Context ); + + window->Window.pContext.pointer_button_pressed = GL_FALSE; +} + + +/* + * Request a window resize + */ +void fgPlatformReshapeWindow( SFG_Window *window, int width, int height ) +{ + fghOnReshapeNotify(window, width, height, GL_FALSE); + + if( window->Window.pContext.egl_window ) + wl_egl_window_resize( window->Window.pContext.egl_window, + width, height, 0, 0 ); +} + + +/* + * Closes a window, destroying the frame and OpenGL context + */ +void fgPlatformCloseWindow( SFG_Window* window ) +{ + fghPlatformCloseWindowEGL(window); + + if ( window->Window.pContext.egl_window ) + wl_egl_window_destroy( window->Window.pContext.egl_window ); + if ( window->Window.pContext.shsurface ) + wl_shell_surface_destroy( window->Window.pContext.shsurface ); + if ( window->Window.pContext.surface ) + wl_surface_destroy( window->Window.pContext.surface ); + if ( window->Window.pContext.cursor_surface ) + wl_surface_destroy( window->Window.pContext.cursor_surface ); +} + + +/* + * This function re-creates the window assets if they + * have been destroyed + */ +void fgPlatformShowWindow( SFG_Window *window ) +{ + if ( ! window->Window.pContext.egl_window || + ! window->Window.pContext.shsurface || + ! window->Window.pContext.surface) + { + fgPlatformCloseWindow( window ); + fgPlatformOpenWindow( window, "", /* TODO : save the title for further use */ + GL_TRUE, window->State.Xpos, window->State.Ypos, + GL_TRUE, window->State.Width, window->State.Height, + (GLboolean)(window->State.IsFullscreen ? GL_TRUE : GL_FALSE), + (GLboolean)(window->Parent ? GL_TRUE : GL_FALSE) ); + } + else + { + /* TODO : support this once we start using xdg-shell + * + * xdg_surface_present( window->Window.pContext.shsurface, 0 ); + * INVOKE_WCB( *window, WindowStatus, ( GLUT_FULLY_RETAINED ) ); + * window->State.Visible = GL_TRUE; + */ + fgWarning( "glutShownWindow(): function unsupported for an already existing" + " window under Wayland" ); + } +} + +/* + * This function hides the specified window + */ +void fgPlatformHideWindow( SFG_Window *window ) +{ + fgPlatformIconifyWindow( window ); +} + +/* + * Iconify the specified window (top-level windows only) + */ +void fgPlatformIconifyWindow( SFG_Window *window ) +{ + /* TODO : support this once we start using xdg-shell + * + * xdg_surface_set_minimized( window->Window.pContext.shsurface ); + * INVOKE_WCB( *window, WindowStatus, ( GLUT_HIDDEN ) ); + * window->State.Visible = GL_FALSE; + */ + fgWarning( "glutIconifyWindow(): function unsupported under Wayland" ); +} + +/* + * Set the current window's title + */ +void fgPlatformGlutSetWindowTitle( const char* title ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + wl_shell_surface_set_title( win->Window.pContext.shsurface, title ); +} + +/* + * Set the current window's iconified title + */ +void fgPlatformGlutSetIconTitle( const char* title ) +{ + fgPlatformGlutSetWindowTitle( title ); +} + +/* + * Change the specified window's position + */ +void fgPlatformPositionWindow( SFG_Window *window, int x, int y ) +{ + /* pointless under Wayland */ + fgWarning( "glutPositionWindow(): function unsupported under Wayland" ); +} + +/* + * Lowers the specified window (by Z order change) + */ +void fgPlatformPushWindow( SFG_Window *window ) +{ + /* pointless under Wayland */ + fgWarning( "glutPushWindow(): function unsupported under Wayland" ); +} + +/* + * Raises the specified window (by Z order change) + */ +void fgPlatformPopWindow( SFG_Window *window ) +{ + /* pointless under Wayland */ + fgWarning( "glutPopWindow(): function unsupported under Wayland" ); +} + +/* + * Toggle the window's full screen state. + */ +void fgPlatformFullScreenToggle( SFG_Window *win ) +{ + if(fghToggleFullscreen() != -1) { + win->State.IsFullscreen = !win->State.IsFullscreen; + } +} + diff --git a/src/x11/fg_cmap_x11.c b/src/x11/fg_cmap_x11.c new file mode 100644 index 0000000..c7a5fb1 --- /dev/null +++ b/src/x11/fg_cmap_x11.c @@ -0,0 +1,75 @@ +/* fg_cmap_x11.c + * + * X11 implementation of the colormap functions + * + * Copyright (C) 2022 John Tsiombikas + * Creation date: Tue August 30 2022 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include +#include "../fg_internal.h" + +void fgPlatformSetColor(int idx, float r, float g, float b) +{ + Display *dpy = fgDisplay.pDisplay.Display; + Colormap cmap = fgStructure.CurrentWindow->Window.cmap; + int cmap_size = fgStructure.CurrentWindow->Window.cmap_size; + XColor color; + + if(idx >= 0 && idx < cmap_size) { + color.pixel = idx; + color.red = (unsigned short)(r * 65535.0f); + color.green = (unsigned short)(g * 65535.0f); + color.blue = (unsigned short)(b * 65535.0f); + color.flags = DoRed | DoGreen | DoBlue; + XStoreColor(dpy, cmap, &color); + } +} + +float fgPlatformGetColor(int idx, int comp) +{ + Display *dpy = fgDisplay.pDisplay.Display; + Colormap cmap = fgStructure.CurrentWindow->Window.cmap; + int cmap_size = fgStructure.CurrentWindow->Window.cmap_size; + XColor color; + + if(idx < 0 || idx >= cmap_size) { + return -1.0f; + } + + color.pixel = idx; + XQueryColor(dpy, cmap, &color); + switch(comp) { + case GLUT_RED: + return color.red / 65535.0f; + case GLUT_GREEN: + return color.green / 65535.0f; + case GLUT_BLUE: + return color.blue / 65535.0f; + default: + break; + } + return -1.0f; +} + +void fgPlatformCopyColormap(int win) +{ + /* TODO */ + fgWarning("glutCopyColormap not implemented yet on X11"); +} diff --git a/src/x11/fg_cursor_x11.c b/src/x11/fg_cursor_x11.c new file mode 100644 index 0000000..9d15900 --- /dev/null +++ b/src/x11/fg_cursor_x11.c @@ -0,0 +1,184 @@ +/* + * fg_cursor_x11.c + * + * The Windows-specific mouse cursor related stuff. + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by John F. Fay, + * Creation date: Sun Feb 5, 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "../fg_internal.h" + +/* This code is for Posix/X11, Solaris, and OSX */ +#include + +/* + * A factory method for an empty cursor + */ +static Cursor getEmptyCursor( void ) +{ + static Cursor cursorNone = None; + if( cursorNone == None ) { + char cursorNoneBits[ 32 ]; + XColor dontCare; + Pixmap cursorNonePixmap; + memset( cursorNoneBits, 0, sizeof( cursorNoneBits ) ); + memset( &dontCare, 0, sizeof( dontCare ) ); + cursorNonePixmap = XCreateBitmapFromData ( fgDisplay.pDisplay.Display, + fgDisplay.pDisplay.RootWindow, + cursorNoneBits, 16, 16 ); + if( cursorNonePixmap != None ) { + cursorNone = XCreatePixmapCursor( fgDisplay.pDisplay.Display, + cursorNonePixmap, cursorNonePixmap, + &dontCare, &dontCare, 0, 0 ); + XFreePixmap( fgDisplay.pDisplay.Display, cursorNonePixmap ); + } + } + return cursorNone; +} + +typedef struct tag_cursorCacheEntry cursorCacheEntry; +struct tag_cursorCacheEntry { + unsigned int cursorShape; /* an XC_foo value */ + Cursor cachedCursor; /* None if the corresponding cursor has + not been created yet */ + Display *dpy; /* display used to allocate this cursor */ +}; + +/* + * Note: The arrangement of the table below depends on the fact that + * the "normal" GLUT_CURSOR_* values start a 0 and are consecutive. + */ +static cursorCacheEntry cursorCache[] = { + { XC_arrow, None, 0 }, /* GLUT_CURSOR_RIGHT_ARROW */ + { XC_top_left_arrow, None, 0 }, /* GLUT_CURSOR_LEFT_ARROW */ + { XC_hand1, None, 0 }, /* GLUT_CURSOR_INFO */ + { XC_pirate, None, 0 }, /* GLUT_CURSOR_DESTROY */ + { XC_question_arrow, None, 0 }, /* GLUT_CURSOR_HELP */ + { XC_exchange, None, 0 }, /* GLUT_CURSOR_CYCLE */ + { XC_spraycan, None, 0 }, /* GLUT_CURSOR_SPRAY */ + { XC_watch, None, 0 }, /* GLUT_CURSOR_WAIT */ + { XC_xterm, None, 0 }, /* GLUT_CURSOR_TEXT */ + { XC_crosshair, None, 0 }, /* GLUT_CURSOR_CROSSHAIR */ + { XC_sb_v_double_arrow, None, 0 }, /* GLUT_CURSOR_UP_DOWN */ + { XC_sb_h_double_arrow, None, 0 }, /* GLUT_CURSOR_LEFT_RIGHT */ + { XC_top_side, None, 0 }, /* GLUT_CURSOR_TOP_SIDE */ + { XC_bottom_side, None, 0 }, /* GLUT_CURSOR_BOTTOM_SIDE */ + { XC_left_side, None, 0 }, /* GLUT_CURSOR_LEFT_SIDE */ + { XC_right_side, None, 0 }, /* GLUT_CURSOR_RIGHT_SIDE */ + { XC_top_left_corner, None, 0 }, /* GLUT_CURSOR_TOP_LEFT_CORNER */ + { XC_top_right_corner, None, 0 }, /* GLUT_CURSOR_TOP_RIGHT_CORNER */ + { XC_bottom_right_corner, None, 0 }, /* GLUT_CURSOR_BOTTOM_RIGHT_CORNER */ + { XC_bottom_left_corner, None, 0 } /* GLUT_CURSOR_BOTTOM_LEFT_CORNER */ +}; + +void fgPlatformSetCursor ( SFG_Window *window, int cursorID ) +{ + Cursor cursor; + /* + * XXX FULL_CROSSHAIR demotes to plain CROSSHAIR. Old GLUT allows + * for this, but if there is a system that easily supports a full- + * window (or full-screen) crosshair, we might consider it. + */ + int cursorIDToUse = + ( cursorID == GLUT_CURSOR_FULL_CROSSHAIR ) ? GLUT_CURSOR_CROSSHAIR : cursorID; + + if( ( cursorIDToUse >= 0 ) && + ( cursorIDToUse < sizeof( cursorCache ) / sizeof( cursorCache[0] ) ) ) { + cursorCacheEntry *entry = &cursorCache[ cursorIDToUse ]; + + /* the second clause forces an invalidation of the cached cursor, if it was + * created through a different display connection. + * This can only happen, in the extremely rare case where the user program calls the + * freeglut extension glutLeaveMainLoop, and then re-initializes freeglut and + * starts over. + */ + if( entry->cachedCursor == None || entry->dpy != fgDisplay.pDisplay.Display ) { + entry->cachedCursor = + XCreateFontCursor( fgDisplay.pDisplay.Display, entry->cursorShape ); + entry->dpy = fgDisplay.pDisplay.Display; + } + cursor = entry->cachedCursor; + } else { + switch( cursorIDToUse ) + { + case GLUT_CURSOR_NONE: + cursor = getEmptyCursor( ); + break; + + case GLUT_CURSOR_INHERIT: + cursor = None; + break; + + default: + fgError( "Unknown cursor type: %d", cursorIDToUse ); + return; + } + } + + if ( cursorIDToUse == GLUT_CURSOR_INHERIT ) { + XUndefineCursor( fgDisplay.pDisplay.Display, window->Window.Handle ); + } else if ( cursor != None ) { + XDefineCursor( fgDisplay.pDisplay.Display, window->Window.Handle, cursor ); + } else if ( cursorIDToUse != GLUT_CURSOR_NONE ) { + fgError( "Failed to create cursor" ); + } +} + + +void fgPlatformWarpPointer ( int x, int y ) +{ + XWarpPointer( + fgDisplay.pDisplay.Display, + None, + fgStructure.CurrentWindow->Window.Handle, + 0, 0, 0, 0, + x, y + ); + /* Make the warp visible immediately. */ + XFlush( fgDisplay.pDisplay.Display ); +} + +void fghPlatformGetCursorPos(const SFG_Window *window, GLboolean client, SFG_XYUse *mouse_pos) +{ + /* Get current pointer location in screen coordinates (if client is false or window is NULL), else + * Get current pointer location relative to top-left of client area of window (if client is true and window is not NULL) + */ + Window w = (client && window && window->Window.Handle)? window->Window.Handle: fgDisplay.pDisplay.RootWindow; + Window junk_window; + unsigned int junk_mask; + int clientX, clientY; + + XQueryPointer(fgDisplay.pDisplay.Display, w, + &junk_window, &junk_window, + &mouse_pos->X, &mouse_pos->Y, /* Screen coords relative to root window's top-left */ + &clientX, &clientY, /* Client coords relative to window's top-left */ + &junk_mask); + + if (client && window && window->Window.Handle) + { + mouse_pos->X = clientX; + mouse_pos->Y = clientY; + } + + mouse_pos->Use = GL_TRUE; +} diff --git a/src/x11/fg_display_x11_glx.c b/src/x11/fg_display_x11_glx.c new file mode 100644 index 0000000..5f68680 --- /dev/null +++ b/src/x11/fg_display_x11_glx.c @@ -0,0 +1,36 @@ +/* + * fg_display_x11.c + * + * Display message posting, context buffer swapping. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Copied for Platform code by Evan Felix + * Creation date: Thur Feb 2 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "../fg_internal.h" + +void fgPlatformGlutSwapBuffers( SFG_PlatformDisplay *pDisplayPtr, SFG_Window* CurrentWindow ) +{ + glXSwapBuffers( pDisplayPtr->Display, CurrentWindow->Window.Handle ); +} + diff --git a/src/x11/fg_ext_x11.c b/src/x11/fg_ext_x11.c new file mode 100644 index 0000000..6b63287 --- /dev/null +++ b/src/x11/fg_ext_x11.c @@ -0,0 +1,61 @@ +/* + * fg_ext.c + * + * Functions related to OpenGL extensions. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Copied for Platform code by Evan Felix + * Creation date: Thur Feb 2 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#define GLX_GLXEXT_PROTOTYPES +#include +#include "../fg_internal.h" + +GLUTproc fgPlatformGetGLUTProcAddress( const char* procName ) +{ + /* optimization: quick initial check */ + if( strncmp( procName, "glut", 4 ) != 0 ) + return NULL; + +#define CHECK_NAME(x) if( strcmp( procName, #x ) == 0) return (GLUTproc)x; + CHECK_NAME(glutJoystickFunc); + CHECK_NAME(glutForceJoystickFunc); + CHECK_NAME(glutGameModeString); + CHECK_NAME(glutEnterGameMode); + CHECK_NAME(glutLeaveGameMode); + CHECK_NAME(glutGameModeGet); +#undef CHECK_NAME + + return NULL; +} + + +#ifndef EGL_VERSION_1_0 +SFG_Proc fgPlatformGetProcAddress( const char *procName ) +{ +#if defined( GLX_ARB_get_proc_address ) + return (SFG_Proc)glXGetProcAddressARB( ( const GLubyte * )procName ); +#else + return NULL; +#endif +} +#endif diff --git a/src/x11/fg_gamemode_x11.c b/src/x11/fg_gamemode_x11.c new file mode 100644 index 0000000..c4711c0 --- /dev/null +++ b/src/x11/fg_gamemode_x11.c @@ -0,0 +1,612 @@ +/* + * fg_gamemode_x11.c + * + * The game mode handling code. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Copied for Platform code by Evan Felix + * Creation date: Thur Feb 2 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include +#include +#include "../fg_internal.h" + +/* we'll try to use XR&R if it's available at compile-time, and at runtime, and the user + * hasn't explicitly disabled it by setting the FREEGLUT_NO_XRANDR env-var. + */ +static int use_xrandr(void) +{ +#ifdef HAVE_X11_EXTENSIONS_XRANDR_H + int event_base, error_base; + if(!XRRQueryExtension(fgDisplay.pDisplay.Display, &event_base, &error_base)) { + return 0; + } + if(getenv("FREEGLUT_NO_XRANDR")) { + return 0; + } + return 1; +#else + return 0; /* no compile-time support */ +#endif +} + +/* we'll try to use XF86VidMode if it's available at compile-time, and at runtime, and the + * user hasn't explicitly disabled it by setting the FREEGLUT_NO_XF86VM env-var. + */ +static int use_xf86vm(void) +{ +#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H + int event_base, error_base; + if(!XF86VidModeQueryExtension(fgDisplay.pDisplay.Display, &event_base, &error_base)) { + return 0; + } + if(getenv("FREEGLUT_NO_XF86VM")) { + return 0; + } + return 1; +#else + return 0; /* no compile-time support */ +#endif +} + + +#ifdef HAVE_X11_EXTENSIONS_XRANDR_H +static int xrandr_resize(int xsz, int ysz, int rate, int just_checking) +{ + int ver_major, ver_minor, use_rate; + XRRScreenConfiguration *xrr_config = 0; + Status result = -1; + + /* NOTE: we have already determined that XR&R is available and enabled before calling this */ + + XRRQueryVersion(fgDisplay.pDisplay.Display, &ver_major, &ver_minor); + + /* we only heed the rate if we CAN actually use it (Xrandr >= 1.1) and + * the user actually cares about it (rate > 0) + */ + use_rate = ( rate > 0 ) && ( ( ver_major > 1 ) || + ( ( ver_major == 1 ) && ( ver_minor >= 1 ) ) ); + + /* this loop is only so that the whole thing will be repeated if someone + * else changes video mode between our query of the current information and + * the attempt to change it. + */ + do { + XRRScreenSize *ssizes; + short *rates; + Rotation rot; + int i, ssizes_count, rates_count, curr, res_idx = -1; + Time timestamp, cfg_timestamp; + + if(xrr_config) { + XRRFreeScreenConfigInfo(xrr_config); + } + + if(!(xrr_config = XRRGetScreenInfo(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow))) { + fgWarning("XRRGetScreenInfo failed"); + break; + } + ssizes = XRRConfigSizes(xrr_config, &ssizes_count); + curr = XRRConfigCurrentConfiguration(xrr_config, &rot); + timestamp = XRRConfigTimes(xrr_config, &cfg_timestamp); + + /* if either of xsz or ysz are unspecified, use the current values */ + if(xsz <= 0) + xsz = fgState.GameModeSize.X = ssizes[curr].width; + if(ysz <= 0) + ysz = fgState.GameModeSize.Y = ssizes[curr].height; + + + if(xsz == ssizes[curr].width && ysz == ssizes[curr].height) { + /* no need to switch, we're already in the requested resolution */ + res_idx = curr; + } else { + for(i=0; i 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) ) + if(use_rate) { + rate = fgState.GameModeRefresh; + + /* for the selected resolution, let's find out if there is + * a matching refresh rate available. + */ + rates = XRRConfigRates(xrr_config, res_idx, &rates_count); + + for(i=0; i 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) ) + if(use_rate) + result = XRRSetScreenConfigAndRate(fgDisplay.pDisplay.Display, xrr_config, + fgDisplay.pDisplay.RootWindow, res_idx, rot, rate, timestamp); + else +#endif + result = XRRSetScreenConfig(fgDisplay.pDisplay.Display, xrr_config, + fgDisplay.pDisplay.RootWindow, res_idx, rot, timestamp); + + } while(result == RRSetConfigInvalidTime); + + if(xrr_config) { + XRRFreeScreenConfigInfo(xrr_config); + } + + if(result == 0) { + return 0; + } + + return -1; +} +#endif /* HAVE_X11_EXTENSIONS_XRANDR_H */ + +/* + * Remembers the current visual settings, so that + * we can change them and restore later... + */ +void fgPlatformRememberState( void ) +{ + /* + * Remember the current pointer location before going fullscreen + * for restoring it later: + */ + Window junk_window; + unsigned int junk_mask; + + XQueryPointer(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow, + &junk_window, &junk_window, + &fgDisplay.pDisplay.DisplayPointerX, &fgDisplay.pDisplay.DisplayPointerY, + &fgDisplay.pDisplay.DisplayPointerX, &fgDisplay.pDisplay.DisplayPointerY, &junk_mask); + +# ifdef HAVE_X11_EXTENSIONS_XRANDR_H + if(use_xrandr()) { + XRRScreenConfiguration *xrr_config; + XRRScreenSize *ssizes; + Rotation rot; + int ssize_count, curr; + + if((xrr_config = XRRGetScreenInfo(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow))) { + ssizes = XRRConfigSizes(xrr_config, &ssize_count); + curr = XRRConfigCurrentConfiguration(xrr_config, &rot); + + fgDisplay.pDisplay.prev_xsz = ssizes[curr].width; + fgDisplay.pDisplay.prev_ysz = ssizes[curr].height; + fgDisplay.pDisplay.prev_refresh = -1; + +# if ( RANDR_MAJOR > 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) ) + if(fgState.GameModeRefresh != -1) { + fgDisplay.pDisplay.prev_refresh = XRRConfigCurrentRate(xrr_config); + } +# endif + + fgDisplay.pDisplay.prev_size_valid = 1; + + XRRFreeScreenConfigInfo(xrr_config); + } + } +# endif /* HAVE_X11_EXTENSIONS_XRANDR_H */ + + /* + * This highly depends on the XFree86 extensions, + * not approved as X Consortium standards + */ +# ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H + if(use_xf86vm()) { + /* + * Remember the current ViewPort location of the screen to be able to + * restore the ViewPort on LeaveGameMode(): + */ + if( !XF86VidModeGetViewPort( + fgDisplay.pDisplay.Display, + fgDisplay.pDisplay.Screen, + &fgDisplay.pDisplay.DisplayViewPortX, + &fgDisplay.pDisplay.DisplayViewPortY ) ) + fgWarning( "XF86VidModeGetViewPort failed" ); + + + /* Query the current display settings: */ + fgDisplay.pDisplay.DisplayModeValid = + XF86VidModeGetModeLine( + fgDisplay.pDisplay.Display, + fgDisplay.pDisplay.Screen, + &fgDisplay.pDisplay.DisplayModeClock, + &fgDisplay.pDisplay.DisplayMode + ); + + if( !fgDisplay.pDisplay.DisplayModeValid ) + fgWarning( "XF86VidModeGetModeLine failed" ); + } +# endif + +} + +/* + * Restores the previously remembered visual settings + */ +void fgPlatformRestoreState( void ) +{ + /* Restore the remembered pointer position: */ + XWarpPointer( + fgDisplay.pDisplay.Display, None, fgDisplay.pDisplay.RootWindow, 0, 0, 0, 0, + fgDisplay.pDisplay.DisplayPointerX, fgDisplay.pDisplay.DisplayPointerY + ); + +#ifdef HAVE_X11_EXTENSIONS_XRANDR_H + if(use_xrandr()) { + if(fgDisplay.pDisplay.prev_size_valid) { + if(xrandr_resize(fgDisplay.pDisplay.prev_xsz, fgDisplay.pDisplay.prev_ysz, fgDisplay.pDisplay.prev_refresh, 0) != -1) { + fgDisplay.pDisplay.prev_size_valid = 0; +#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H + fgDisplay.pDisplay.DisplayModeValid = 0; +#endif + } + } + return; /* don't fall back to XF86VidMode if we have XR&R */ + } +#endif /* HAVE_X11_EXTENSIONS_XRANDR_H */ + + + +#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H + /* + * This highly depends on the XFree86 extensions, + * not approved as X Consortium standards + */ + if(use_xf86vm()) { + + if( fgDisplay.pDisplay.DisplayModeValid ) + { + XF86VidModeModeInfo** displayModes; + int i, displayModesCount; + + if( !XF86VidModeGetAllModeLines( + fgDisplay.pDisplay.Display, + fgDisplay.pDisplay.Screen, + &displayModesCount, + &displayModes ) ) + { + fgWarning( "XF86VidModeGetAllModeLines failed" ); + return; + } + + + /* + * Check every of the modes looking for one that matches our demands. + * If we find one, switch to it and restore the remembered viewport. + */ + for( i = 0; i < displayModesCount; i++ ) + { + if(displayModes[ i ]->hdisplay == fgDisplay.pDisplay.DisplayMode.hdisplay && + displayModes[ i ]->vdisplay == fgDisplay.pDisplay.DisplayMode.vdisplay && + displayModes[ i ]->dotclock == fgDisplay.pDisplay.DisplayModeClock ) + { + if( !XF86VidModeSwitchToMode( + fgDisplay.pDisplay.Display, + fgDisplay.pDisplay.Screen, + displayModes[ i ] ) ) + { + fgWarning( "XF86VidModeSwitchToMode failed" ); + break; + } + + if( !XF86VidModeSetViewPort( + fgDisplay.pDisplay.Display, + fgDisplay.pDisplay.Screen, + fgDisplay.pDisplay.DisplayViewPortX, + fgDisplay.pDisplay.DisplayViewPortY ) ) + fgWarning( "XF86VidModeSetViewPort failed" ); + + + /* + * For the case this would be the last X11 call the application + * calls exit() we've to flush the X11 output queue to have the + * commands sent to the X server before the application exits. + */ + XFlush( fgDisplay.pDisplay.Display ); + + fgDisplay.pDisplay.DisplayModeValid = 0; +#ifdef HAVE_X11_EXTENSIONS_XRANDR_H + fgDisplay.pDisplay.prev_size_valid = 0; +#endif + break; + } + } + XFree( displayModes ); + } + } +#endif /* HAVE_X11_EXTENSIONS_XF86VMODE_H */ +} + +#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H + +/* + * Checks a single display mode settings against user's preferences. + */ +static GLboolean fghCheckDisplayMode( int width, int height, int depth, int refresh ) +{ + /* The desired values should be stored in fgState structure... */ + return ( width == fgState.GameModeSize.X ) && + ( height == fgState.GameModeSize.Y ) && + ( depth == fgState.GameModeDepth ) && + ( refresh == fgState.GameModeRefresh ); +} + +/* + * Checks all display modes settings against user's preferences. + * Returns the mode number found or -1 if none could be found. + */ +static int fghCheckDisplayModes( GLboolean exactMatch, int displayModesCount, XF86VidModeModeInfo** displayModes ) +{ + int i; + for( i = 0; i < displayModesCount; i++ ) + { + /* Compute the displays refresh rate, dotclock comes in kHz. */ + int refresh = ( displayModes[ i ]->dotclock * 1000 ) / + ( displayModes[ i ]->htotal * displayModes[ i ]->vtotal ); + + if( fghCheckDisplayMode( displayModes[ i ]->hdisplay, + displayModes[ i ]->vdisplay, + fgState.GameModeDepth, + ( exactMatch ? refresh : fgState.GameModeRefresh ) ) ) { + if (!exactMatch) + { + /* Update the chosen refresh rate, otherwise a + * glutGameModeGet(GLUT_GAME_MODE_REFRESH_RATE) would not + * return the right values + */ + fgState.GameModeRefresh = refresh; + } + + return i; + } + } + return -1; +} + +#endif + +/* + * Changes the current display mode to match user's settings + */ +GLboolean fgPlatformChangeDisplayMode( GLboolean haveToTest ) +{ + GLboolean success = GL_FALSE; +#ifdef HAVE_X11_EXTENSIONS_XRANDR_H + if(use_xrandr()) { + if(xrandr_resize(fgState.GameModeSize.X, fgState.GameModeSize.Y, + fgState.GameModeRefresh, haveToTest) != -1) { + return GL_TRUE; + } + return GL_FALSE; /* don't fall back to XF86VidMode */ + } +#endif /* HAVE_X11_EXTENSIONS_XRANDR_H */ + + + /* + * This highly depends on the XFree86 extensions, + * not approved as X Consortium standards + */ +#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H + if(use_xf86vm()) { + /* + * This is also used by applications which check modes by calling + * glutGameModeGet(GLUT_GAME_MODE_POSSIBLE), so allow the check: + */ + if( haveToTest || fgDisplay.pDisplay.DisplayModeValid ) + { + XF86VidModeModeInfo** displayModes; + int i, displayModesCount; + + /* If we don't have a valid modeline in the display structure, which + * can happen if this is called from glutGameModeGet instead of + * glutEnterGameMode, then we need to query the current mode, to make + * unspecified settings to default to their current values. + */ + if(!fgDisplay.pDisplay.DisplayModeValid) { + if(!XF86VidModeGetModeLine(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.Screen, + &fgDisplay.pDisplay.DisplayModeClock, &fgDisplay.pDisplay.DisplayMode)) { + return success; + } + } + + if (fgState.GameModeSize.X == -1) + { + fgState.GameModeSize.X = fgDisplay.pDisplay.DisplayMode.hdisplay; + } + if (fgState.GameModeSize.Y == -1) + { + fgState.GameModeSize.Y = fgDisplay.pDisplay.DisplayMode.vdisplay; + } + if (fgState.GameModeDepth == -1) + { + /* can't get color depth from this, nor can we change it, do nothing + * TODO: get with XGetVisualInfo()? but then how to set? + */ + } + if (fgState.GameModeRefresh == -1) + { + /* Compute the displays refresh rate, dotclock comes in kHz. */ + int refresh = ( fgDisplay.pDisplay.DisplayModeClock * 1000 ) / + ( fgDisplay.pDisplay.DisplayMode.htotal * fgDisplay.pDisplay.DisplayMode.vtotal ); + + fgState.GameModeRefresh = refresh; + } + + /* query all possible display modes */ + if( !XF86VidModeGetAllModeLines( + fgDisplay.pDisplay.Display, + fgDisplay.pDisplay.Screen, + &displayModesCount, + &displayModes ) ) + { + fgWarning( "XF86VidModeGetAllModeLines failed" ); + return success; + } + + + /* + * Check every of the modes looking for one that matches our demands, + * ignoring the refresh rate if no exact match could be found. + */ + i = fghCheckDisplayModes( GL_TRUE, displayModesCount, displayModes ); + if( i < 0 ) { + i = fghCheckDisplayModes( GL_FALSE, displayModesCount, displayModes ); + } + success = ( i < 0 ) ? GL_FALSE : GL_TRUE; + + if( !haveToTest && success ) { + if( !XF86VidModeSwitchToMode( + fgDisplay.pDisplay.Display, + fgDisplay.pDisplay.Screen, + displayModes[ i ] ) ) + fgWarning( "XF86VidModeSwitchToMode failed" ); + } + + XFree( displayModes ); + } + } + +#endif /* HAVE_X11_EXTENSIONS_XF86VMODE_H */ + + return success; +} + + +void fgPlatformEnterGameMode( void ) +{ + + /* + * Sync needed to avoid a real race, the Xserver must have really created + * the window before we can grab the pointer into it: + */ + XSync( fgDisplay.pDisplay.Display, False ); + /* + * Grab the pointer to confine it into the window after the calls to + * XWrapPointer() which ensure that the pointer really enters the window. + * + * We also need to wait here until XGrabPointer() returns GrabSuccess, + * otherwise the new window is not viewable yet and if the next function + * (XSetInputFocus) is called with a not yet viewable window, it will exit + * the application which we have to aviod, so wait until it's viewable: + */ + while( GrabSuccess != XGrabPointer( + fgDisplay.pDisplay.Display, fgStructure.GameModeWindow->Window.Handle, + TRUE, + ButtonPressMask | ButtonReleaseMask | ButtonMotionMask + | PointerMotionMask, + GrabModeAsync, GrabModeAsync, + fgStructure.GameModeWindow->Window.Handle, None, CurrentTime) ) { + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 100000000; + nanosleep(&ts, 0); + } + /* + * Change input focus to the new window. This will exit the application + * if the new window is not viewable yet, see the XGrabPointer loop above. + */ + XSetInputFocus( + fgDisplay.pDisplay.Display, + fgStructure.GameModeWindow->Window.Handle, + RevertToNone, + CurrentTime + ); + + /* Move the Pointer to the middle of the fullscreen window */ + XWarpPointer( + fgDisplay.pDisplay.Display, + None, + fgDisplay.pDisplay.RootWindow, + 0, 0, 0, 0, + fgState.GameModeSize.X/2, fgState.GameModeSize.Y/2 + ); + +#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H + if(use_xf86vm()) { + + if( fgDisplay.pDisplay.DisplayModeValid ) + { + int x, y; + Window child; + + /* Change to viewport to the window topleft edge: */ + if( !XF86VidModeSetViewPort( fgDisplay.pDisplay.Display, fgDisplay.pDisplay.Screen, 0, 0 ) ) + fgWarning( "XF86VidModeSetViewPort failed" ); + + /* + * Final window repositioning: It could be avoided using an undecorated + * window using override_redirect, but this * would possily require + * more changes and investigation. + */ + + /* Get the current position of the drawable area on screen */ + XTranslateCoordinates( + fgDisplay.pDisplay.Display, + fgStructure.CurrentWindow->Window.Handle, + fgDisplay.pDisplay.RootWindow, + 0, 0, &x, &y, + &child + ); + + /* Move the decorataions out of the topleft corner of the display */ + XMoveWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle, + -x, -y); + } + } + +#endif /* HAVE_X11_EXTENSIONS_XF86VMODE_H */ + + /* Grab the keyboard, too */ + XGrabKeyboard( + fgDisplay.pDisplay.Display, + fgStructure.GameModeWindow->Window.Handle, + FALSE, + GrabModeAsync, GrabModeAsync, + CurrentTime + ); + +} + +void fgPlatformLeaveGameMode( void ) +{ + XUngrabPointer( fgDisplay.pDisplay.Display, CurrentTime ); + XUngrabKeyboard( fgDisplay.pDisplay.Display, CurrentTime ); +} + diff --git a/src/x11/fg_glutfont_definitions_x11.c b/src/x11/fg_glutfont_definitions_x11.c new file mode 100644 index 0000000..d086a99 --- /dev/null +++ b/src/x11/fg_glutfont_definitions_x11.c @@ -0,0 +1,115 @@ +/* + * freeglut_glutfont_definitions_x11.c + * + * Bitmap and stroke fonts displaying. + * + * Copyright (c) 2003 Stephen J. Baker (whether he wants it or not). + * All Rights Reserved. + * Written by John F. Fay , who releases the + * copyright over to the "freeglut" project lead. + * Creation date: Mon July 21 2003 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * This file is necessary for the *nix version of "freeglut" because the + * original GLUT defined its font variables in rather an unusual way. + * Publicly, in "glut.h", they were defined as "void *". Privately, + * in one of the source code files, they were defined as pointers to a + * structure. Most compilers and linkers are satisfied with the "void *" + * and don't go any farther, but some of them balked. In particular, + * when compiling with "freeglut" and then trying to run using the GLUT + * ".so" library, some of them would give an error. So we are having to + * create this file to define the variables as pointers to an unusual + * structure to match GLUT. + */ + +/* + * freeglut_internal.h uses some GL types, but including the GL header portably + * is a bit tricky, so we include freeglut_std.h here, which contains the + * necessary machinery. But this poses another problem, caused by the ugly + * original definition of the font constants in "classic" GLUT: They are defined + * as void* externally, so we move them temporarily out of the way by AN EXTREME + * CPP HACK. + */ + +#define glutStrokeRoman glutStrokeRomanIGNOREME +#define glutStrokeMonoRoman glutStrokeMonoRomanIGNOREME +#define glutBitmap9By15 glutBitmap9By15IGNOREME +#define glutBitmap8By13 glutBitmap8By13IGNOREME +#define glutBitmapTimesRoman10 glutBitmapTimesRoman10IGNOREME +#define glutBitmapTimesRoman24 glutBitmapTimesRoman24IGNOREME +#define glutBitmapHelvetica10 glutBitmapHelvetica10IGNOREME +#define glutBitmapHelvetica12 glutBitmapHelvetica12IGNOREME +#define glutBitmapHelvetica18 glutBitmapHelvetica18IGNOREME + +#include + +#undef glutStrokeRoman +#undef glutStrokeMonoRoman +#undef glutBitmap9By15 +#undef glutBitmap8By13 +#undef glutBitmapTimesRoman10 +#undef glutBitmapTimesRoman24 +#undef glutBitmapHelvetica10 +#undef glutBitmapHelvetica12 +#undef glutBitmapHelvetica18 + +#include "../fg_internal.h" + +struct freeglutStrokeFont +{ + const char *name ; + int num_chars ; + void *ch ; + float top ; + float bottom ; +}; + +struct freeglutBitmapFont +{ + const char *name ; + const int num_chars ; + const int first ; + const void *ch ; +}; + + +static struct freeglutStrokeFont glutStrokeRoman_ ; +static struct freeglutStrokeFont glutStrokeMonoRoman_ ; + +static struct freeglutBitmapFont glutBitmap9By15_ ; +static struct freeglutBitmapFont glutBitmap8By13_ ; +static struct freeglutBitmapFont glutBitmapTimesRoman10_ ; +static struct freeglutBitmapFont glutBitmapTimesRoman24_ ; +static struct freeglutBitmapFont glutBitmapHelvetica10_ ; +static struct freeglutBitmapFont glutBitmapHelvetica12_ ; +static struct freeglutBitmapFont glutBitmapHelvetica18_ ; + + +void *glutStrokeRoman = &glutStrokeRoman_ ; +void *glutStrokeMonoRoman = &glutStrokeMonoRoman_ ; + +void *glutBitmap9By15 = &glutBitmap9By15_ ; +void *glutBitmap8By13 = &glutBitmap8By13_ ; +void *glutBitmapTimesRoman10 = &glutBitmapTimesRoman10_ ; +void *glutBitmapTimesRoman24 = &glutBitmapTimesRoman24_ ; +void *glutBitmapHelvetica10 = &glutBitmapHelvetica10_ ; +void *glutBitmapHelvetica12 = &glutBitmapHelvetica12_ ; +void *glutBitmapHelvetica18 = &glutBitmapHelvetica18_ ; diff --git a/src/x11/fg_init_x11.c b/src/x11/fg_init_x11.c new file mode 100644 index 0000000..d2907c9 --- /dev/null +++ b/src/x11/fg_init_x11.c @@ -0,0 +1,302 @@ +/* + * fg_init_x11.c + * + * Various freeglut initialization functions. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Copied for Platform code by Evan Felix + * Creation date: Thur Feb 2 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#define FREEGLUT_BUILDING_LIB +#include /* LONG_MAX */ +#include +#include "fg_internal.h" +#include "fg_init.h" +#include "egl/fg_init_egl.h" + +/* Return the atom associated with "name". */ +static Atom fghGetAtom(const char * name) +{ + return XInternAtom(fgDisplay.pDisplay.Display, name, False); +} + +/* + * Check if "property" is set on "window". The property's values are returned + * through "data". If the property is set and is of type "type", return the + * number of elements in "data". Return zero otherwise. In both cases, use + * "Xfree()" to free "data". + */ +static int fghGetWindowProperty(Window window, + Atom property, + Atom type, + unsigned char ** data) +{ + /* + * Caller always has to use "Xfree()" to free "data", since + * "XGetWindowProperty() always allocates one extra byte in prop_return + * [i.e. "data"] (even if the property is zero length) [..]". + */ + + int status; /* Returned by "XGetWindowProperty". */ + + Atom type_returned; + int temp_format; /* Not used. */ + unsigned long number_of_elements; + unsigned long temp_bytes_after; /* Not used. */ + + + status = XGetWindowProperty(fgDisplay.pDisplay.Display, + window, + property, + 0, + LONG_MAX, + False, + type, + &type_returned, + &temp_format, + &number_of_elements, + &temp_bytes_after, + data); + + FREEGLUT_INTERNAL_ERROR_EXIT(status == Success, + "XGetWindowProperty failled", + "fghGetWindowProperty"); + + if (type_returned != type) + { + number_of_elements = 0; + } + + return number_of_elements; +} + +/* Check if the window manager is NET WM compliant. */ +static int fghNetWMSupported(void) +{ + Atom wm_check; + Window ** window_ptr_1; + + int number_of_windows; + int net_wm_supported; + + + net_wm_supported = 0; + + wm_check = fghGetAtom("_NET_SUPPORTING_WM_CHECK"); + window_ptr_1 = malloc(sizeof(Window *)); + + /* + * Check that the window manager has set this property on the root window. + * The property must be the ID of a child window. + */ + number_of_windows = fghGetWindowProperty(fgDisplay.pDisplay.RootWindow, + wm_check, + XA_WINDOW, + (unsigned char **) window_ptr_1); + if (number_of_windows == 1) + { + Window ** window_ptr_2; + + window_ptr_2 = malloc(sizeof(Window *)); + + /* Check that the window has the same property set to the same value. */ + number_of_windows = fghGetWindowProperty(**window_ptr_1, + wm_check, + XA_WINDOW, + (unsigned char **) window_ptr_2); + if ((number_of_windows == 1) && (**window_ptr_1 == **window_ptr_2)) + { + /* NET WM compliant */ + net_wm_supported = 1; + } + + XFree(*window_ptr_2); + free(window_ptr_2); + } + + XFree(*window_ptr_1); + free(window_ptr_1); + + return net_wm_supported; +} + +/* Check if "hint" is present in "property" for "window". */ +int fgHintPresent(Window window, Atom property, Atom hint) +{ + Atom *atoms; + int number_of_atoms; + int supported; + int i; + + supported = 0; + + number_of_atoms = fghGetWindowProperty(window, + property, + XA_ATOM, + (unsigned char **) &atoms); + for (i = 0; i < number_of_atoms; i++) + { + if (atoms[i] == hint) + { + supported = 1; + break; + } + } + + XFree(atoms); + return supported; +} + +/* + * A call to this function should initialize all the display stuff... + */ +void fgPlatformInitialize( const char* displayName ) +{ + fgDisplay.pDisplay.Display = XOpenDisplay( displayName ); + + if( fgDisplay.pDisplay.Display == NULL ) + fgError( "failed to open display '%s'", XDisplayName( displayName ) ); + + if ( fgState.XSyncSwitch ) + XSynchronize(fgDisplay.pDisplay.Display, True); + +#ifdef EGL_VERSION_1_0 + fghPlatformInitializeEGL(); +#else + if( !glXQueryExtension( fgDisplay.pDisplay.Display, NULL, NULL ) ) + fgError( "OpenGL GLX extension not supported by display '%s'", + XDisplayName( displayName ) ); + + /* This forces AMD Catalyst drivers to initialize and register a shutdown + * function, which must be done before our own call to atexit to prevent + * a crash if glutMainLoop is not called or is not exited cleanly. + * (see bug #206) + */ + glXQueryExtensionsString( fgDisplay.pDisplay.Display, + DefaultScreen( fgDisplay.pDisplay.Display )); +#endif + + fgDisplay.pDisplay.Screen = DefaultScreen( fgDisplay.pDisplay.Display ); + fgDisplay.pDisplay.RootWindow = RootWindow( + fgDisplay.pDisplay.Display, + fgDisplay.pDisplay.Screen + ); + + fgDisplay.ScreenWidth = DisplayWidth( + fgDisplay.pDisplay.Display, + fgDisplay.pDisplay.Screen + ); + fgDisplay.ScreenHeight = DisplayHeight( + fgDisplay.pDisplay.Display, + fgDisplay.pDisplay.Screen + ); + + fgDisplay.ScreenWidthMM = DisplayWidthMM( + fgDisplay.pDisplay.Display, + fgDisplay.pDisplay.Screen + ); + fgDisplay.ScreenHeightMM = DisplayHeightMM( + fgDisplay.pDisplay.Display, + fgDisplay.pDisplay.Screen + ); + + fgDisplay.pDisplay.Connection = ConnectionNumber( fgDisplay.pDisplay.Display ); + + /* Create the window deletion atom */ + fgDisplay.pDisplay.DeleteWindow = fghGetAtom("WM_DELETE_WINDOW"); + + /* Create the state and full screen atoms */ + fgDisplay.pDisplay.State = None; + fgDisplay.pDisplay.StateFullScreen = None; + fgDisplay.pDisplay.NetWMPid = None; + fgDisplay.pDisplay.ClientMachine = None; + + fgDisplay.pDisplay.NetWMSupported = fghNetWMSupported(); + + if (fgDisplay.pDisplay.NetWMSupported) + { + const Atom supported = fghGetAtom("_NET_SUPPORTED"); + const Atom state = fghGetAtom("_NET_WM_STATE"); + + /* Check if the state hint is supported. */ + if (fgHintPresent(fgDisplay.pDisplay.RootWindow, supported, state)) + { + const Atom full_screen = fghGetAtom("_NET_WM_STATE_FULLSCREEN"); + + fgDisplay.pDisplay.State = state; + + /* Check if the window manager supports full screen. */ + /** Check "_NET_WM_ALLOWED_ACTIONS" on our window instead? **/ + if (fgHintPresent(fgDisplay.pDisplay.RootWindow, supported, full_screen)) + { + fgDisplay.pDisplay.StateFullScreen = full_screen; + } + } + + fgDisplay.pDisplay.NetWMPid = fghGetAtom("_NET_WM_PID"); + fgDisplay.pDisplay.ClientMachine = fghGetAtom("WM_CLIENT_MACHINE"); + } + + /* Get start time */ + fgState.Time = fgSystemTime(); + + + fgState.Initialised = GL_TRUE; + + atexit(fgDeinitialize); + + /* InputDevice uses GlutTimerFunc(), so fgState.Initialised must be TRUE */ + fgInitialiseInputDevices(); +} + +void fgPlatformDeinitialiseInputDevices ( void ) +{ + fghCloseInputDevices (); + + fgState.JoysticksInitialised = GL_FALSE; + fgState.InputDevsInitialised = GL_FALSE; +} + + +void fgPlatformCloseDisplay ( void ) +{ + /* + * Make sure all X-client data we have created will be destroyed on + * display closing + */ + XSetCloseDownMode( fgDisplay.pDisplay.Display, DestroyAll ); + + /* + * Close the display connection, destroying all windows we have + * created so far + */ + XCloseDisplay( fgDisplay.pDisplay.Display ); +} + + +#ifndef EGL_VERSION_1_0 +void fgPlatformDestroyContext ( SFG_PlatformDisplay pDisplay, SFG_WindowContextType MContext ) +{ + /* Note that the MVisualInfo is not owned by the MenuContext! */ + glXDestroyContext( pDisplay.Display, MContext ); +} +#endif diff --git a/src/x11/fg_input_devices_x11.c b/src/x11/fg_input_devices_x11.c new file mode 100644 index 0000000..e5bd55a --- /dev/null +++ b/src/x11/fg_input_devices_x11.c @@ -0,0 +1,123 @@ +/* + * fg_input_devices_x11.c + * + * Handles miscellaneous input devices via direct serial-port access. + * Proper X11 XInput device support is not yet supported. + * Also lacks Mac support. + * + * Written by Joe Krahn 2005 + * + * Copyright (c) 2005 Stephen J. Baker. All Rights Reserved. + * Copied for Platform code by Evan Felix + * Creation date: Thur Feb 2 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA OR STEPHEN J. BAKER BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include "../fg_internal.h" + +#include +#include +#include +#include +#include +#include +#include + +struct _serialport { + int fd; + struct termios termio, termio_save; +}; + +typedef struct _serialport SERIALPORT; + +void fg_serial_flush ( SERIALPORT *port ); + +/*****************************************************************/ + +/* + * Try initializing the input device(s) + */ +void fgPlatformRegisterDialDevice ( const char *dial_device ) +{ +} + +SERIALPORT *fg_serial_open ( const char *device ) +{ + int fd; + struct termios termio; + SERIALPORT *port; + + fd = open(device, O_RDWR | O_NONBLOCK ); + if (fd <0) { + perror(device); + return NULL; + } + + port = malloc(sizeof(SERIALPORT)); + memset(port, 0, sizeof(SERIALPORT)); + port->fd = fd; + + /* save current port settings */ + tcgetattr(fd,&port->termio_save); + + memset(&termio, 0, sizeof(termio)); + termio.c_cflag = CS8 | CREAD | HUPCL ; + termio.c_iflag = IGNPAR | IGNBRK ; + termio.c_cc[VTIME] = 0; /* inter-character timer */ + termio.c_cc[VMIN] = 1; /* block read until 1 chars received, when blocking I/O */ + + cfsetispeed(&termio, B9600); + cfsetospeed(&termio, B9600); + tcsetattr(fd,TCSANOW,&termio); + + fg_serial_flush(port); + return port; +} + +void fg_serial_close(SERIALPORT *port) +{ + if (port) + { + /* restore old port settings */ + tcsetattr(port->fd,TCSANOW,&port->termio_save); + close(port->fd); + free(port); + } +} + +int fg_serial_getchar(SERIALPORT *port) +{ + unsigned char ch; + if (!port) return EOF; + if (read(port->fd,&ch,1)) return ch; + return EOF; +} + +int fg_serial_putchar(SERIALPORT *port, unsigned char ch) +{ + if (!port) return 0; + return write(port->fd,&ch,1); +} + +void fg_serial_flush ( SERIALPORT *port ) +{ + tcflush ( port->fd, TCIOFLUSH ); +} diff --git a/src/x11/fg_internal_x11.h b/src/x11/fg_internal_x11.h new file mode 100644 index 0000000..fb6f901 --- /dev/null +++ b/src/x11/fg_internal_x11.h @@ -0,0 +1,231 @@ +/* + * fg_internal_x11.h + * + * The freeglut library private include file. + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by Diederick C. Niehorster, + * Creation date: Fri Jan 20, 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef FREEGLUT_INTERNAL_X11_H +#define FREEGLUT_INTERNAL_X11_H + + +/* -- PLATFORM-SPECIFIC INCLUDES ------------------------------------------- */ +#ifdef EGL_VERSION_1_0 +#include "egl/fg_internal_egl.h" +#else +#include "x11/fg_internal_x11_glx.h" +#endif +#include +#include +#include +#include +#include +#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H +# include +#endif +#ifdef HAVE_X11_EXTENSIONS_XRANDR_H +# include +#endif + + +/* -- GLOBAL TYPE DEFINITIONS ---------------------------------------------- */ +/* The structure used by display initialization in fg_init.c */ +typedef struct tagSFG_PlatformDisplay SFG_PlatformDisplay; +struct tagSFG_PlatformDisplay +{ + Display* Display; /* The display we are being run in. */ + int Screen; /* The screen we are about to use. */ + Window RootWindow; /* The screen's root window. */ + int Connection; /* The display's connection number */ + Atom DeleteWindow; /* The window deletion atom */ + Atom State; /* The state atom */ + Atom StateFullScreen; /* The full screen atom */ + int NetWMSupported; /* Flag for EWMH Window Managers */ + Atom NetWMPid; /* The _NET_WM_PID atom */ + Atom ClientMachine; /* The client machine name atom */ + +#ifdef HAVE_X11_EXTENSIONS_XRANDR_H + int prev_xsz, prev_ysz; + int prev_refresh; + int prev_size_valid; +#endif /* HAVE_X11_EXTENSIONS_XRANDR_H */ + +#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H + /* + * XF86VidMode may be compilable even if it fails at runtime. Therefore, + * the validity of the VidMode has to be tracked + */ + int DisplayModeValid; /* Flag that indicates runtime status*/ + XF86VidModeModeLine DisplayMode; /* Current screen's display settings */ + int DisplayModeClock; /* The display mode's refresh rate */ + int DisplayViewPortX; /* saved X location of the viewport */ + int DisplayViewPortY; /* saved Y location of the viewport */ +#endif /* HAVE_X11_EXTENSIONS_XF86VMODE_H */ + +#ifdef EGL_VERSION_1_0 + struct tagSFG_PlatformDisplayEGL egl; +#endif + + int DisplayPointerX; /* saved X location of the pointer */ + int DisplayPointerY; /* saved Y location of the pointer */ +}; + + +/* + * Make "freeglut" window handle and context types so that we don't need so + * much conditionally-compiled code later in the library. + */ +#ifndef EGL_VERSION_1_0 +typedef Window SFG_WindowHandleType; +typedef GLXContext SFG_WindowContextType; +typedef Colormap SFG_WindowColormapType; +#endif + +typedef struct tagSFG_PlatformContext SFG_PlatformContext; +struct tagSFG_PlatformContext +{ +#ifdef EGL_VERSION_1_0 + struct tagSFG_PlatformContextEGL egl; +#else +#ifdef USE_FBCONFIG + GLXFBConfig FBConfig; /* The window's FBConfig */ +#else + XVisualInfo *visinf; /* for older GLX keep the visual info */ +#endif /* !def GLX_VERSION_1_3 */ +#endif /* !def EGL_VERSION_1_0 */ +}; + + +/* Window's state description. This structure should be kept portable. */ +typedef struct tagSFG_PlatformWindowState SFG_PlatformWindowState; +struct tagSFG_PlatformWindowState +{ + int OldWidth; /* Window width from before a resize */ + int OldHeight; /* " height " " " " */ + GLboolean KeyRepeating; /* Currently in repeat mode? */ +}; + +/* -- JOYSTICK-SPECIFIC STRUCTURES AND TYPES ------------------------------- */ +/* + * Initial defines from "js.h" starting around line 33 with the existing "fg_joystick.c" + * interspersed + */ +# ifdef HAVE_SYS_IOCTL_H +# include +# endif +# ifdef HAVE_FCNTL_H +# include +# endif + +#include +#include + +# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) +# define HAVE_USB_JS 1 +# include +# define JS_DATA_TYPE joystick +# define JS_RETURN (sizeof(struct JS_DATA_TYPE)) +# endif + +# if defined(__linux__) +# include + +/* check the joystick driver version */ +# if defined(JS_VERSION) && JS_VERSION >= 0x010000 +# define JS_NEW +# endif +# else /* Not BSD or Linux */ +# ifndef JS_RETURN + + /* + * We'll put these values in and that should + * allow the code to at least compile when there is + * no support. The JS open routine should error out + * and shut off all the code downstream anyway and if + * the application doesn't use a joystick we'll be fine. + */ + + struct JS_DATA_TYPE + { + int buttons; + int x; + int y; + }; + +# define JS_RETURN (sizeof(struct JS_DATA_TYPE)) +# endif +# endif + +/* XXX It might be better to poll the operating system for the numbers of buttons and + * XXX axes and then dynamically allocate the arrays. + */ +# define _JS_MAX_AXES 16 +typedef struct tagSFG_PlatformJoystick SFG_PlatformJoystick; +struct tagSFG_PlatformJoystick +{ +# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) + struct os_specific_s *os; +# endif + +# ifdef JS_NEW + struct js_event js; + int tmp_buttons; + float tmp_axes [ _JS_MAX_AXES ]; +# else + struct JS_DATA_TYPE js; +# endif + + char fname [ 128 ]; + int fd; +}; + + +/* Menu font and color definitions */ +#define FREEGLUT_MENU_FONT GLUT_BITMAP_HELVETICA_18 + +#define FREEGLUT_MENU_PEN_FORE_COLORS {0.0f, 0.0f, 0.0f, 1.0f} +#define FREEGLUT_MENU_PEN_BACK_COLORS {0.70f, 0.70f, 0.70f, 1.0f} +#define FREEGLUT_MENU_PEN_HFORE_COLORS {0.0f, 0.0f, 0.0f, 1.0f} +#define FREEGLUT_MENU_PEN_HBACK_COLORS {1.0f, 1.0f, 1.0f, 1.0f} + + + + +/* -- PRIVATE FUNCTION DECLARATIONS ---------------------------------------- */ +/* spaceball device functions, defined in fg_spaceball.c */ +int fgIsSpaceballXEvent(const XEvent *ev); +void fgSpaceballHandleXEvent(const XEvent *ev); + +/* + * Check if "hint" is present in "property" for "window". See fg_init.c + */ +int fgHintPresent(Window window, Atom property, Atom hint); + +/* Handler for X extension Events */ +#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H +void fgHandleExtensionEvents(XEvent *ev); +void fgRegisterDevices(Display *dpy, Window win); +#endif + + +#endif /* FREEGLUT_INTERNAL_X11_H */ diff --git a/src/x11/fg_internal_x11_glx.h b/src/x11/fg_internal_x11_glx.h new file mode 100644 index 0000000..9a1d680 --- /dev/null +++ b/src/x11/fg_internal_x11_glx.h @@ -0,0 +1,90 @@ +/* + * fg_internal_x11.h + * + * The freeglut library private include file. + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Creation date: Fri Jan 20, 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef FREEGLUT_INTERNAL_X11_GLX_H +#define FREEGLUT_INTERNAL_X11_GLX_H + +#include + +/* If GLX is too old, we will fail during runtime when multisampling + is requested, but at least freeglut compiles. */ +#ifndef GLX_SAMPLE_BUFFERS +# define GLX_SAMPLE_BUFFERS 0x80A8 +#endif +#ifndef GLX_SAMPLES +# define GLX_SAMPLES 0x80A9 +#endif + + +#ifndef GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB +#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2 +#endif + +#ifndef GLX_CONTEXT_MAJOR_VERSION_ARB +#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#endif + +#ifndef GLX_CONTEXT_MINOR_VERSION_ARB +#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 +#endif + +#ifndef GLX_CONTEXT_FLAGS_ARB +#define GLX_CONTEXT_FLAGS_ARB 0x2094 +#endif + +#ifndef GLX_CONTEXT_PROFILE_MASK_ARB +#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126 +#endif + +#ifndef GLX_CONTEXT_DEBUG_BIT_ARB +#define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001 +#endif + +#ifndef GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB +#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 +#endif + +#ifndef GLX_CONTEXT_CORE_PROFILE_BIT_ARB +#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#endif + +#ifndef GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB +#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 +#endif + +#ifndef GLX_RGBA_FLOAT_TYPE +#define GLX_RGBA_FLOAT_TYPE 0x20B9 +#endif + +#ifndef GLX_RGBA_FLOAT_BIT +#define GLX_RGBA_FLOAT_BIT 0x00000004 +#endif + +#ifdef GLX_VERSION_1_3 +#define USE_FBCONFIG +#endif + +#endif diff --git a/src/x11/fg_joystick_x11.c b/src/x11/fg_joystick_x11.c new file mode 100644 index 0000000..0a13796 --- /dev/null +++ b/src/x11/fg_joystick_x11.c @@ -0,0 +1,705 @@ +/* + * fg_joystick_x11.c + * + * Joystick handling code + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Steve Baker, + * Copied for Platform code by Evan Felix + * Creation date: Thur Feb 2 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * FreeBSD port by Stephen Montgomery-Smith + * + * Redone by John Fay 2/4/04 with another look from the PLIB "js" library. + * Many thanks for Steve Baker for permission to pull from that library. + */ + +#include +#include "../fg_internal.h" +#ifdef HAVE_SYS_PARAM_H +# include +#endif + +#include + + +/* BSD defines from "jsBSD.cxx" around lines 42-270 */ + +#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + +# ifdef HAVE_USB_JS +# if defined(__NetBSD__) +# ifdef HAVE_USBHID_H +# include +# else +# include +# endif +# include +# elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +# ifdef HAVE_USBHID_H +# include +# else +# include +# endif +#if __FreeBSD_version < 800061 +# include +#else +# include +# include +#endif +# endif +# include + +/* Compatibility with older usb.h revisions */ +# if !defined(USB_MAX_DEVNAMES) && defined(MAXDEVNAMES) +# define USB_MAX_DEVNAMES MAXDEVNAMES +# endif +# endif + +struct os_specific_s { + char fname [128 ]; + int fd; + int is_analog; + /* The following structure members are specific to analog joysticks */ + struct joystick ajs; +# ifdef HAVE_USB_JS + /* The following structure members are specific to USB joysticks */ + struct hid_item *hids; + int hid_dlen; + int hid_offset; + char *hid_data_buf; + int axes_usage [ _JS_MAX_AXES ]; +# endif + /* We keep button and axes state ourselves, as they might not be updated + * on every read of a USB device + */ + int cache_buttons; + float cache_axes [ _JS_MAX_AXES ]; +}; + +/* Idents lower than USB_IDENT_OFFSET are for analog joysticks. */ +# define USB_IDENT_OFFSET 2 + +# define USBDEV "/dev/usb" +# define UHIDDEV "/dev/uhid" +# define AJSDEV "/dev/joy" + + +#endif + +#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +static int hatmap_x[9] = {0, 0, 1, 1, 1, 0, -1, -1, -1}; +static int hatmap_y[9] = {0, 1, 1, 0, -1, -1, -1, 0, 1}; + +# ifdef HAVE_USB_JS +/* +* fghJoystickFindUSBdev (and its helper, fghJoystickWalkUSBdev) try to locate +* the full name of a USB device. If /dev/usbN isn't readable, we punt and +* return the uhidN device name. We warn the user of this situation once. +*/ +static char *fghJoystickWalkUSBdev(int f, char *dev, char *out, int outlen) +{ +#if __FreeBSD_version < 800061 + struct usb_device_info di; + int i, a; + char *cp; + + for (a = 1; a < USB_MAX_DEVICES; a++) { + di.udi_addr = a; + if (ioctl(f, USB_DEVICEINFO, &di) != 0) + return NULL; + for (i = 0; i < USB_MAX_DEVNAMES; i++) + if (di.udi_devnames[i][0] && + strcmp(di.udi_devnames[i], dev) == 0) { + cp = calloc(1, strlen(di.udi_vendor) + strlen(di.udi_product) + 2); + strcpy(cp, di.udi_vendor); + strcat(cp, " "); + strcat(cp, di.udi_product); + strncpy(out, cp, outlen - 1); + out[outlen - 1] = 0; + free(cp); + return out; + } + } +#endif + return NULL; +} + +static int fghJoystickFindUSBdev(char *name, char *out, int outlen) +{ + int i, f; + char buf[50]; + char *cp; + static int protection_warned = 0; + + for (i = 0; i < 16; i++) { + snprintf(buf, sizeof(buf), "%s%d", USBDEV, i); + f = open(buf, O_RDONLY); + if (f >= 0) { + cp = fghJoystickWalkUSBdev(f, name, out, outlen); + close(f); + if (cp) + return 1; + } + else if (errno == EACCES) { + if (!protection_warned) { + fgWarning("Can't open %s for read!", buf); + protection_warned = 1; + } + } + } + return 0; +} +#endif + +static int fghJoystickInitializeHID(struct os_specific_s *os, + int *num_axes, int *num_buttons) +{ + int size, is_joystick; +# ifdef HAVE_USBHID_H + int report_id = 0; +# endif + struct hid_data *d; + struct hid_item h; + report_desc_t rd; + + if ((rd = hid_get_report_desc(os->fd)) == 0) + { + fgWarning("error: %s: %s", os->fname, strerror(errno)); + return FALSE; + } + + os->hids = NULL; + +# ifdef HAVE_USBHID_H + if (ioctl(os->fd, USB_GET_REPORT_ID, &report_id) < 0) + { + /*** XXX {report_id} may not be the right variable? ***/ + fgWarning("error: %s%d: %s", UHIDDEV, report_id, strerror(errno)); + return FALSE; + } + + size = hid_report_size(rd, hid_input, report_id); +# else + size = hid_report_size(rd, 0, hid_input); +# endif + os->hid_data_buf = calloc(1, size); + os->hid_dlen = size; + + is_joystick = 0; +# ifdef HAVE_USBHID_H + d = hid_start_parse(rd, 1 << hid_input, report_id); +# else + d = hid_start_parse(rd, 1 << hid_input); +# endif + while (hid_get_item(d, &h)) + { + int usage, page, interesting_hid; + + page = HID_PAGE(h.usage); + usage = HID_USAGE(h.usage); + + /* This test is somewhat too simplistic, but this is how MicroSoft + * does, so I guess it works for all joysticks/game pads. */ + is_joystick = is_joystick || + (h.kind == hid_collection && + page == HUP_GENERIC_DESKTOP && + (usage == HUG_JOYSTICK || usage == HUG_GAME_PAD)); + + if (h.kind != hid_input) + continue; + + if (!is_joystick) + continue; + + interesting_hid = TRUE; + if (page == HUP_GENERIC_DESKTOP) + { + switch (usage) + { + case HUG_X: + case HUG_RX: + case HUG_Y: + case HUG_RY: + case HUG_Z: + case HUG_RZ: + case HUG_SLIDER: + if (*num_axes < _JS_MAX_AXES) + { + os->axes_usage[*num_axes] = usage; + (*num_axes)++; + } + break; + case HUG_HAT_SWITCH: + /* Allocate two axes for a hat */ + if (*num_axes + 1 < _JS_MAX_AXES) + { + os->axes_usage[*num_axes] = usage; + (*num_axes)++; + os->axes_usage[*num_axes] = usage; + (*num_axes)++; + } + break; + default: + interesting_hid = FALSE; + break; + } + } + else if (page == HUP_BUTTON) + { + interesting_hid = (usage > 0) && + (usage <= _JS_MAX_BUTTONS); + + if (interesting_hid && usage - 1 > *num_buttons) + *num_buttons = usage - 1; + } + + if (interesting_hid) + { + h.next = os->hids; + os->hids = calloc(1, sizeof(struct hid_item)); + *os->hids = h; + } + } + hid_end_parse(d); + + return os->hids != NULL; +} +# endif +#endif + + +/*this should be defined in a header file */ +#define MAX_NUM_JOYSTICKS 2 +extern SFG_Joystick *fgJoystick [ MAX_NUM_JOYSTICKS ]; + +void fgPlatformJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes ) +{ + int status; + +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + int len; + + if ( joy->pJoystick.os->is_analog ) + { + int status = read ( joy->pJoystick.os->fd, &joy->pJoystick.os->ajs, sizeof(joy->pJoystick.os->ajs) ); + if ( status != sizeof(joy->pJoystick.os->ajs) ) { + perror ( joy->pJoystick.os->fname ); + joy->error = GL_TRUE; + return; + } + if ( buttons != NULL ) + *buttons = ( joy->pJoystick.os->ajs.b1 ? 1 : 0 ) | ( joy->pJoystick.os->ajs.b2 ? 2 : 0 ); + + if ( axes != NULL ) + { + axes[0] = (float) joy->pJoystick.os->ajs.x; + axes[1] = (float) joy->pJoystick.os->ajs.y; + } + + return; + } + +# ifdef HAVE_USB_JS + while ( ( len = read ( joy->pJoystick.os->fd, joy->pJoystick.os->hid_data_buf, joy->pJoystick.os->hid_dlen ) ) == joy->pJoystick.os->hid_dlen ) + { + struct hid_item *h; + + for ( h = joy->pJoystick.os->hids; h; h = h->next ) + { + int d = hid_get_data ( joy->pJoystick.os->hid_data_buf, h ); + + int page = HID_PAGE ( h->usage ); + int usage = HID_USAGE ( h->usage ); + + if ( page == HUP_GENERIC_DESKTOP ) + { + int i; + for ( i = 0; i < joy->num_axes; i++ ) + if (joy->pJoystick.os->axes_usage[i] == usage) + { + if (usage == HUG_HAT_SWITCH) + { + if (d < 0 || d > 8) + d = 0; /* safety */ + joy->pJoystick.os->cache_axes[i] = (float)hatmap_x[d]; + joy->pJoystick.os->cache_axes[i + 1] = (float)hatmap_y[d]; + } + else + { + joy->pJoystick.os->cache_axes[i] = (float)d; + } + break; + } + } + else if (page == HUP_BUTTON) + { + if (usage > 0 && usage < _JS_MAX_BUTTONS + 1) + { + if (d) + joy->pJoystick.os->cache_buttons |= (1 << ( usage - 1 )); + else + joy->pJoystick.os->cache_buttons &= ~(1 << ( usage - 1 )); + } + } + } + } + if ( len < 0 && errno != EAGAIN ) + { + perror( joy->pJoystick.os->fname ); + joy->error = 1; + } + if ( buttons != NULL ) *buttons = joy->pJoystick.os->cache_buttons; + if ( axes != NULL ) + memcpy ( axes, joy->pJoystick.os->cache_axes, sizeof(float) * joy->num_axes ); +# endif +#endif + +#ifdef JS_NEW + + while ( 1 ) + { + status = read ( joy->pJoystick.fd, &joy->pJoystick.js, sizeof(struct js_event) ); + + if ( status != sizeof( struct js_event ) ) + { + if ( errno == EAGAIN ) + { + /* Use the old values */ + if ( buttons ) + *buttons = joy->pJoystick.tmp_buttons; + if ( axes ) + memcpy( axes, joy->pJoystick.tmp_axes, + sizeof( float ) * joy->num_axes ); + return; + } + + fgWarning ( "%s", joy->pJoystick.fname ); + joy->error = GL_TRUE; + return; + } + + switch ( joy->pJoystick.js.type & ~JS_EVENT_INIT ) + { + case JS_EVENT_BUTTON: + if( joy->pJoystick.js.value == 0 ) /* clear the flag */ + joy->pJoystick.tmp_buttons &= ~( 1 << joy->pJoystick.js.number ); + else + joy->pJoystick.tmp_buttons |= ( 1 << joy->pJoystick.js.number ); + break; + + case JS_EVENT_AXIS: + if ( joy->pJoystick.js.number < joy->num_axes ) + { + joy->pJoystick.tmp_axes[ joy->pJoystick.js.number ] = ( float )joy->pJoystick.js.value; + + if( axes ) + memcpy( axes, joy->pJoystick.tmp_axes, sizeof(float) * joy->num_axes ); + } + break; + + default: + fgWarning ( "PLIB_JS: Unrecognised /dev/js return!?!" ); + + /* use the old values */ + + if ( buttons != NULL ) *buttons = joy->pJoystick.tmp_buttons; + if ( axes != NULL ) + memcpy ( axes, joy->pJoystick.tmp_axes, sizeof(float) * joy->num_axes ); + + return; + } + + if( buttons ) + *buttons = joy->pJoystick.tmp_buttons; + } +#else + + status = read( joy->pJoystick.fd, &joy->pJoystick.js, JS_RETURN ); + + if ( status != JS_RETURN ) + { + fgWarning( "%s", joy->pJoystick.fname ); + joy->error = GL_TRUE; + return; + } + + if ( buttons ) +# if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) || defined( __NetBSD__ ) + *buttons = ( joy->pJoystick.js.b1 ? 1 : 0 ) | ( joy->pJoystick.js.b2 ? 2 : 0 ); /* XXX Should not be here -- BSD is handled earlier */ +# else + *buttons = joy->pJoystick.js.buttons; +# endif + + if ( axes ) + { + axes[ 0 ] = (float) joy->pJoystick.js.x; + axes[ 1 ] = (float) joy->pJoystick.js.y; + } +#endif +} + + +void fgPlatformJoystickOpen( SFG_Joystick* joy ) +{ +#if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) + int i = 0; + char *cp; +#endif +#ifdef JS_NEW + unsigned char u; + int i=0; +#else +# if defined( __linux__ ) || TARGET_HOST_SOLARIS + int i = 0; + int counter = 0; +# endif +#endif + +#if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) + for( i = 0; i < _JS_MAX_AXES; i++ ) + joy->pJoystick.os->cache_axes[ i ] = 0.0f; + + joy->pJoystick.os->cache_buttons = 0; + + joy->pJoystick.os->fd = open( joy->pJoystick.os->fname, O_RDONLY | O_NONBLOCK); + + if( joy->pJoystick.os->fd < 0 && errno == EACCES ) + fgWarning ( "%s exists but is not readable by you", joy->pJoystick.os->fname ); + + joy->error =( joy->pJoystick.os->fd < 0 ); + + if( joy->error ) + return; + + joy->num_axes = 0; + joy->num_buttons = 0; + if( joy->pJoystick.os->is_analog ) + { + FILE *joyfile; + char joyfname[ 1024 ]; + int noargs, in_no_axes; + + float axes [ _JS_MAX_AXES ]; + int buttons[ _JS_MAX_AXES ]; + + joy->num_axes = 2; + joy->num_buttons = 32; + + fgJoystickRawRead( joy, buttons, axes ); + joy->error = axes[ 0 ] < -1000000000.0f; + if( joy->error ) + return; + + snprintf( joyfname, sizeof(joyfname), "%s/.joy%drc", getenv( "HOME" ), joy->id ); + + joyfile = fopen( joyfname, "r" ); + joy->error =( joyfile == NULL ); + if( joy->error ) + return; + + noargs = fscanf( joyfile, "%d%f%f%f%f%f%f", &in_no_axes, + &joy->min[ 0 ], &joy->center[ 0 ], &joy->max[ 0 ], + &joy->min[ 1 ], &joy->center[ 1 ], &joy->max[ 1 ] ); + joy->error = noargs != 7 || in_no_axes != _JS_MAX_AXES; + fclose( joyfile ); + if( joy->error ) + return; + + for( i = 0; i < _JS_MAX_AXES; i++ ) + { + joy->dead_band[ i ] = 0.0f; + joy->saturate [ i ] = 1.0f; + } + + return; /* End of analog code */ + } + +# ifdef HAVE_USB_JS + if( ! fghJoystickInitializeHID( joy->pJoystick.os, &joy->num_axes, + &joy->num_buttons ) ) + { + close( joy->pJoystick.os->fd ); + joy->error = GL_TRUE; + return; + } + + cp = strrchr( joy->pJoystick.os->fname, '/' ); + if( cp ) + { + if( fghJoystickFindUSBdev( &cp[1], joy->name, sizeof( joy->name ) ) == + 0 ) + strcpy( joy->name, &cp[1] ); + } + + if( joy->num_axes > _JS_MAX_AXES ) + joy->num_axes = _JS_MAX_AXES; + + for( i = 0; i < _JS_MAX_AXES; i++ ) + { + /* We really should get this from the HID, but that data seems + * to be quite unreliable for analog-to-USB converters. Punt for + * now. + */ + if( joy->pJoystick.os->axes_usage[ i ] == HUG_HAT_SWITCH ) + { + joy->max [ i ] = 1.0f; + joy->center[ i ] = 0.0f; + joy->min [ i ] = -1.0f; + } + else + { + joy->max [ i ] = 255.0f; + joy->center[ i ] = 127.0f; + joy->min [ i ] = 0.0f; + } + + joy->dead_band[ i ] = 0.0f; + joy->saturate[ i ] = 1.0f; + } +# endif +#endif + +#if defined( __linux__ ) || TARGET_HOST_SOLARIS + /* Default for older Linux systems. */ + joy->num_axes = 2; + joy->num_buttons = 32; + +# ifdef JS_NEW + for( i = 0; i < _JS_MAX_AXES; i++ ) + joy->pJoystick.tmp_axes[ i ] = 0.0f; + + joy->pJoystick.tmp_buttons = 0; +# endif + + joy->pJoystick.fd = open( joy->pJoystick.fname, O_RDONLY ); + + joy->error =( joy->pJoystick.fd < 0 ); + + if( joy->error ) + return; + + /* Set the correct number of axes for the linux driver */ +# ifdef JS_NEW + /* Melchior Franz's fixes for big-endian Linuxes since writing + * to the upper byte of an uninitialized word doesn't work. + * 9 April 2003 + */ + if(ioctl(joy->pJoystick.fd, JSIOCGAXES, &u) != -1) + joy->num_axes = u; + if(ioctl(joy->pJoystick.fd, JSIOCGBUTTONS, &u) != -1) + joy->num_buttons = u; + ioctl( joy->pJoystick.fd, JSIOCGNAME( sizeof( joy->name ) ), joy->name ); + fcntl(joy->pJoystick.fd, F_SETFL, fcntl(joy->pJoystick.fd, F_GETFL) | O_NONBLOCK); +# endif + + /* + * The Linux driver seems to return 512 for all axes + * when no stick is present - but there is a chance + * that could happen by accident - so it's gotta happen + * on both axes for at least 100 attempts. + * + * PWO: shouldn't be that done somehow wiser on the kernel level? + */ +# ifndef JS_NEW + counter = 0; + + do + { + fghJoystickRawRead( joy, NULL, joy->center ); + counter++; + } while( !joy->error && + counter < 100 && + joy->center[ 0 ] == 512.0f && + joy->center[ 1 ] == 512.0f ); + + if ( counter >= 100 ) + joy->error = GL_TRUE; +# endif + + for( i = 0; i < _JS_MAX_AXES; i++ ) + { +# ifdef JS_NEW + joy->max [ i ] = 32767.0f; + joy->center[ i ] = 0.0f; + joy->min [ i ] = -32767.0f; +# else + joy->max[ i ] = joy->center[ i ] * 2.0f; + joy->min[ i ] = 0.0f; +# endif + joy->dead_band[ i ] = 0.0f; + joy->saturate [ i ] = 1.0f; + } +#endif +} + + +void fgPlatformJoystickInit( SFG_Joystick *fgJoystick[], int ident ) +{ +#if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) + fgJoystick[ ident ]->id = ident; + fgJoystick[ ident ]->error = GL_FALSE; + + fgJoystick[ ident ]->pJoystick.os = calloc( 1, sizeof( struct os_specific_s ) ); + memset( fgJoystick[ ident ]->pJoystick.os, 0, sizeof( struct os_specific_s ) ); + if( ident < USB_IDENT_OFFSET ) + fgJoystick[ ident ]->pJoystick.os->is_analog = 1; + if( fgJoystick[ ident ]->pJoystick.os->is_analog ) + snprintf( fgJoystick[ ident ]->pJoystick.os->fname, sizeof(fgJoystick[ ident ]->pJoystick.os->fname), "%s%d", AJSDEV, ident ); + else + snprintf( fgJoystick[ ident ]->pJoystick.os->fname, sizeof(fgJoystick[ ident ]->pJoystick.os->fname), "%s%d", UHIDDEV, + ident - USB_IDENT_OFFSET ); +#elif defined( __linux__ ) + fgJoystick[ ident ]->id = ident; + fgJoystick[ ident ]->error = GL_FALSE; + + snprintf( fgJoystick[ident]->pJoystick.fname, sizeof(fgJoystick[ident]->pJoystick.fname), "/dev/input/js%d", ident ); + + if( access( fgJoystick[ ident ]->pJoystick.fname, F_OK ) != 0 ) + snprintf( fgJoystick[ ident ]->pJoystick.fname, sizeof(fgJoystick[ ident ]->pJoystick.fname), "/dev/js%d", ident ); +#endif +} + + +void fgPlatformJoystickClose ( int ident ) +{ +#if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) + if( fgJoystick[ident]->pJoystick.os ) + { + if( ! fgJoystick[ ident ]->error ) + close( fgJoystick[ ident ]->pJoystick.os->fd ); +#ifdef HAVE_USB_JS + if( fgJoystick[ ident ]->pJoystick.os->hids ) + free (fgJoystick[ ident ]->pJoystick.os->hids); + if( fgJoystick[ ident ]->pJoystick.os->hid_data_buf ) + free( fgJoystick[ ident ]->pJoystick.os->hid_data_buf ); +#endif + free( fgJoystick[ident]->pJoystick.os ); + } +#endif + + if( ! fgJoystick[ident]->error ) + close( fgJoystick[ ident ]->pJoystick.fd ); +} + diff --git a/src/x11/fg_main_x11.c b/src/x11/fg_main_x11.c new file mode 100644 index 0000000..b083043 --- /dev/null +++ b/src/x11/fg_main_x11.c @@ -0,0 +1,1119 @@ +/* + * fg_main_x11.c + * + * The X11-specific windows message processing methods. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Copied for Platform code by Evan Felix + * Creation date: Thur Feb 2 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "../fg_internal.h" +#include +#include + + +/* + * Try to get the maximum value allowed for ints, falling back to the minimum + * guaranteed by ISO C99 if there is no suitable header. + */ +#ifdef HAVE_LIMITS_H +# include +#endif +#ifndef INT_MAX +# define INT_MAX 32767 +#endif + +#ifndef MIN +# define MIN(a,b) (((a)<(b)) ? (a) : (b)) +#endif + +extern void fghOnReshapeNotify(SFG_Window *window, int width, int height, GLboolean forceNotify); +extern void fghOnPositionNotify(SFG_Window *window, int x, int y, GLboolean forceNotify); +extern void fgPlatformFullScreenToggle( SFG_Window *win ); +extern void fgPlatformPositionWindow( SFG_Window *window, int x, int y ); +extern void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height ); +extern void fgPlatformPushWindow( SFG_Window *window ); +extern void fgPlatformPopWindow( SFG_Window *window ); +extern void fgPlatformHideWindow( SFG_Window *window ); +extern void fgPlatformIconifyWindow( SFG_Window *window ); +extern void fgPlatformShowWindow( SFG_Window *window ); + +/* used in the event handling code to match and discard stale mouse motion events */ +static Bool match_motion(Display *dpy, XEvent *xev, XPointer arg); + +/* + * TODO BEFORE THE STABLE RELEASE: + * + * There are some issues concerning window redrawing under X11, and maybe + * some events are not handled. + * + * Need to investigate why the X11 version breaks out with an error when + * closing a window (using the window manager, not glutDestroyWindow)... + */ + + + +fg_time_t fgPlatformSystemTime ( void ) +{ +#ifdef CLOCK_MONOTONIC + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + return now.tv_nsec/1000000 + now.tv_sec*1000; +#elif defined(HAVE_GETTIMEOFDAY) + struct timeval now; + gettimeofday( &now, NULL ); + return now.tv_usec/1000 + now.tv_sec*1000; +#endif +} + +/* + * Does the magic required to relinquish the CPU until something interesting + * happens. + */ + +void fgPlatformSleepForEvents( fg_time_t msec ) +{ + /* + * Possibly due to aggressive use of XFlush() and friends, + * it is possible to have our socket drained but still have + * unprocessed events. (Or, this may just be normal with + * X, anyway?) We do non-trivial processing of X events + * after the event-reading loop, in any case, so we + * need to allow that we may have an empty socket but non- + * empty event queue. + */ + if( ! XPending( fgDisplay.pDisplay.Display ) ) + { + fd_set fdset; + int err; + int socket; + struct timeval wait; + + socket = ConnectionNumber( fgDisplay.pDisplay.Display ); + FD_ZERO( &fdset ); + FD_SET( socket, &fdset ); + wait.tv_sec = msec / 1000; + wait.tv_usec = (msec % 1000) * 1000; + err = select( socket+1, &fdset, NULL, NULL, &wait ); + + if( ( -1 == err ) && ( errno != EINTR ) ) + fgWarning ( "freeglut select() error: %d", errno ); + } +} + + +/* + * Returns GLUT modifier mask for the state field of an X11 event. + */ +int fgPlatformGetModifiers( int state ) +{ + int ret = 0; + + if( state & ( ShiftMask | LockMask ) ) + ret |= GLUT_ACTIVE_SHIFT; + if( state & ControlMask ) + ret |= GLUT_ACTIVE_CTRL; + if( state & Mod1Mask ) + ret |= GLUT_ACTIVE_ALT; + if( state & Mod2Mask ) + ret |= GLUT_ACTIVE_SUPER; + + return ret; +} + +#ifdef EVENT_DEBUG +static const char* fghTypeToString( int type ) +{ + switch( type ) { + case KeyPress: return "KeyPress"; + case KeyRelease: return "KeyRelease"; + case ButtonPress: return "ButtonPress"; + case ButtonRelease: return "ButtonRelease"; + case MotionNotify: return "MotionNotify"; + case EnterNotify: return "EnterNotify"; + case LeaveNotify: return "LeaveNotify"; + case FocusIn: return "FocusIn"; + case FocusOut: return "FocusOut"; + case KeymapNotify: return "KeymapNotify"; + case Expose: return "Expose"; + case GraphicsExpose: return "GraphicsExpose"; + case NoExpose: return "NoExpose"; + case VisibilityNotify: return "VisibilityNotify"; + case CreateNotify: return "CreateNotify"; + case DestroyNotify: return "DestroyNotify"; + case UnmapNotify: return "UnmapNotify"; + case MapNotify: return "MapNotify"; + case MapRequest: return "MapRequest"; + case ReparentNotify: return "ReparentNotify"; + case ConfigureNotify: return "ConfigureNotify"; + case ConfigureRequest: return "ConfigureRequest"; + case GravityNotify: return "GravityNotify"; + case ResizeRequest: return "ResizeRequest"; + case CirculateNotify: return "CirculateNotify"; + case CirculateRequest: return "CirculateRequest"; + case PropertyNotify: return "PropertyNotify"; + case SelectionClear: return "SelectionClear"; + case SelectionRequest: return "SelectionRequest"; + case SelectionNotify: return "SelectionNotify"; + case ColormapNotify: return "ColormapNotify"; + case ClientMessage: return "ClientMessage"; + case MappingNotify: return "MappingNotify"; + default: return "UNKNOWN"; + } +} + +static const char* fghBoolToString( Bool b ) +{ + return b == False ? "False" : "True"; +} + +static const char* fghNotifyHintToString( char is_hint ) +{ + switch( is_hint ) { + case NotifyNormal: return "NotifyNormal"; + case NotifyHint: return "NotifyHint"; + default: return "UNKNOWN"; + } +} + +static const char* fghNotifyModeToString( int mode ) +{ + switch( mode ) { + case NotifyNormal: return "NotifyNormal"; + case NotifyGrab: return "NotifyGrab"; + case NotifyUngrab: return "NotifyUngrab"; + case NotifyWhileGrabbed: return "NotifyWhileGrabbed"; + default: return "UNKNOWN"; + } +} + +static const char* fghNotifyDetailToString( int detail ) +{ + switch( detail ) { + case NotifyAncestor: return "NotifyAncestor"; + case NotifyVirtual: return "NotifyVirtual"; + case NotifyInferior: return "NotifyInferior"; + case NotifyNonlinear: return "NotifyNonlinear"; + case NotifyNonlinearVirtual: return "NotifyNonlinearVirtual"; + case NotifyPointer: return "NotifyPointer"; + case NotifyPointerRoot: return "NotifyPointerRoot"; + case NotifyDetailNone: return "NotifyDetailNone"; + default: return "UNKNOWN"; + } +} + +static const char* fghVisibilityToString( int state ) { + switch( state ) { + case VisibilityUnobscured: return "VisibilityUnobscured"; + case VisibilityPartiallyObscured: return "VisibilityPartiallyObscured"; + case VisibilityFullyObscured: return "VisibilityFullyObscured"; + default: return "UNKNOWN"; + } +} + +static const char* fghConfigureDetailToString( int detail ) +{ + switch( detail ) { + case Above: return "Above"; + case Below: return "Below"; + case TopIf: return "TopIf"; + case BottomIf: return "BottomIf"; + case Opposite: return "Opposite"; + default: return "UNKNOWN"; + } +} + +static const char* fghPlaceToString( int place ) +{ + switch( place ) { + case PlaceOnTop: return "PlaceOnTop"; + case PlaceOnBottom: return "PlaceOnBottom"; + default: return "UNKNOWN"; + } +} + +static const char* fghMappingRequestToString( int request ) +{ + switch( request ) { + case MappingModifier: return "MappingModifier"; + case MappingKeyboard: return "MappingKeyboard"; + case MappingPointer: return "MappingPointer"; + default: return "UNKNOWN"; + } +} + +static const char* fghPropertyStateToString( int state ) +{ + switch( state ) { + case PropertyNewValue: return "PropertyNewValue"; + case PropertyDelete: return "PropertyDelete"; + default: return "UNKNOWN"; + } +} + +static const char* fghColormapStateToString( int state ) +{ + switch( state ) { + case ColormapUninstalled: return "ColormapUninstalled"; + case ColormapInstalled: return "ColormapInstalled"; + default: return "UNKNOWN"; + } +} + +static void fghPrintEvent( XEvent *event ) +{ + switch( event->type ) { + + case KeyPress: + case KeyRelease: { + XKeyEvent *e = &event->xkey; + fgWarning( "%s: window=0x%x, root=0x%x, subwindow=0x%x, time=%lu, " + "(x,y)=(%d,%d), (x_root,y_root)=(%d,%d), state=0x%x, " + "keycode=%u, same_screen=%s", fghTypeToString( e->type ), + e->window, e->root, e->subwindow, (unsigned long)e->time, + e->x, e->y, e->x_root, e->y_root, e->state, e->keycode, + fghBoolToString( e->same_screen ) ); + break; + } + + case ButtonPress: + case ButtonRelease: { + XButtonEvent *e = &event->xbutton; + fgWarning( "%s: window=0x%x, root=0x%x, subwindow=0x%x, time=%lu, " + "(x,y)=(%d,%d), (x_root,y_root)=(%d,%d), state=0x%x, " + "button=%u, same_screen=%d", fghTypeToString( e->type ), + e->window, e->root, e->subwindow, (unsigned long)e->time, + e->x, e->y, e->x_root, e->y_root, e->state, e->button, + fghBoolToString( e->same_screen ) ); + break; + } + + case MotionNotify: { + XMotionEvent *e = &event->xmotion; + fgWarning( "%s: window=0x%x, root=0x%x, subwindow=0x%x, time=%lu, " + "(x,y)=(%d,%d), (x_root,y_root)=(%d,%d), state=0x%x, " + "is_hint=%s, same_screen=%d", fghTypeToString( e->type ), + e->window, e->root, e->subwindow, (unsigned long)e->time, + e->x, e->y, e->x_root, e->y_root, e->state, + fghNotifyHintToString( e->is_hint ), + fghBoolToString( e->same_screen ) ); + break; + } + + case EnterNotify: + case LeaveNotify: { + XCrossingEvent *e = &event->xcrossing; + fgWarning( "%s: window=0x%x, root=0x%x, subwindow=0x%x, time=%lu, " + "(x,y)=(%d,%d), mode=%s, detail=%s, same_screen=%d, " + "focus=%d, state=0x%x", fghTypeToString( e->type ), + e->window, e->root, e->subwindow, (unsigned long)e->time, + e->x, e->y, fghNotifyModeToString( e->mode ), + fghNotifyDetailToString( e->detail ), (int)e->same_screen, + (int)e->focus, e->state ); + break; + } + + case FocusIn: + case FocusOut: { + XFocusChangeEvent *e = &event->xfocus; + fgWarning( "%s: window=0x%x, mode=%s, detail=%s", + fghTypeToString( e->type ), e->window, + fghNotifyModeToString( e->mode ), + fghNotifyDetailToString( e->detail ) ); + break; + } + + case KeymapNotify: { + XKeymapEvent *e = &event->xkeymap; + char buf[32 * 2 + 1]; + int i; + for(i=0; i<32; i++) { + sprintf(buf + i * 2, "%02x", e->key_vector[i]); + } + buf[64] = 0; + fgWarning("%s: window=0x%x, %s", fghTypeToString(e->type), e->window, buf); + break; + } + + case Expose: { + XExposeEvent *e = &event->xexpose; + fgWarning( "%s: window=0x%x, (x,y)=(%d,%d), (width,height)=(%d,%d), " + "count=%d", fghTypeToString( e->type ), e->window, e->x, + e->y, e->width, e->height, e->count ); + break; + } + + case GraphicsExpose: { + XGraphicsExposeEvent *e = &event->xgraphicsexpose; + fgWarning( "%s: drawable=0x%x, (x,y)=(%d,%d), (width,height)=(%d,%d), " + "count=%d, (major_code,minor_code)=(%d,%d)", + fghTypeToString( e->type ), e->drawable, e->x, e->y, + e->width, e->height, e->count, e->major_code, + e->minor_code ); + break; + } + + case NoExpose: { + XNoExposeEvent *e = &event->xnoexpose; + fgWarning( "%s: drawable=0x%x, (major_code,minor_code)=(%d,%d)", + fghTypeToString( e->type ), e->drawable, e->major_code, + e->minor_code ); + break; + } + + case VisibilityNotify: { + XVisibilityEvent *e = &event->xvisibility; + fgWarning( "%s: window=0x%x, state=%s", fghTypeToString( e->type ), + e->window, fghVisibilityToString( e->state) ); + break; + } + + case CreateNotify: { + XCreateWindowEvent *e = &event->xcreatewindow; + fgWarning( "%s: (x,y)=(%d,%d), (width,height)=(%d,%d), border_width=%d, " + "window=0x%x, override_redirect=%s", + fghTypeToString( e->type ), e->x, e->y, e->width, e->height, + e->border_width, e->window, + fghBoolToString( e->override_redirect ) ); + break; + } + + case DestroyNotify: { + XDestroyWindowEvent *e = &event->xdestroywindow; + fgWarning( "%s: event=0x%x, window=0x%x", + fghTypeToString( e->type ), e->event, e->window ); + break; + } + + case UnmapNotify: { + XUnmapEvent *e = &event->xunmap; + fgWarning( "%s: event=0x%x, window=0x%x, from_configure=%s", + fghTypeToString( e->type ), e->event, e->window, + fghBoolToString( e->from_configure ) ); + break; + } + + case MapNotify: { + XMapEvent *e = &event->xmap; + fgWarning( "%s: event=0x%x, window=0x%x, override_redirect=%s", + fghTypeToString( e->type ), e->event, e->window, + fghBoolToString( e->override_redirect ) ); + break; + } + + case MapRequest: { + XMapRequestEvent *e = &event->xmaprequest; + fgWarning( "%s: parent=0x%x, window=0x%x", + fghTypeToString( event->type ), e->parent, e->window ); + break; + } + + case ReparentNotify: { + XReparentEvent *e = &event->xreparent; + fgWarning( "%s: event=0x%x, window=0x%x, parent=0x%x, (x,y)=(%d,%d), " + "override_redirect=%s", fghTypeToString( e->type ), + e->event, e->window, e->parent, e->x, e->y, + fghBoolToString( e->override_redirect ) ); + break; + } + + case ConfigureNotify: { + XConfigureEvent *e = &event->xconfigure; + fgWarning( "%s: event=0x%x, window=0x%x, (x,y)=(%d,%d), " + "(width,height)=(%d,%d), border_width=%d, above=0x%x, " + "override_redirect=%s", fghTypeToString( e->type ), e->event, + e->window, e->x, e->y, e->width, e->height, e->border_width, + e->above, fghBoolToString( e->override_redirect ) ); + break; + } + + case ConfigureRequest: { + XConfigureRequestEvent *e = &event->xconfigurerequest; + fgWarning( "%s: parent=0x%x, window=0x%x, (x,y)=(%d,%d), " + "(width,height)=(%d,%d), border_width=%d, above=0x%x, " + "detail=%s, value_mask=%lx", fghTypeToString( e->type ), + e->parent, e->window, e->x, e->y, e->width, e->height, + e->border_width, e->above, + fghConfigureDetailToString( e->detail ), e->value_mask ); + break; + } + + case GravityNotify: { + XGravityEvent *e = &event->xgravity; + fgWarning( "%s: event=0x%x, window=0x%x, (x,y)=(%d,%d)", + fghTypeToString( e->type ), e->event, e->window, e->x, e->y ); + break; + } + + case ResizeRequest: { + XResizeRequestEvent *e = &event->xresizerequest; + fgWarning( "%s: window=0x%x, (width,height)=(%d,%d)", + fghTypeToString( e->type ), e->window, e->width, e->height ); + break; + } + + case CirculateNotify: { + XCirculateEvent *e = &event->xcirculate; + fgWarning( "%s: event=0x%x, window=0x%x, place=%s", + fghTypeToString( e->type ), e->event, e->window, + fghPlaceToString( e->place ) ); + break; + } + + case CirculateRequest: { + XCirculateRequestEvent *e = &event->xcirculaterequest; + fgWarning( "%s: parent=0x%x, window=0x%x, place=%s", + fghTypeToString( e->type ), e->parent, e->window, + fghPlaceToString( e->place ) ); + break; + } + + case PropertyNotify: { + XPropertyEvent *e = &event->xproperty; + fgWarning( "%s: window=0x%x, atom=%lu, time=%lu, state=%s", + fghTypeToString( e->type ), e->window, + (unsigned long)e->atom, (unsigned long)e->time, + fghPropertyStateToString( e->state ) ); + break; + } + + case SelectionClear: { + XSelectionClearEvent *e = &event->xselectionclear; + fgWarning( "%s: window=0x%x, selection=%lu, time=%lu", + fghTypeToString( e->type ), e->window, + (unsigned long)e->selection, (unsigned long)e->time ); + break; + } + + case SelectionRequest: { + XSelectionRequestEvent *e = &event->xselectionrequest; + fgWarning( "%s: owner=0x%x, requestor=0x%x, selection=0x%x, " + "target=0x%x, property=%lu, time=%lu", + fghTypeToString( e->type ), e->owner, e->requestor, + (unsigned long)e->selection, (unsigned long)e->target, + (unsigned long)e->property, (unsigned long)e->time ); + break; + } + + case SelectionNotify: { + XSelectionEvent *e = &event->xselection; + fgWarning( "%s: requestor=0x%x, selection=0x%x, target=0x%x, " + "property=%lu, time=%lu", fghTypeToString( e->type ), + e->requestor, (unsigned long)e->selection, + (unsigned long)e->target, (unsigned long)e->property, + (unsigned long)e->time ); + break; + } + + case ColormapNotify: { + XColormapEvent *e = &event->xcolormap; + fgWarning( "%s: window=0x%x, colormap=%lu, new=%s, state=%s", + fghTypeToString( e->type ), e->window, + (unsigned long)e->colormap, fghBoolToString( e->new ), + fghColormapStateToString( e->state ) ); + break; + } + + case ClientMessage: { + XClientMessageEvent *e = &event->xclient; + char buf[61]; + char *p = buf; + int i; + switch(e->format) { + case 8: + for(i=0; i<20; i++, p+=3) { + sprintf(p, " %02x", e->data.b[i]); + } + break; + case 16: + for(i=0; i<10; i++, p+=5) { + sprintf(p, " %04x", e->data.s[i]); + } + break; + case 32: + for(i=0; i<5; i++, p+=9) { + sprintf(p, " %08lx", e->data.l[i]); + } + break; + } + *p = '\0'; + fgWarning("%s: window=0x%x, message_type=%lu, format=%d, data=(%s )", + fghTypeToString(e->type), e->window, + (unsigned long)e->message_type, e->format, buf); + break; + } + + case MappingNotify: { + XMappingEvent *e = &event->xmapping; + fgWarning( "%s: window=0x%x, request=%s, first_keycode=%d, count=%d", + fghTypeToString( e->type ), e->window, + fghMappingRequestToString( e->request ), e->first_keycode, + e->count ); + break; + } + + default: + fgWarning( "%s", fghTypeToString( event->type ) ); + break; + } +} +#endif + + +void fgPlatformProcessSingleEvent ( void ) +{ + SFG_Window* window; + XEvent event; + + /* This code was repeated constantly, so here it goes into a definition: */ +#define GETWINDOW(a) \ + window = fgWindowByHandle( event.a.window ); \ + if( window == NULL ) \ + break; + +#define GETMOUSE(a) \ + window->State.MouseX = event.a.x; \ + window->State.MouseY = event.a.y; + + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMainLoopEvent" ); + + while( XPending( fgDisplay.pDisplay.Display ) ) + { + XNextEvent( fgDisplay.pDisplay.Display, &event ); +#ifdef EVENT_DEBUG + fghPrintEvent( &event ); +#endif + + switch( event.type ) + { + case ClientMessage: + if (fgStructure.CurrentWindow) + if(fgIsSpaceballXEvent(&event)) { + fgSpaceballHandleXEvent(&event); + break; + } + /* Destroy the window when the WM_DELETE_WINDOW message arrives */ + if( (Atom) event.xclient.data.l[ 0 ] == fgDisplay.pDisplay.DeleteWindow ) + { + GETWINDOW( xclient ); + + fgDestroyWindow ( window ); + + if( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT ) + { + fgDeinitialize( ); + exit( 0 ); + } + else if( fgState.ActionOnWindowClose == GLUT_ACTION_GLUTMAINLOOP_RETURNS ) + fgState.ExecState = GLUT_EXEC_STATE_STOP; + + return; + } + break; + + /* + * CreateNotify causes a configure-event so that sub-windows are + * handled compatibly with GLUT. Otherwise, your sub-windows + * (in freeglut only) will not get an initial reshape event, + * which can break things. + * + * GLUT presumably does this because it generally tries to treat + * sub-windows the same as windows. + */ + case CreateNotify: + case ConfigureNotify: + { + int width, height, x, y; + if( event.type == CreateNotify ) { + GETWINDOW( xcreatewindow ); + width = event.xcreatewindow.width; + height = event.xcreatewindow.height; + x = event.xcreatewindow.x; + y = event.xcreatewindow.y; + } else { + GETWINDOW( xconfigure ); + width = event.xconfigure.width; + height = event.xconfigure.height; + x = event.xconfigure.x; + y = event.xconfigure.y; + } + + /* Update state and call callback, if there was a change */ + fghOnPositionNotify(window, x, y, GL_FALSE); + /* Update state and call callback, if there was a change */ + fghOnReshapeNotify(window, width, height, GL_FALSE); + } + break; + + case DestroyNotify: + /* + * This is sent to confirm the XDestroyWindow call. + * + * XXX WHY is this commented out? Should we re-enable it? + */ + /* fgAddToWindowDestroyList ( window ); */ + break; + + case Expose: + /* + * We are too dumb to process partial exposes... + * + * XXX Well, we could do it. However, it seems to only + * XXX be potentially useful for single-buffered (since + * XXX double-buffered does not respect viewport when we + * XXX do a buffer-swap). + * + */ + if( event.xexpose.count == 0 ) + { + GETWINDOW( xexpose ); + window->State.WorkMask |= GLUT_DISPLAY_WORK; + } + break; + + case MapNotify: + break; + + case UnmapNotify: + /* We get this when iconifying a window. */ + GETWINDOW( xunmap ); + INVOKE_WCB( *window, WindowStatus, ( GLUT_HIDDEN ) ); + window->State.Visible = GL_FALSE; + break; + + case MappingNotify: + /* + * Have the client's keyboard knowledge updated (xlib.ps, + * page 206, says that's a good thing to do) + */ + XRefreshKeyboardMapping( (XMappingEvent *) &event ); + break; + + case VisibilityNotify: + { + /* + * Sending this event, the X server can notify us that the window + * has just acquired one of the three possible visibility states: + * VisibilityUnobscured, VisibilityPartiallyObscured or + * VisibilityFullyObscured. Note that we DO NOT receive a + * VisibilityNotify event when iconifying a window, we only get an + * UnmapNotify then. + */ + GETWINDOW( xvisibility ); + switch( event.xvisibility.state ) + { + case VisibilityUnobscured: + INVOKE_WCB( *window, WindowStatus, ( GLUT_FULLY_RETAINED ) ); + window->State.Visible = GL_TRUE; + break; + + case VisibilityPartiallyObscured: + INVOKE_WCB( *window, WindowStatus, + ( GLUT_PARTIALLY_RETAINED ) ); + window->State.Visible = GL_TRUE; + break; + + case VisibilityFullyObscured: + INVOKE_WCB( *window, WindowStatus, ( GLUT_FULLY_COVERED ) ); + window->State.Visible = GL_FALSE; + break; + + default: + fgWarning( "Unknown X visibility state: %d", + event.xvisibility.state ); + break; + } + } + break; + + case EnterNotify: + case LeaveNotify: + GETWINDOW( xcrossing ); + GETMOUSE( xcrossing ); + if( ( event.type == LeaveNotify ) && window->IsMenu && + window->ActiveMenu && window->ActiveMenu->IsActive ) + fgUpdateMenuHighlight( window->ActiveMenu ); + + INVOKE_WCB( *window, Entry, ( ( EnterNotify == event.type ) ? + GLUT_ENTERED : + GLUT_LEFT ) ); + break; + + case MotionNotify: + { + /* if GLUT_SKIP_STALE_MOTION_EVENTS is true, then discard all but + * the last motion event from the queue + */ + if(fgState.SkipStaleMotion) { + while(XCheckIfEvent(fgDisplay.pDisplay.Display, &event, match_motion, 0)); + } + + GETWINDOW( xmotion ); + GETMOUSE( xmotion ); + + if( window->ActiveMenu ) + { + if( window == window->ActiveMenu->ParentWindow ) + { + window->ActiveMenu->Window->State.MouseX = + event.xmotion.x_root - window->ActiveMenu->X; + window->ActiveMenu->Window->State.MouseY = + event.xmotion.y_root - window->ActiveMenu->Y; + } + + fgUpdateMenuHighlight( window->ActiveMenu ); + + break; + } + + /* + * XXX For more than 5 buttons, just check {event.xmotion.state}, + * XXX rather than a host of bit-masks? Or maybe we need to + * XXX track ButtonPress/ButtonRelease events in our own + * XXX bit-mask? + */ + fgState.Modifiers = fgPlatformGetModifiers( event.xmotion.state ); + if ( event.xmotion.state & ( Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) ) { + INVOKE_WCB( *window, Motion, ( event.xmotion.x, + event.xmotion.y ) ); + } else { + INVOKE_WCB( *window, Passive, ( event.xmotion.x, + event.xmotion.y ) ); + } + fgState.Modifiers = INVALID_MODIFIERS; + } + break; + + case ButtonRelease: + case ButtonPress: + { + GLboolean pressed; + int button, x, y; + + /* + * A mouse button has been pressed or released. Traditionally, + * break if the window was found within the freeglut structures. + */ + GETWINDOW( xbutton ); + GETMOUSE( xbutton ); + + /* + * An X button (at least in XFree86) is numbered from 1. + * A GLUT button is numbered from 0. + * Old GLUT passed through buttons other than just the first + * three, though it only gave symbolic names and official + * support to the first three. + */ + button = event.xbutton.button - 1; + + pressed = event.type == ButtonPress ? GL_TRUE : GL_FALSE; + x = event.xbutton.x; + y = event.xbutton.y; + + /* + * Do not execute the application's mouse callback if a menu + * is hooked to this button. In that case an appropriate + * private call should be generated. + */ + if(fgCheckActiveMenu( window, button, pressed, x, y)) + break; + + /* + * Check if there is a mouse or mouse wheel callback hooked to the + * window + */ + if(!FETCH_WCB(*window, Mouse) && !FETCH_WCB(*window, MouseWheel)) + break; + + fgState.Modifiers = fgPlatformGetModifiers(event.xbutton.state); + + /* Finally execute the mouse or mouse wheel callback. + * The mouse wheel is reported as buttons 4 (down) and 5 (up) by + * the X server. "button" has been converted to 0-based above, so + * that's 3 and 4 for us. + * If a wheel callback hasn't been registered, we simply treat them + * as button presses and pass them to the mouse handler. This is + * important for compatibility with the original GLUT. + */ + if(button < 3 || button > 4 || !FETCH_WCB(*window, MouseWheel)) { + INVOKE_WCB(*window, Mouse, (button, pressed ? GLUT_DOWN : GLUT_UP, x, y)); + } else { + if(pressed) { + int dir = button & 1 ? 1 : -1; + /* there's no way to know if X buttons after 5 are more + * wheels/wheel axes, or regular buttons. So we'll only + * ever invoke the wheel CB for wheel 0. + */ + INVOKE_WCB(*window, MouseWheel, (0, dir, x, y)); + } + } + fgState.Modifiers = INVALID_MODIFIERS; + } + break; + + case KeyRelease: + case KeyPress: + { + FGCBKeyboardUC keyboard_cb; + FGCBSpecialUC special_cb; + FGCBUserData keyboard_ud; + FGCBUserData special_ud; + + GETWINDOW( xkey ); + GETMOUSE( xkey ); + + /* Detect auto repeated keys, if configured globally or per-window */ + + if ( fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE ) + { + if (event.type==KeyRelease) + { + /* + * Look at X11 keystate to detect repeat mode. + * While X11 says the key is actually held down, we'll ignore KeyRelease/KeyPress pairs. + */ + + char keys[32]; + XQueryKeymap( fgDisplay.pDisplay.Display, keys ); /* Look at X11 keystate to detect repeat mode */ + + if ( event.xkey.keycode<256 ) /* XQueryKeymap is limited to 256 keycodes */ + { + if ( keys[event.xkey.keycode>>3] & (1<<(event.xkey.keycode%8)) ) + window->State.pWState.KeyRepeating = GL_TRUE; + else + window->State.pWState.KeyRepeating = GL_FALSE; + } + } + } + else + window->State.pWState.KeyRepeating = GL_FALSE; + + /* Cease processing this event if it is auto repeated */ + + if (window->State.pWState.KeyRepeating) + { + if (event.type == KeyPress) window->State.pWState.KeyRepeating = GL_FALSE; + break; + } + + if( event.type == KeyPress ) + { + keyboard_cb = (FGCBKeyboardUC)( FETCH_WCB( *window, Keyboard )); + special_cb = (FGCBSpecialUC) ( FETCH_WCB( *window, Special )); + keyboard_ud = FETCH_USER_DATA_WCB( *window, Keyboard ); + special_ud = FETCH_USER_DATA_WCB( *window, Special ); + } + else + { + keyboard_cb = (FGCBKeyboardUC)( FETCH_WCB( *window, KeyboardUp )); + special_cb = (FGCBSpecialUC) ( FETCH_WCB( *window, SpecialUp )); + keyboard_ud = FETCH_USER_DATA_WCB( *window, KeyboardUp ); + special_ud = FETCH_USER_DATA_WCB( *window, SpecialUp ); + } + + /* Is there a keyboard/special callback hooked for this window? */ + if( keyboard_cb || special_cb ) + { + XComposeStatus composeStatus; + char asciiCode[ 32 ]; + KeySym keySym; + int len; + + /* Check for the ASCII/KeySym codes associated with the event: */ + len = XLookupString( &event.xkey, asciiCode, sizeof(asciiCode), + &keySym, &composeStatus + ); + + /* GLUT API tells us to have two separate callbacks... */ + if( len > 0 ) + { + /* ...one for the ASCII translateable keypresses... */ + if( keyboard_cb ) + { + fgSetWindow( window ); + fgState.Modifiers = fgPlatformGetModifiers( event.xkey.state ); + keyboard_cb( asciiCode[ 0 ], + event.xkey.x, event.xkey.y, + keyboard_ud + ); + fgState.Modifiers = INVALID_MODIFIERS; + } + } + else + { + int special = -1; + + /* + * ...and one for all the others, which need to be + * translated to GLUT_KEY_Xs... + */ + switch( keySym ) + { + case XK_F1: special = GLUT_KEY_F1; break; + case XK_F2: special = GLUT_KEY_F2; break; + case XK_F3: special = GLUT_KEY_F3; break; + case XK_F4: special = GLUT_KEY_F4; break; + case XK_F5: special = GLUT_KEY_F5; break; + case XK_F6: special = GLUT_KEY_F6; break; + case XK_F7: special = GLUT_KEY_F7; break; + case XK_F8: special = GLUT_KEY_F8; break; + case XK_F9: special = GLUT_KEY_F9; break; + case XK_F10: special = GLUT_KEY_F10; break; + case XK_F11: special = GLUT_KEY_F11; break; + case XK_F12: special = GLUT_KEY_F12; break; + + case XK_KP_Left: + case XK_Left: special = GLUT_KEY_LEFT; break; + case XK_KP_Right: + case XK_Right: special = GLUT_KEY_RIGHT; break; + case XK_KP_Up: + case XK_Up: special = GLUT_KEY_UP; break; + case XK_KP_Down: + case XK_Down: special = GLUT_KEY_DOWN; break; + + case XK_KP_Prior: + case XK_Prior: special = GLUT_KEY_PAGE_UP; break; + case XK_KP_Next: + case XK_Next: special = GLUT_KEY_PAGE_DOWN; break; + case XK_KP_Home: + case XK_Home: special = GLUT_KEY_HOME; break; + case XK_KP_End: + case XK_End: special = GLUT_KEY_END; break; + case XK_KP_Insert: + case XK_Insert: special = GLUT_KEY_INSERT; break; + + case XK_Num_Lock : special = GLUT_KEY_NUM_LOCK; break; + case XK_KP_Begin : special = GLUT_KEY_BEGIN; break; + case XK_KP_Delete: special = GLUT_KEY_DELETE; break; + + case XK_Shift_L: special = GLUT_KEY_SHIFT_L; break; + case XK_Shift_R: special = GLUT_KEY_SHIFT_R; break; + case XK_Control_L: special = GLUT_KEY_CTRL_L; break; + case XK_Control_R: special = GLUT_KEY_CTRL_R; break; + case XK_Alt_L: special = GLUT_KEY_ALT_L; break; + case XK_Alt_R: special = GLUT_KEY_ALT_R; break; + case XK_Meta_L: + case XK_Super_L: + special = GLUT_KEY_SUPER_L; + break; + case XK_Meta_R: + case XK_Super_R: + special = GLUT_KEY_SUPER_R; + break; + } + + /* + * Execute the callback (if one has been specified), + * given that the special code seems to be valid... + */ + if( special_cb && (special != -1) ) + { + fgSetWindow( window ); + fgState.Modifiers = fgPlatformGetModifiers( event.xkey.state ); + special_cb( special, event.xkey.x, event.xkey.y, special_ud ); + fgState.Modifiers = INVALID_MODIFIERS; + } + } + } + } + break; + + case ReparentNotify: + break; /* XXX Should disable this event */ + + /* Not handled */ + case GravityNotify: + break; + + default: + /* enter handling of Extension Events here */ + #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H + fgHandleExtensionEvents( &event ); + #endif + break; + } + } +} + + +static Bool match_motion(Display *dpy, XEvent *xev, XPointer arg) +{ + return xev->type == MotionNotify; +} + +void fgPlatformMainLoopPreliminaryWork ( void ) +{ +} + + +/* deal with work list items */ +void fgPlatformInitWork(SFG_Window* window) +{ + /* Notify windowStatus/visibility, position and size get notified on window creation with message handlers above + * XXX CHECK: do the messages happen too early like on windows, so client code cannot have registered + * a callback yet and the message is thus never received by client? + * -> this is a no-op + */ + return; +} + +void fgPlatformPosResZordWork(SFG_Window* window, unsigned int workMask) +{ + if (workMask & GLUT_FULL_SCREEN_WORK) + fgPlatformFullScreenToggle( window ); + if (workMask & GLUT_POSITION_WORK) + fgPlatformPositionWindow( window, window->State.DesiredXpos, window->State.DesiredYpos ); + if (workMask & GLUT_SIZE_WORK) + fgPlatformReshapeWindow ( window, window->State.DesiredWidth, window->State.DesiredHeight ); + if (workMask & GLUT_ZORDER_WORK) + { + if (window->State.DesiredZOrder < 0) + fgPlatformPushWindow( window ); + else + fgPlatformPopWindow( window ); + } +} + +void fgPlatformVisibilityWork(SFG_Window* window) +{ + /* Visibility status of window gets updated in the window message handlers above + * XXX: is this really the case? check + */ + SFG_Window *win = window; + switch (window->State.DesiredVisibility) + { + case DesireHiddenState: + fgPlatformHideWindow( window ); + break; + case DesireIconicState: + /* Call on top-level window */ + while (win->Parent) + win = win->Parent; + fgPlatformIconifyWindow( win ); + break; + case DesireNormalState: + fgPlatformShowWindow( window ); + break; + } +} + diff --git a/src/x11/fg_menu_x11.c b/src/x11/fg_menu_x11.c new file mode 100644 index 0000000..53de825 --- /dev/null +++ b/src/x11/fg_menu_x11.c @@ -0,0 +1,49 @@ +/* + * fg_menu_x11.c + * + * Pull-down menu creation and handling. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Copied for Platform code by Evan Felix + * Creation date: Wed Feb 1, 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "../fg_internal.h" + +/* + * * Private function to get the virtual maximum screen extent + * */ +GLvoid fgPlatformGetGameModeVMaxExtent( SFG_Window* window, int* x, int* y ) +{ + int wx, wy; + Window w; + + XTranslateCoordinates( + fgDisplay.pDisplay.Display, + window->Window.Handle, + fgDisplay.pDisplay.RootWindow, + 0, 0, &wx, &wy, &w); + + *x = fgState.GameModeSize.X + wx; + *y = fgState.GameModeSize.Y + wy; +} + diff --git a/src/x11/fg_spaceball_x11.c b/src/x11/fg_spaceball_x11.c new file mode 100644 index 0000000..155d24b --- /dev/null +++ b/src/x11/fg_spaceball_x11.c @@ -0,0 +1,413 @@ +/* Spaceball support for Linux. + * Written by John Tsiombikas + * Copied for Platform code by Evan Felix + * Creation date: Thur Feb 2 2012 + * + * This code supports 3Dconnexion's 6-dof space-whatever devices. + * It can communicate with either the proprietary 3Dconnexion daemon (3dxsrv) + * free spacenavd (http://spacenav.sourceforge.net), through the "standard" + * magellan X-based protocol. + */ + +#include +#include "../fg_internal.h" + +#include + +extern int fg_sball_initialized; + +enum { + SPNAV_EVENT_ANY, /* used by spnav_remove_events() */ + SPNAV_EVENT_MOTION, + SPNAV_EVENT_BUTTON /* includes both press and release */ +}; + +struct spnav_event_motion { + int type; + int x, y, z; + int rx, ry, rz; + unsigned int period; + int *data; +}; + +struct spnav_event_button { + int type; + int press; + int bnum; +}; + +typedef union spnav_event { + int type; + struct spnav_event_motion motion; + struct spnav_event_button button; +} spnav_event; + + +static int spnav_x11_open(Display *dpy, Window win); +static int spnav_x11_window(Window win); +static int spnav_x11_event(const XEvent *xev, spnav_event *event); +static int spnav_close(void); +static int spnav_fd(void); +static int spnav_remove_events(int type); + +static SFG_Window *spnav_win; + +void fgPlatformInitializeSpaceball(void) +{ + Window w; + + fg_sball_initialized = 1; + if(!fgStructure.CurrentWindow) + { + fg_sball_initialized = -1; + return; + } + + w = fgStructure.CurrentWindow->Window.Handle; + if(spnav_x11_open(fgDisplay.pDisplay.Display, w) == -1) + { + fg_sball_initialized = -1; + return; + } +} + +void fgPlatformSpaceballClose(void) +{ + spnav_close(); +} + +int fgPlatformHasSpaceball(void) +{ + /* XXX this function should somehow query the driver if there's a device + * plugged in, as opposed to just checking if there's a driver to talk to. + */ + return spnav_fd() == -1 ? 0 : 1; +} + +int fgPlatformSpaceballNumButtons(void) { + return 2; +} + +void fgPlatformSpaceballSetWindow(SFG_Window *window) +{ + if(spnav_win != window) { + spnav_x11_window(window->Window.Handle); + spnav_win = window; + } +} + +int fgIsSpaceballXEvent(const XEvent *xev) +{ + spnav_event sev; + + if(spnav_win != fgStructure.CurrentWindow) { + /* this will also initialize spaceball if needed (first call) */ + fgSpaceballSetWindow(fgStructure.CurrentWindow); + } + + if(fg_sball_initialized != 1) { + return 0; + } + + return spnav_x11_event(xev, &sev); +} + +void fgSpaceballHandleXEvent(const XEvent *xev) +{ + spnav_event sev; + + if(fg_sball_initialized == 0) { + fgInitialiseSpaceball(); + if(fg_sball_initialized != 1) { + return; + } + } + + if(spnav_x11_event(xev, &sev)) { + switch(sev.type) { + case SPNAV_EVENT_MOTION: + if(sev.motion.x | sev.motion.y | sev.motion.z) { + INVOKE_WCB(*spnav_win, SpaceMotion, (sev.motion.x, sev.motion.y, sev.motion.z)); + } + if(sev.motion.rx | sev.motion.ry | sev.motion.rz) { + INVOKE_WCB(*spnav_win, SpaceRotation, (sev.motion.rx, sev.motion.ry, sev.motion.rz)); + } + spnav_remove_events(SPNAV_EVENT_MOTION); + break; + + case SPNAV_EVENT_BUTTON: + /* button numbers are 1-based in glutSpaceballButtonFunc */ + INVOKE_WCB(*spnav_win, SpaceButton, (sev.button.bnum + 1, sev.button.press ? GLUT_DOWN : GLUT_UP)); + break; + + default: + break; + } + } +} + +/* +The following code is part of libspnav, part of the spacenav project (spacenav.sf.net) +Copyright (C) 2007-2009 John Tsiombikas + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#include +#include +#include +#include + +#include +#include + +static Window get_daemon_window(Display *dpy); +static int catch_badwin(Display *dpy, XErrorEvent *err); + +static Display *dpy; +static Window app_win; +static Atom motion_event, button_press_event, button_release_event, command_event; + +enum { + CMD_APP_WINDOW = 27695, + CMD_APP_SENS +}; + +#define IS_OPEN dpy + +struct event_node { + spnav_event event; + struct event_node *next; +}; + +static int spnav_x11_open(Display *display, Window win) +{ + if(IS_OPEN) { + return -1; + } + + dpy = display; + + motion_event = XInternAtom(dpy, "MotionEvent", True); + button_press_event = XInternAtom(dpy, "ButtonPressEvent", True); + button_release_event = XInternAtom(dpy, "ButtonReleaseEvent", True); + command_event = XInternAtom(dpy, "CommandEvent", True); + + if(!motion_event || !button_press_event || !button_release_event || !command_event) { + dpy = 0; + return -1; /* daemon not started */ + } + + if(spnav_x11_window(win) == -1) { + dpy = 0; + return -1; /* daemon not started */ + } + + app_win = win; + return 0; +} + +static int spnav_close(void) +{ + if(dpy) { + spnav_x11_window(DefaultRootWindow(dpy)); + app_win = 0; + dpy = 0; + return 0; + } + return -1; +} + +static int spnav_x11_window(Window win) +{ + int (*prev_xerr_handler)(Display*, XErrorEvent*); + XEvent xev; + Window daemon_win; + + if(!IS_OPEN) { + return -1; + } + + if(!(daemon_win = get_daemon_window(dpy))) { + return -1; + } + + prev_xerr_handler = XSetErrorHandler(catch_badwin); + + xev.type = ClientMessage; + xev.xclient.send_event = False; + xev.xclient.display = dpy; + xev.xclient.window = win; + xev.xclient.message_type = command_event; + xev.xclient.format = 16; + xev.xclient.data.s[0] = ((unsigned int)win & 0xffff0000) >> 16; + xev.xclient.data.s[1] = (unsigned int)win & 0xffff; + xev.xclient.data.s[2] = CMD_APP_WINDOW; + + XSendEvent(dpy, daemon_win, False, 0, &xev); + XSync(dpy, False); + + XSetErrorHandler(prev_xerr_handler); + return 0; +} + +static int spnav_fd(void) +{ + if(dpy) { + return ConnectionNumber(dpy); + } + return -1; +} + +/*static int spnav_wait_event(spnav_event *event) +{ + if(dpy) { + for(;;) { + XEvent xev; + XNextEvent(dpy, &xev); + + if(spnav_x11_event(&xev, event) > 0) { + return event->type; + } + } + } + return 0; +} + +static int spnav_poll_event(spnav_event *event) +{ + if(dpy) { + if(XPending(dpy)) { + XEvent xev; + XNextEvent(dpy, &xev); + + return spnav_x11_event(&xev, event); + } + } + return 0; +}*/ + +static Bool match_events(Display *dpy, XEvent *xev, char *arg) +{ + int evtype = *(int*)arg; + + if(xev->type != ClientMessage) { + return False; + } + + if(xev->xclient.message_type == motion_event) { + return !evtype || evtype == SPNAV_EVENT_MOTION ? True : False; + } + if(xev->xclient.message_type == button_press_event || + xev->xclient.message_type == button_release_event) { + return !evtype || evtype == SPNAV_EVENT_BUTTON ? True : False; + } + return False; +} + +static int spnav_remove_events(int type) +{ + int rm_count = 0; + + if(dpy) { + XEvent xev; + + while(XCheckIfEvent(dpy, &xev, match_events, (char*)&type)) { + rm_count++; + } + return rm_count; + } + return 0; +} + +static int spnav_x11_event(const XEvent *xev, spnav_event *event) +{ + int i; + int xmsg_type; + + if(xev->type != ClientMessage) { + return 0; + } + + xmsg_type = xev->xclient.message_type; + + if(xmsg_type != motion_event && xmsg_type != button_press_event && + xmsg_type != button_release_event) { + return 0; + } + + if(xmsg_type == motion_event) { + event->type = SPNAV_EVENT_MOTION; + event->motion.data = &event->motion.x; + + for(i=0; i<6; i++) { + event->motion.data[i] = xev->xclient.data.s[i + 2]; + } + event->motion.period = xev->xclient.data.s[8]; + } else { + event->type = SPNAV_EVENT_BUTTON; + event->button.press = xmsg_type == button_press_event ? 1 : 0; + event->button.bnum = xev->xclient.data.s[2]; + } + return event->type; +} + + +static Window get_daemon_window(Display *dpy) +{ + Window win, root_win; + XTextProperty wname; + Atom type; + int fmt; + unsigned long nitems, bytes_after; + unsigned char *prop; + + root_win = DefaultRootWindow(dpy); + + XGetWindowProperty(dpy, root_win, command_event, 0, 1, False, AnyPropertyType, &type, &fmt, &nitems, &bytes_after, &prop); + if(!prop) { + return 0; + } + + win = *(Window*)prop; + XFree(prop); + + if(!XGetWMName(dpy, win, &wname) || strcmp("Magellan Window", (char*)wname.value) != 0) { + return 0; + } + + return win; +} + +static int catch_badwin(Display *dpy, XErrorEvent *err) +{ + char buf[256]; + + if(err->error_code == BadWindow) { + /* do nothing? */ + } else { + XGetErrorText(dpy, err->error_code, buf, sizeof buf); + fprintf(stderr, "Caught unexpected X error: %s\n", buf); + } + return 0; +} + diff --git a/src/x11/fg_state_x11.c b/src/x11/fg_state_x11.c new file mode 100644 index 0000000..19be997 --- /dev/null +++ b/src/x11/fg_state_x11.c @@ -0,0 +1,257 @@ +/* + * fg_state_x11.c + * + * X11-specific freeglut state query methods. + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by John F. Fay, + * Creation date: Sat Feb 4 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" +#ifdef EGL_VERSION_1_0 +#include "egl/fg_state_egl.h" +#else +#include "x11/fg_state_x11_glx.h" +#endif + +int fgPlatformGlutDeviceGet ( GLenum eWhat ) +{ + switch( eWhat ) + { + case GLUT_HAS_KEYBOARD: + /* + * X11 has a core keyboard by definition, although it can + * be present as a virtual/dummy keyboard. For now, there + * is no reliable way to tell if a real keyboard is present. + */ + return 1; + + /* X11 has a mouse by definition */ + case GLUT_HAS_MOUSE: + return 1 ; + + case GLUT_NUM_MOUSE_BUTTONS: + /* We should be able to pass NULL when the last argument is zero, + * but at least one X server has a bug where this causes a segfault. + * + * In XFree86/Xorg servers, a mouse wheel is seen as two buttons + * rather than an Axis; "fg_main.c" expects this when + * checking for a wheel event. + */ + { + unsigned char map; + int nbuttons = XGetPointerMapping(fgDisplay.pDisplay.Display, &map,0); + return nbuttons; + } + + default: + fgWarning( "glutDeviceGet(): missing enum handle %d", eWhat ); + break; + } + + /* And now -- the failure. */ + return -1; +} + + +int fgPlatformGlutGet ( GLenum eWhat ) +{ + switch( eWhat ) + { + + /* + * Those calls are somewhat similar, as they use XGetWindowAttributes() + * function + */ + case GLUT_WINDOW_X: + case GLUT_WINDOW_Y: + { + int x, y; + Window p,w; + + if( fgStructure.CurrentWindow == NULL ) + return 0; + + if (fgStructure.CurrentWindow->Parent) + /* For child window, we should return relative to upper-left + * of parent's client area. + */ + p = fgStructure.CurrentWindow->Parent->Window.Handle; + else + p = fgDisplay.pDisplay.RootWindow; + + XTranslateCoordinates( + fgDisplay.pDisplay.Display, + fgStructure.CurrentWindow->Window.Handle, + p, + 0, 0, &x, &y, &w); + + switch ( eWhat ) + { + case GLUT_WINDOW_X: return x; + case GLUT_WINDOW_Y: return y; + } + } + + case GLUT_WINDOW_BORDER_WIDTH: + case GLUT_WINDOW_HEADER_HEIGHT: + { + Atom actual_type, net_extents; + int actual_format; + unsigned long nitems, bytes_after; + unsigned char *data = NULL; + int result, top, left; + + if (fgStructure.CurrentWindow == NULL || fgStructure.CurrentWindow->Parent) + /* can't get widths/heights if no current window + * and child windows don't have borders */ + return 0; + + /* try to get through _NET_FRAME_EXTENTS */ + net_extents = XInternAtom(fgDisplay.pDisplay.Display, "_NET_FRAME_EXTENTS", False); + + result = XGetWindowProperty( + fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle, net_extents, + 0, 4, False, AnyPropertyType, + &actual_type, &actual_format, + &nitems, &bytes_after, &data); + + if (result == Success && nitems == 4 && bytes_after == 0) + /* got the data we expected, here's to hoping that + * _NET_FRAME_EXTENTS is supported and the data + * contain sensible values */ + { + long *extents = (long *)data; + left = (int) extents[0]; /* we take left as border width, consistent with old logic. bottom and right better be the same... */ + top = (int) extents[2]; + } + else + { + /* try in the previous way as fall-back */ + Window w; + int x,y; + + XTranslateCoordinates( + fgDisplay.pDisplay.Display, + fgStructure.CurrentWindow->Window.Handle, + fgDisplay.pDisplay.RootWindow, + 0, 0, &x, &y, &w); + + if (w == 0) + /* logic below needs w */ + return 0; + + XTranslateCoordinates( + fgDisplay.pDisplay.Display, + fgStructure.CurrentWindow->Window.Handle, + w, 0, 0, &x, &y, &w); + + left = x; + top = y; + } + if (result == Success) + XFree(data); + + switch ( eWhat ) + { + case GLUT_WINDOW_BORDER_WIDTH: return left; + case GLUT_WINDOW_HEADER_HEIGHT: return top; + } + } + + case GLUT_WINDOW_WIDTH: + case GLUT_WINDOW_HEIGHT: + { + XWindowAttributes winAttributes; + + if( fgStructure.CurrentWindow == NULL ) + return 0; + XGetWindowAttributes( + fgDisplay.pDisplay.Display, + fgStructure.CurrentWindow->Window.Handle, + &winAttributes + ); + switch ( eWhat ) + { + case GLUT_WINDOW_WIDTH: return winAttributes.width ; + case GLUT_WINDOW_HEIGHT: return winAttributes.height ; + } + } + + /* Colormap size is handled in a bit different way than all the rest */ + case GLUT_WINDOW_COLORMAP_SIZE: + if( +#ifndef EGL_VERSION_1_0 + fgPlatformGetConfig( GLX_RGBA ) || +#endif + fgStructure.CurrentWindow == NULL) + { + /* + * We've got a RGBA visual, so there is no colormap at all. + * The other possibility is that we have no current window set. + */ + return 0; + } + else + { + XVisualInfo * visualInfo; + int result; +#ifdef EGL_VERSION_1_0 + EGLint vid = 0; + XVisualInfo visualTemplate; + int num_visuals; + if (!eglGetConfigAttrib(fgDisplay.pDisplay.egl.Display, + fgStructure.CurrentWindow->Window.pContext.egl.Config, + EGL_NATIVE_VISUAL_ID, &vid)) + fgError("eglGetConfigAttrib(EGL_NATIVE_VISUAL_ID) failed"); + visualTemplate.visualid = vid; + visualInfo = XGetVisualInfo(fgDisplay.pDisplay.Display, VisualIDMask, &visualTemplate, &num_visuals); +#else + { +#ifdef USE_FBCONFIG + GLXFBConfig fbconfig; + + fbconfig = fgStructure.CurrentWindow->Window.pContext.FBConfig; + visualInfo = glXGetVisualFromFBConfig(fgDisplay.pDisplay.Display, fbconfig); +#else + visualInfo = fgStructure.CurrentWindow->Window.pContext.visinf; +#endif + } +#endif + result = visualInfo->visual->map_entries; + +#ifdef USE_FBCONFIG + /* only free if we got it from glXGetVisualFromFBConfig */ + XFree(visualInfo); +#endif + + return result; + } + + default: +#ifdef EGL_VERSION_1_0 + return fghPlatformGlutGetEGL(eWhat); +#else + return fghPlatformGlutGetGLX(eWhat); +#endif + } +} diff --git a/src/x11/fg_state_x11_glx.c b/src/x11/fg_state_x11_glx.c new file mode 100644 index 0000000..f82cff9 --- /dev/null +++ b/src/x11/fg_state_x11_glx.c @@ -0,0 +1,257 @@ +/* + * fg_state_x11_glx.c + * + * X11-specific freeglut state query methods. + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by John F. Fay, + * Creation date: Sat Feb 4 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" +#include "x11/fg_window_x11_glx.h" + +#ifndef GL_SAMPLES +#define GL_SAMPLES 0x80a9 +#endif + +/* + * Queries the GL context about some attributes + */ +int fgPlatformGetConfig(int attribute) +{ + int res, retval = 0; + Display *dpy; + + if(!fgStructure.CurrentWindow) { + return 0; + } + + dpy = fgDisplay.pDisplay.Display; + { +#ifdef USE_FBCONFIG + GLXFBConfig fbcfg; + fbcfg = fgStructure.CurrentWindow->Window.pContext.FBConfig; + res = glXGetFBConfigAttrib(dpy, fbcfg, attribute, &retval); +#else + XVisualInfo *vinf; + vinf = fgStructure.CurrentWindow->Window.pContext.visinf; + res = glXGetConfig(dpy, vinf, attribute, &retval); +#endif + } + + if(res != 0) { + if(res == GLX_BAD_ATTRIBUTE) { + fgWarning("Attempting to query invalid GLX attribute: 0x%04x\n", attribute); + } + return 0; + } + return retval; +} + +int fghPlatformGlutGetGLX ( GLenum eWhat ) +{ + switch( eWhat ) + { + /* + * The window/context specific queries are handled mostly by + * fgPlatformGetConfig(). + */ + case GLUT_WINDOW_NUM_SAMPLES: + { + int nsamples = 0; +#ifdef GLX_VERSION_1_3 + glGetIntegerv(GL_SAMPLES, &nsamples); + glGetError(); /* clear error if GL_SAMPLES is not supported */ +#endif + return nsamples; + } + + /* + * The rest of GLX queries under X are general enough to use a macro to + * check them + */ +# define GLX_QUERY(a,b) case a: return fgPlatformGetConfig( b ); + + GLX_QUERY( GLUT_WINDOW_RGBA, GLX_RGBA ); + GLX_QUERY( GLUT_WINDOW_DOUBLEBUFFER, GLX_DOUBLEBUFFER ); + GLX_QUERY( GLUT_WINDOW_BUFFER_SIZE, GLX_BUFFER_SIZE ); + GLX_QUERY( GLUT_WINDOW_STENCIL_SIZE, GLX_STENCIL_SIZE ); + GLX_QUERY( GLUT_WINDOW_DEPTH_SIZE, GLX_DEPTH_SIZE ); + GLX_QUERY( GLUT_WINDOW_RED_SIZE, GLX_RED_SIZE ); + GLX_QUERY( GLUT_WINDOW_GREEN_SIZE, GLX_GREEN_SIZE ); + GLX_QUERY( GLUT_WINDOW_BLUE_SIZE, GLX_BLUE_SIZE ); + GLX_QUERY( GLUT_WINDOW_ALPHA_SIZE, GLX_ALPHA_SIZE ); + GLX_QUERY( GLUT_WINDOW_ACCUM_RED_SIZE, GLX_ACCUM_RED_SIZE ); + GLX_QUERY( GLUT_WINDOW_ACCUM_GREEN_SIZE, GLX_ACCUM_GREEN_SIZE ); + GLX_QUERY( GLUT_WINDOW_ACCUM_BLUE_SIZE, GLX_ACCUM_BLUE_SIZE ); + GLX_QUERY( GLUT_WINDOW_ACCUM_ALPHA_SIZE, GLX_ACCUM_ALPHA_SIZE ); + GLX_QUERY( GLUT_WINDOW_STEREO, GLX_STEREO ); + GLX_QUERY( GLUT_WINDOW_SRGB, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB); + +# undef GLX_QUERY + + /* I do not know yet if there will be a fgChooseVisual() function for Win32 */ + case GLUT_DISPLAY_MODE_POSSIBLE: + { + /* We should not have to call fghChooseConfig again here. */ +#ifdef USE_FBCONFIG + GLXFBConfig config; +#else + XVisualInfo *config; +#endif + return fghChooseConfig(&config); + } + + /* This is system-dependent */ + case GLUT_WINDOW_FORMAT_ID: + if( fgStructure.CurrentWindow == NULL ) + return 0; + +#ifdef USE_FBCONFIG + return fgPlatformGetConfig( GLX_VISUAL_ID ); +#else + return fgStructure.CurrentWindow->Window.pContext.visinf->visualid; +#endif + + default: + fgWarning( "glutGet(): missing enum handle %d", eWhat ); + break; + } + + return -1; +} + +#ifdef USE_FBCONFIG +int *fgPlatformGlutGetModeValues(GLenum eWhat, int *size) +{ + int *array; + + int attributes[9]; + GLXFBConfig * fbconfigArray; /* Array of FBConfigs */ + int fbconfigArraySize; /* Number of FBConfigs in the array */ + int attribute_name = 0; + + array = NULL; + *size = 0; + + switch (eWhat) + { + case GLUT_AUX: + case GLUT_MULTISAMPLE: + + attributes[0] = GLX_BUFFER_SIZE; + attributes[1] = GLX_DONT_CARE; + + switch (eWhat) + { + case GLUT_AUX: + /* + FBConfigs are now sorted by increasing number of auxiliary + buffers. We want at least one buffer. + */ + attributes[2] = GLX_AUX_BUFFERS; + attributes[3] = 1; + attributes[4] = None; + + attribute_name = GLX_AUX_BUFFERS; + + break; + + + case GLUT_MULTISAMPLE: + attributes[2] = GLX_AUX_BUFFERS; + attributes[3] = GLX_DONT_CARE; + attributes[4] = GLX_SAMPLE_BUFFERS; + attributes[5] = 1; + /* + FBConfigs are now sorted by increasing number of samples per + pixel. We want at least one sample. + */ + attributes[6] = GLX_SAMPLES; + attributes[7] = 1; + attributes[8] = None; + + attribute_name = GLX_SAMPLES; + + break; + } + + fbconfigArray = glXChooseFBConfig(fgDisplay.pDisplay.Display, + fgDisplay.pDisplay.Screen, + attributes, + &fbconfigArraySize); + + if (fbconfigArray != NULL) + { + int * temp_array; + int result __fg_unused; /* Returned by glXGetFBConfigAttrib. Not checked. */ + int previous_value; + int i; + + temp_array = malloc(sizeof(int) * fbconfigArraySize); + previous_value = 0; + + for (i = 0; i < fbconfigArraySize; i++) + { + int value; + + result = glXGetFBConfigAttrib(fgDisplay.pDisplay.Display, + fbconfigArray[i], + attribute_name, + &value); + if (value > previous_value) + { + temp_array[*size] = value; + previous_value = value; + (*size)++; + } + } + + array = malloc(sizeof(int) * (*size)); + for (i = 0; i < *size; i++) + { + array[i] = temp_array[i]; + } + + free(temp_array); + XFree(fbconfigArray); + } + + break; + + default: + break; + } + + return array; +} + +#else /* !def USE_FBCONFIG */ + +int *fgPlatformGlutGetModeValues(GLenum what, int *size) +{ + /* TODO */ + *size = 0; + return 0; +} + +#endif /* !def USE_FBCONFIG */ diff --git a/src/x11/fg_state_x11_glx.h b/src/x11/fg_state_x11_glx.h new file mode 100644 index 0000000..c6349a2 --- /dev/null +++ b/src/x11/fg_state_x11_glx.h @@ -0,0 +1,35 @@ +/* + * fg_state_x11_glx.c + * + * X11-specific freeglut state query methods. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Copied for Platform code by Evan Felix + * Creation date: Thur Feb 2 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __FG_STATE_X11_GLX_H__ +#define __FG_STATE_X11_GLX_H__ + +int fgPlatformGetConfig(int attribute); +int fghPlatformGlutGetGLX(GLenum eWhat); + +#endif diff --git a/src/x11/fg_structure_x11.c b/src/x11/fg_structure_x11.c new file mode 100644 index 0000000..0d42d66 --- /dev/null +++ b/src/x11/fg_structure_x11.c @@ -0,0 +1,51 @@ +/* + * fg_structure.c + * + * Windows and menus need tree structure + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Copied for Platform code by Evan Felix + * Creation date: Thur Feb 2 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "fg_internal.h" +#ifdef EGL_VERSION_1_0 +#include "egl/fg_structure_egl.h" +#endif + +extern SFG_Structure fgStructure; + +void fgPlatformCreateWindow ( SFG_Window *window ) +{ +#ifdef EGL_VERSION_1_0 + fghPlatformCreateWindowEGL(window); +#else +#ifdef USE_FBCONFIG + window->Window.pContext.FBConfig = NULL; +#else + window->Window.pContext.visinf = NULL; +#endif +#endif + + window->State.pWState.OldHeight = window->State.pWState.OldWidth = -1; +} + diff --git a/src/x11/fg_window_x11.c b/src/x11/fg_window_x11.c new file mode 100644 index 0000000..f31a845 --- /dev/null +++ b/src/x11/fg_window_x11.c @@ -0,0 +1,597 @@ +/* + * fg_window_x11.c + * + * Window management methods for X11 + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Copied for Platform code by Evan Felix + * Creation date: Thur Feb 2 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#define FREEGLUT_BUILDING_LIB +#include +#include /* LONG_MAX */ +#include /* usleep, gethostname, getpid */ +#include /* pid_t */ +#include "../fg_internal.h" + +#ifdef EGL_VERSION_1_0 +#include "egl/fg_window_egl.h" +#define fghCreateNewContext fghCreateNewContextEGL +#else +#include "x11/fg_window_x11_glx.h" +#endif + +#ifndef HOST_NAME_MAX +#define HOST_NAME_MAX 255 +#endif + +/* Motif window hints, only define needed ones */ +typedef struct +{ + unsigned long flags; + unsigned long functions; + unsigned long decorations; + long input_mode; + unsigned long status; +} MotifWmHints; +#define MWM_HINTS_DECORATIONS (1L << 1) +#define MWM_DECOR_BORDER (1L << 1) + +static int fghResizeFullscrToggle(void) +{ + XWindowAttributes attributes; + SFG_Window *win = fgStructure.CurrentWindow; + + if(glutGet(GLUT_FULL_SCREEN)) { + /* restore original window size */ + fgStructure.CurrentWindow->State.WorkMask = GLUT_SIZE_WORK; + fgStructure.CurrentWindow->State.DesiredWidth = win->State.pWState.OldWidth; + fgStructure.CurrentWindow->State.DesiredHeight = win->State.pWState.OldHeight; + + } else { + fgStructure.CurrentWindow->State.pWState.OldWidth = win->State.Width; + fgStructure.CurrentWindow->State.pWState.OldHeight = win->State.Height; + + /* resize the window to cover the entire screen */ + XGetWindowAttributes(fgDisplay.pDisplay.Display, + fgStructure.CurrentWindow->Window.Handle, + &attributes); + + /* + * The "x" and "y" members of "attributes" are the window's coordinates + * relative to its parent, i.e. to the decoration window. + */ + XMoveResizeWindow(fgDisplay.pDisplay.Display, + fgStructure.CurrentWindow->Window.Handle, + -attributes.x, + -attributes.y, + fgDisplay.ScreenWidth, + fgDisplay.ScreenHeight); + } + return 0; +} + +#define _NET_WM_STATE_TOGGLE 2 +static int fghEwmhFullscrToggle(void) +{ + XEvent xev; + long evmask = SubstructureRedirectMask | SubstructureNotifyMask; + + if(!fgDisplay.pDisplay.State || !fgDisplay.pDisplay.StateFullScreen) { + return -1; + } + + xev.type = ClientMessage; + xev.xclient.window = fgStructure.CurrentWindow->Window.Handle; + xev.xclient.message_type = fgDisplay.pDisplay.State; + xev.xclient.format = 32; + xev.xclient.data.l[0] = _NET_WM_STATE_TOGGLE; + xev.xclient.data.l[1] = fgDisplay.pDisplay.StateFullScreen; + xev.xclient.data.l[2] = 0; /* no second property to toggle */ + xev.xclient.data.l[3] = 1; /* source indication: application */ + xev.xclient.data.l[4] = 0; /* unused */ + + if(!XSendEvent(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow, 0, evmask, &xev)) { + return -1; + } + return 0; +} + +static int fghToggleFullscreen(void) +{ + /* first try the EWMH (_NET_WM_STATE) method ... */ + if(fghEwmhFullscrToggle() != -1) { + return 0; + } + + /* fall back to resizing the window */ + if(fghResizeFullscrToggle() != -1) { + return 0; + } + return -1; +} + +static Bool fghWindowIsVisible( Display *display, XEvent *event, XPointer arg) +{ + Window window = (Window)arg; + return (event->type == MapNotify) && (event->xmap.window == window); +} + +/* + * Opens a window. Requires a SFG_Window object created and attached + * to the freeglut structure. OpenGL context is created here. + */ +void fgPlatformOpenWindow( SFG_Window* window, const char* title, + GLboolean positionUse, int x, int y, + GLboolean sizeUse, int w, int h, + GLboolean gameMode, GLboolean isSubWindow ) +{ + Display *dpy = fgDisplay.pDisplay.Display; + Window rootwin = fgDisplay.pDisplay.RootWindow; + Window parent = window->Parent ? window->Parent->Window.Handle : 0; + Window win; + Colormap cmap; + XVisualInfo * visualInfo = NULL; + XSetWindowAttributes wattr; + XTextProperty txprop; + XSizeHints sizeHints; + XWMHints wmHints; + XEvent eventReturnBuffer; /* return buffer required for a call */ + unsigned long mask; + unsigned int current_DisplayMode = fgState.DisplayMode; + XEvent fakeEvent = {0}; + Atom xa_motif_wm_hints = XInternAtom(dpy, "_MOTIF_WM_HINTS", False); + +#ifdef EGL_VERSION_1_0 + EGLint vid = 0; + XVisualInfo visualTemplate; + int num_visuals; +#endif + + /* Save the display mode if we are creating a menu window */ + if(window->IsMenu && !fgStructure.MenuContext) { + fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB; + } + +#ifdef EGL_VERSION_1_0 +#define WINDOW_CONFIG window->Window.pContext.egl.Config +#else +#ifdef USE_FBCONFIG +#define WINDOW_CONFIG window->Window.pContext.FBConfig +#else +#define WINDOW_CONFIG window->Window.pContext.visinf +#endif /* !def USE_FBCONFIG */ +#endif + fghChooseConfig(&WINDOW_CONFIG); + + if(window->IsMenu && !fgStructure.MenuContext) { + fgState.DisplayMode = current_DisplayMode; + } + + if(!WINDOW_CONFIG) { + /* + * The "fghChooseConfig" returned a null meaning that the visual + * context is not available. + * Try a couple of variations to see if they will work. + */ +#ifndef EGL_VERSION_1_0 + if(!(fgState.DisplayMode & GLUT_DOUBLE)) { + fgState.DisplayMode |= GLUT_DOUBLE; + fghChooseConfig(&WINDOW_CONFIG); + fgState.DisplayMode &= ~GLUT_DOUBLE; + + if(WINDOW_CONFIG) goto done_retry; + } +#endif + + if(fgState.DisplayMode & GLUT_MULTISAMPLE) { + fgState.DisplayMode &= ~GLUT_MULTISAMPLE; + fghChooseConfig(&WINDOW_CONFIG); + fgState.DisplayMode |= GLUT_MULTISAMPLE; + + if(WINDOW_CONFIG) goto done_retry; + } + + if(fgState.DisplayMode & GLUT_SRGB) { + fgState.DisplayMode &= ~GLUT_SRGB; + fghChooseConfig(&WINDOW_CONFIG); + fgState.DisplayMode |= GLUT_SRGB; + + if(WINDOW_CONFIG) goto done_retry; + } + } +done_retry: + +#ifdef USE_FBCONFIG + FREEGLUT_INTERNAL_ERROR_EXIT(WINDOW_CONFIG != NULL, + "FBConfig with necessary capabilities not found", "fgOpenWindow"); +#else + FREEGLUT_INTERNAL_ERROR_EXIT(WINDOW_CONFIG != NULL, + "GLX Visual with necessary capabilities not found", "fgOpenWindow"); +#endif + + /* Get the X visual. */ +#ifdef EGL_VERSION_1_0 + if(!eglGetConfigAttrib(fgDisplay.pDisplay.egl.Display, window->Window.pContext.egl.Config, EGL_NATIVE_VISUAL_ID, &vid)) { + fgError("eglGetConfigAttrib(EGL_NATIVE_VISUAL_ID) failed"); + } + visualTemplate.visualid = vid; + visualInfo = XGetVisualInfo(dpy, VisualIDMask, &visualTemplate, &num_visuals); +#else +#ifdef USE_FBCONFIG + visualInfo = glXGetVisualFromFBConfig(dpy, window->Window.pContext.FBConfig); + + FREEGLUT_INTERNAL_ERROR_EXIT( visualInfo != NULL, + "visualInfo could not be retrieved from FBConfig", "fgOpenWindow"); +#else + visualInfo = window->Window.pContext.visinf; +#endif /* !def USE_FBCONFIG */ +#endif /* GLX part */ + + if(fgState.DisplayMode & GLUT_INDEX) { + cmap = XCreateColormap(dpy, rootwin, visualInfo->visual, AllocAll); + FREEGLUT_INTERNAL_ERROR_EXIT(cmap, + "Failed to allocate the whole colormap, which is required in index color mode", "fgOpenWindow"); + window->Window.cmap_size = visualInfo->colormap_size; + } else { + cmap = XCreateColormap(dpy, rootwin, visualInfo->visual, AllocNone); + window->Window.cmap_size = 0; + } + window->Window.cmap = cmap; + + /* + * XXX HINT: the masks should be updated when adding/removing callbacks. + * XXX This might speed up message processing. Is that true? + * XXX + * XXX A: Not appreciably, but it WILL make it easier to debug. + * XXX Try tracing old GLUT and try tracing freeglut. Old GLUT + * XXX turns off events that it doesn't need and is a whole lot + * XXX more pleasant to trace. (Think mouse-motion! Tons of + * XXX ``bonus'' GUI events stream in.) + * + * TODO: we absolutely need to fix this. In network rendering, flooding the + * wire with unnecessary mouse motion events is Bad. At the very least + * make the PointerMotionMask dynamic. + */ + wattr.event_mask = + StructureNotifyMask | SubstructureNotifyMask | ExposureMask | + ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | + VisibilityChangeMask | EnterWindowMask | LeaveWindowMask | + PointerMotionMask | ButtonMotionMask; + wattr.background_pixmap = None; + wattr.background_pixel = 0; + wattr.border_pixel = 0; + wattr.colormap = cmap; + + mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask; + + if(window->IsMenu || gameMode) { + wattr.override_redirect = True; + mask |= CWOverrideRedirect; + } + + if(!positionUse) + x = y = -1; /* default window position */ + if(!sizeUse) + w = h = 300; /* default window size */ + + win = XCreateWindow(dpy, parent ? parent : rootwin, x, y, w, h, 0, + visualInfo->depth, InputOutput, visualInfo->visual, mask, &wattr); + window->Window.Handle = win; + + /* Fake configure event to force viewport setup + * even with no window manager. + */ + fakeEvent.xconfigure.type = ConfigureNotify; + fakeEvent.xconfigure.display = dpy; + fakeEvent.xconfigure.window = win; + fakeEvent.xconfigure.x = x; + fakeEvent.xconfigure.y = y; + fakeEvent.xconfigure.width = w; + fakeEvent.xconfigure.height = h; + XPutBackEvent(dpy, &fakeEvent); + + /* + * The GLX context creation, possibly trying the direct context rendering + * or else use the current context if the user has so specified + */ + if(window->IsMenu) { + /* + * If there isn't already an OpenGL rendering context for menu + * windows, make one + */ + if(!fgStructure.MenuContext) { + fgStructure.MenuContext = malloc(sizeof *fgStructure.MenuContext); + fgStructure.MenuContext->MContext = fghCreateNewContext(window); + } + + /* window->Window.Context = fgStructure.MenuContext->MContext; */ + window->Window.Context = fghCreateNewContext(window); + + } else if(fgState.UseCurrentContext) { +#ifdef EGL_VERSION_1_0 + window->Window.Context = eglGetCurrentContext(); +#else + window->Window.Context = glXGetCurrentContext(); +#endif + + if(!window->Window.Context) { + window->Window.Context = fghCreateNewContext(window); + } + } else { + window->Window.Context = fghCreateNewContext(window); + } + +#if !defined( __FreeBSD__ ) && !defined( __NetBSD__ ) && !defined(EGL_VERSION_1_0) + if(!glXIsDirect(dpy, window->Window.Context)) { + if(fgState.DirectContext == GLUT_FORCE_DIRECT_CONTEXT) { + fgError("Unable to force direct context rendering for window '%s'", title); + } + } +#endif + + sizeHints.flags = 0; + if(positionUse) + sizeHints.flags |= USPosition; + if(sizeUse) + sizeHints.flags |= USSize; + + /* + * Fill in the size hints values now (the x, y, width and height + * settings are obsolete, are there any more WMs that support them?) + * Unless the X servers actually stop supporting these, we should + * continue to fill them in. It is *not* our place to tell the user + * that they should replace a window manager that they like, and which + * works, just because *we* think that it's not "modern" enough. + */ + sizeHints.x = x; + sizeHints.y = y; + sizeHints.width = w; + sizeHints.height = h; + + wmHints.flags = StateHint; + wmHints.initial_state = fgState.ForceIconic ? IconicState : NormalState; + /* Prepare the window and iconified window names... */ + XStringListToTextProperty((char**)&title, 1, &txprop); + + XSetWMProperties(dpy, win, &txprop, &txprop, 0, 0, &sizeHints, &wmHints, 0); + XFree(txprop.value); + + XSetWMProtocols(dpy, win, &fgDisplay.pDisplay.DeleteWindow, 1); + + if (!isSubWindow && !window->IsMenu && + ((fgState.DisplayMode & GLUT_BORDERLESS) || (fgState.DisplayMode & GLUT_CAPTIONLESS))) + { + /* _MOTIF_WM_HINTS is replaced by _NET_WM_WINDOW_TYPE, but that property does not allow precise + * control over the visual style of the window, which is what we are trying to achieve here. + * Stick with Motif and hope for the best... */ + MotifWmHints hints = {0}; + hints.flags = MWM_HINTS_DECORATIONS; + hints.decorations = (fgState.DisplayMode & GLUT_CAPTIONLESS) ? MWM_DECOR_BORDER:0; + + XChangeProperty(dpy, win, xa_motif_wm_hints, xa_motif_wm_hints, 32, PropModeReplace, + (unsigned char*)&hints, sizeof(MotifWmHints) / sizeof(long)); + } + + + if (fgDisplay.pDisplay.NetWMSupported + && fgDisplay.pDisplay.NetWMPid != None + && fgDisplay.pDisplay.ClientMachine != None) + { + char hostname[HOST_NAME_MAX]; + pid_t pid = getpid(); + + if (pid > 0 && gethostname(hostname, sizeof(hostname)) > -1) + { + hostname[sizeof(hostname) - 1] = '\0'; + + XChangeProperty(dpy, win, fgDisplay.pDisplay.NetWMPid, XA_CARDINAL, 32, + PropModeReplace, (unsigned char*)&pid, 1); + + XChangeProperty(dpy, win, fgDisplay.pDisplay.ClientMachine, XA_STRING, 8, + PropModeReplace, (unsigned char*)hostname, strlen(hostname)); + } + } + +#ifdef EGL_VERSION_1_0 + fghPlatformOpenWindowEGL(window); +#elif defined(GLX_VERSION_1_3) + glXMakeContextCurrent(dpy, win, win, window->Window.Context); +#else + glXMakeCurrent(dpy, win, window->Window.Context); +#endif + + /* register extension events _before_ window is mapped */ +#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H + fgRegisterDevices(dpy, win); +#endif + + if(!window->IsMenu) { /* Don't show window after creation if its a menu */ + XMapWindow(dpy, win); + window->State.Visible = GL_TRUE; + } + +#ifdef USE_FBCONFIG + /* on the non-fbconfig path, the visualInfo pointer is the one owned by the + * window, so delete only if we got this from glXGetVisualFromFBConfig + */ + XFree(visualInfo); +#endif + + /* wait till window visible */ + if(!isSubWindow && !window->IsMenu) { + XPeekIfEvent(dpy, &eventReturnBuffer, &fghWindowIsVisible, (XPointer)window->Window.Handle); + } +#undef WINDOW_CONFIG +} + + +/* + * Request a window resize + */ +void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height ) +{ + XResizeWindow( fgDisplay.pDisplay.Display, window->Window.Handle, + width, height ); + XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */ +} + + +/* + * Closes a window, destroying the frame and OpenGL context + */ +void fgPlatformCloseWindow( SFG_Window* window ) +{ +#ifdef EGL_VERSION_1_0 + fghPlatformCloseWindowEGL(window); +#else + if( window->Window.Context ) + glXDestroyContext( fgDisplay.pDisplay.Display, window->Window.Context ); +#ifdef USE_FBCONFIG + window->Window.pContext.FBConfig = NULL; +#else + XFree(window->Window.pContext.visinf); + window->Window.pContext.visinf = NULL; +#endif /* !def USE_FBCONFIG */ +#endif /* GLX part */ + + if( window->Window.Handle ) { + XDestroyWindow( fgDisplay.pDisplay.Display, window->Window.Handle ); + } + /* XFlush( fgDisplay.pDisplay.Display ); */ /* XXX Shouldn't need this */ +} + + +/* + * This function makes the specified window visible + */ +void fgPlatformShowWindow( SFG_Window *window ) +{ + XMapWindow( fgDisplay.pDisplay.Display, window->Window.Handle ); + XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */ +} + +/* + * This function hides the specified window + */ +void fgPlatformHideWindow( SFG_Window *window ) +{ + if( window->Parent == NULL ) + XWithdrawWindow( fgDisplay.pDisplay.Display, + window->Window.Handle, + fgDisplay.pDisplay.Screen ); + else + XUnmapWindow( fgDisplay.pDisplay.Display, + window->Window.Handle ); + XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */ +} + +/* + * Iconify the specified window (top-level windows only) + */ +void fgPlatformIconifyWindow( SFG_Window *window ) +{ + XIconifyWindow( fgDisplay.pDisplay.Display, window->Window.Handle, + fgDisplay.pDisplay.Screen ); + XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */ + + fgStructure.CurrentWindow->State.Visible = GL_FALSE; +} + +/* + * Set the current window's title + */ +void fgPlatformGlutSetWindowTitle( const char* title ) +{ + XTextProperty text; + + text.value = (unsigned char *) title; + text.encoding = XA_STRING; + text.format = 8; + text.nitems = strlen( title ); + + XSetWMName( + fgDisplay.pDisplay.Display, + fgStructure.CurrentWindow->Window.Handle, + &text + ); + + XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */ +} + +/* + * Set the current window's iconified title + */ +void fgPlatformGlutSetIconTitle( const char* title ) +{ + XTextProperty text; + + text.value = (unsigned char *) title; + text.encoding = XA_STRING; + text.format = 8; + text.nitems = strlen( title ); + + XSetWMIconName( + fgDisplay.pDisplay.Display, + fgStructure.CurrentWindow->Window.Handle, + &text + ); + + XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */ +} + +/* + * Change the specified window's position + */ +void fgPlatformPositionWindow( SFG_Window *window, int x, int y ) +{ + XMoveWindow( fgDisplay.pDisplay.Display, window->Window.Handle, + x, y ); + XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */ +} + +/* + * Lowers the specified window (by Z order change) + */ +void fgPlatformPushWindow( SFG_Window *window ) +{ + XLowerWindow( fgDisplay.pDisplay.Display, window->Window.Handle ); +} + +/* + * Raises the specified window (by Z order change) + */ +void fgPlatformPopWindow( SFG_Window *window ) +{ + XRaiseWindow( fgDisplay.pDisplay.Display, window->Window.Handle ); +} + +/* + * Toggle the window's full screen state. + */ +void fgPlatformFullScreenToggle( SFG_Window *win ) +{ + if(fghToggleFullscreen() != -1) { + win->State.IsFullscreen = !win->State.IsFullscreen; + } +} + diff --git a/src/x11/fg_window_x11_glx.c b/src/x11/fg_window_x11_glx.c new file mode 100644 index 0000000..6229119 --- /dev/null +++ b/src/x11/fg_window_x11_glx.c @@ -0,0 +1,365 @@ +/* + * fg_window_x11_glx.c + * + * Window management methods for X11 with GLX + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Copied for Platform code by Evan Felix + * Creation date: Thur Feb 2 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#define FREEGLUT_BUILDING_LIB +#include +#include "fg_internal.h" + +/* pushing attribute/value pairs into an array */ +#define ATTRIB(a) attributes[where++]=(a) +#define ATTRIB_VAL(a,v) {ATTRIB(a); ATTRIB(v);} + +/* + * Chooses a visual basing on the current display mode settings + */ + +#ifdef USE_FBCONFIG +int fghChooseConfig(GLXFBConfig* fbconfig) +{ + GLboolean wantIndexedMode = GL_FALSE; + int attributes[ 100 ]; + int where = 0, numAuxBuffers; + + /* First we have to process the display mode settings... */ + if( fgState.DisplayMode & GLUT_INDEX ) { + ATTRIB_VAL( GLX_BUFFER_SIZE, 8 ); + /* Buffer size is selected later. */ + + ATTRIB_VAL( GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT ); + wantIndexedMode = GL_TRUE; + } else { + ATTRIB_VAL( GLX_RED_SIZE, 1 ); + ATTRIB_VAL( GLX_GREEN_SIZE, 1 ); + ATTRIB_VAL( GLX_BLUE_SIZE, 1 ); + if( fgState.DisplayMode & GLUT_ALPHA ) { + ATTRIB_VAL( GLX_ALPHA_SIZE, 1 ); + } + } + + if( fgState.DisplayMode & GLUT_DOUBLE ) { + ATTRIB_VAL( GLX_DOUBLEBUFFER, True ); + } + + if( fgState.DisplayMode & GLUT_STEREO ) { + ATTRIB_VAL( GLX_STEREO, True ); + } + + if( fgState.DisplayMode & GLUT_DEPTH ) { + ATTRIB_VAL( GLX_DEPTH_SIZE, 1 ); + } + + if( fgState.DisplayMode & GLUT_STENCIL ) { + ATTRIB_VAL( GLX_STENCIL_SIZE, 1 ); + } + + if( fgState.DisplayMode & GLUT_ACCUM ) { + ATTRIB_VAL( GLX_ACCUM_RED_SIZE, 1 ); + ATTRIB_VAL( GLX_ACCUM_GREEN_SIZE, 1 ); + ATTRIB_VAL( GLX_ACCUM_BLUE_SIZE, 1 ); + if( fgState.DisplayMode & GLUT_ALPHA ) { + ATTRIB_VAL( GLX_ACCUM_ALPHA_SIZE, 1 ); + } + } + + numAuxBuffers = fghNumberOfAuxBuffersRequested(); + if ( numAuxBuffers > 0 ) { + ATTRIB_VAL( GLX_AUX_BUFFERS, numAuxBuffers ); + } + + if( fgState.DisplayMode & GLUT_SRGB ) { + ATTRIB_VAL( GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, True ); + } + + if (fgState.DisplayMode & GLUT_MULTISAMPLE) { + ATTRIB_VAL(GLX_SAMPLE_BUFFERS, 1); + ATTRIB_VAL(GLX_SAMPLES, fgState.SampleNumber); + } + + /* Push a terminator at the end of the list */ + ATTRIB( None ); + + { + GLXFBConfig * fbconfigArray; /* Array of FBConfigs */ + int fbconfigArraySize; /* Number of FBConfigs in the array */ + + + /* Get all FBConfigs that match "attributes". */ + fbconfigArray = glXChooseFBConfig( fgDisplay.pDisplay.Display, + fgDisplay.pDisplay.Screen, + attributes, + &fbconfigArraySize ); + + if (fbconfigArray != NULL) + { + int result __fg_unused; /* Returned by glXGetFBConfigAttrib, not checked. */ + + + if( wantIndexedMode ) + { + /* + * In index mode, we want the largest buffer size, i.e. visual + * depth. Here, FBConfigs are sorted by increasing buffer size + * first, so FBConfigs with the largest size come last. + */ + + int bufferSizeMin, bufferSizeMax; + + /* Get bufferSizeMin. */ + result = + glXGetFBConfigAttrib( fgDisplay.pDisplay.Display, + fbconfigArray[0], + GLX_BUFFER_SIZE, + &bufferSizeMin ); + /* Get bufferSizeMax. */ + result = + glXGetFBConfigAttrib( fgDisplay.pDisplay.Display, + fbconfigArray[fbconfigArraySize - 1], + GLX_BUFFER_SIZE, + &bufferSizeMax ); + + if (bufferSizeMax > bufferSizeMin) + { + /* + * Free and reallocate fbconfigArray, keeping only FBConfigs + * with the largest buffer size. + */ + XFree(fbconfigArray); + + /* Add buffer size token at the end of the list. */ + where--; + ATTRIB_VAL( GLX_BUFFER_SIZE, bufferSizeMax ); + ATTRIB( None ); + + fbconfigArray = glXChooseFBConfig( fgDisplay.pDisplay.Display, + fgDisplay.pDisplay.Screen, + attributes, + &fbconfigArraySize ); + } + } + + *fbconfig = fbconfigArray[0]; + } + else + { + *fbconfig = NULL; + return 0; + } + XFree(fbconfigArray); + } + return 1; +} + +static void fghFillContextAttributes( int *attributes ) { + int where = 0, contextFlags, contextProfile; + + ATTRIB_VAL( GLX_CONTEXT_MAJOR_VERSION_ARB, fgState.MajorVersion ); + ATTRIB_VAL( GLX_CONTEXT_MINOR_VERSION_ARB, fgState.MinorVersion ); + + contextFlags = + fghMapBit( fgState.ContextFlags, GLUT_DEBUG, GLX_CONTEXT_DEBUG_BIT_ARB ) | + fghMapBit( fgState.ContextFlags, GLUT_FORWARD_COMPATIBLE, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB ); + if ( contextFlags != 0 ) { + ATTRIB_VAL( GLX_CONTEXT_FLAGS_ARB, contextFlags ); + } + + contextProfile = + fghMapBit( fgState.ContextProfile, GLUT_CORE_PROFILE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB ) | + fghMapBit( fgState.ContextProfile, GLUT_COMPATIBILITY_PROFILE, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB ); + if ( contextProfile != 0 ) { + ATTRIB_VAL( GLX_CONTEXT_PROFILE_MASK_ARB, contextProfile ); + } + + ATTRIB( 0 ); +} + +typedef GLXContext (*CreateContextAttribsProc)(Display *dpy, GLXFBConfig config, + GLXContext share_list, Bool direct, + const int *attrib_list); + +GLXContext fghCreateNewContext( SFG_Window* window ) +{ + /* for color model calculation */ + int menu = ( window->IsMenu && !fgStructure.MenuContext ); + int index_mode = ( fgState.DisplayMode & GLUT_INDEX ); + + /* "classic" context creation */ + Display *dpy = fgDisplay.pDisplay.Display; + GLXFBConfig config = window->Window.pContext.FBConfig; + int render_type = ( !menu && index_mode ) ? GLX_COLOR_INDEX_TYPE : GLX_RGBA_TYPE; + GLXContext share_list = NULL; + Bool direct = ( fgState.DirectContext != GLUT_FORCE_INDIRECT_CONTEXT ); + GLXContext context; + + /* new context creation */ + int attributes[9]; + CreateContextAttribsProc createContextAttribs = (CreateContextAttribsProc) fgPlatformGetProcAddress( "glXCreateContextAttribsARB" ); + + /* glXCreateContextAttribsARB not found, yet the user has requested the new context creation */ + if ( !createContextAttribs && !fghIsLegacyContextRequested(window) ) { + fgWarning( "OpenGL >2.1 context requested but glXCreateContextAttribsARB is not available! Falling back to legacy context creation" ); + fgState.MajorVersion = 2; + fgState.MinorVersion = 1; + } + + /* If nothing fancy has been required, simply use the old context creation GLX API entry */ + if ( fghIsLegacyContextRequested(window) || !createContextAttribs ) + { + context = glXCreateNewContext( dpy, config, render_type, share_list, direct ); + if ( context == NULL ) { + fghContextCreationError(); + } + return context; + } + + /* color index mode is not available anymore with OpenGL 3.0 */ + if ( render_type == GLX_COLOR_INDEX_TYPE ) { + fgWarning( "color index mode is deprecated, using RGBA mode" ); + } + + fghFillContextAttributes( attributes ); + + context = createContextAttribs( dpy, config, share_list, direct, attributes ); + if ( context == NULL ) { + fghContextCreationError(); + } + return context; +} + +#else /* !defined USE_FBCONFIG */ + +int fghChooseConfig(XVisualInfo **vinf_ret) +{ + Display *dpy = fgDisplay.pDisplay.Display; + int scr = DefaultScreen(dpy); + XVisualInfo *vi; + int attr[32]; + int *aptr = attr; + int *samples = 0; + unsigned int mode = fgState.DisplayMode; + + if(mode & GLUT_DOUBLE) { + *aptr++ = GLX_DOUBLEBUFFER; + } + + if(mode & GLUT_INDEX) { + *aptr++ = GLX_BUFFER_SIZE; + *aptr++ = 1; + } else { + *aptr++ = GLX_RGBA; + *aptr++ = GLX_RED_SIZE; *aptr++ = 1; + *aptr++ = GLX_GREEN_SIZE; *aptr++ = 1; + *aptr++ = GLX_BLUE_SIZE; *aptr++ = 1; + } + if(mode & GLUT_ALPHA) { + *aptr++ = GLX_ALPHA_SIZE; + *aptr++ = 1; + } + if(mode & GLUT_DEPTH) { + *aptr++ = GLX_DEPTH_SIZE; + *aptr++ = 8; + } + if(mode & GLUT_STENCIL) { + *aptr++ = GLX_STENCIL_SIZE; + *aptr++ = 1; + } + if(mode & GLUT_ACCUM) { + *aptr++ = GLX_ACCUM_RED_SIZE; *aptr++ = 1; + *aptr++ = GLX_ACCUM_GREEN_SIZE; *aptr++ = 1; + *aptr++ = GLX_ACCUM_BLUE_SIZE; *aptr++ = 1; + } + if(mode & GLUT_STEREO) { + *aptr++ = GLX_STEREO; + } + if(mode & GLUT_SRGB) { + *aptr++ = GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB; + } + if(mode & GLUT_MULTISAMPLE) { + *aptr++ = GLX_SAMPLE_BUFFERS; + *aptr++ = 1; + *aptr++ = GLX_SAMPLES; + samples = aptr; + *aptr++ = 32; /* start high and attempt halving each time below */ + } + *aptr++ = None; + + if(!samples) { + vi = glXChooseVisual(dpy, scr, attr); + } else { + while(!(vi = glXChooseVisual(dpy, scr, attr)) && *samples) { + *samples >>= 1; + if(!*samples) { + aptr[-3] = None; + } + } + } + if(vi) { + *vinf_ret = vi; + return 1; + } + return 0; +} + +GLXContext fghCreateNewContext(SFG_Window* window) +{ + Display *dpy = fgDisplay.pDisplay.Display; + XVisualInfo *vi = window->Window.pContext.visinf; + GLXContext share_list = 0; + Bool direct = fgState.DirectContext != GLUT_FORCE_INDIRECT_CONTEXT; + GLXContext ctx; + + if(!fghIsLegacyContextRequested(window)) { + fgWarning("Core profile context requested, but freeglut was compiled to " + "use the old GLX context creation mechanism.\n" + "Will create an unversioned old-style context instead."); + } + + if(!(ctx = glXCreateContext(dpy, vi, share_list, direct))) { + fghContextCreationError(); + return 0; + } + return ctx; +} +#endif /* !defined USE_FBCONFIG */ + +void fgPlatformSetWindow ( SFG_Window *window ) +{ + if ( window ) + { +#ifdef GLX_VERSION_1_3 + glXMakeContextCurrent( + fgDisplay.pDisplay.Display, + window->Window.Handle, + window->Window.Handle, + window->Window.Context + ); +#else + glXMakeCurrent(fgDisplay.pDisplay.Display, window->Window.Handle, + window->Window.Context); +#endif + } +} diff --git a/src/x11/fg_window_x11_glx.h b/src/x11/fg_window_x11_glx.h new file mode 100644 index 0000000..1cab38a --- /dev/null +++ b/src/x11/fg_window_x11_glx.h @@ -0,0 +1,41 @@ +/* + * fg_window_x11_glx.c + * + * Window management methods for X11 with GLX + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Copied for Platform code by Evan Felix + * Creation date: Thur Feb 2 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __FG_WINDOW_X11_GLX_H__ +#define __FG_WINDOW_X11_GLX_H__ + +#include "fg_internal_x11_glx.h" + +#ifdef USE_FBCONFIG +int fghChooseConfig(GLXFBConfig *fbconfig); +#else +int fghChooseConfig(XVisualInfo **vinf_ret); +#endif +GLXContext fghCreateNewContext(SFG_Window* window); + +#endif diff --git a/src/x11/fg_xinput_x11.c b/src/x11/fg_xinput_x11.c new file mode 100644 index 0000000..ddddbe6 --- /dev/null +++ b/src/x11/fg_xinput_x11.c @@ -0,0 +1,267 @@ +/* Written for XI1 by Nikolas Doerfler (c) 2008 * + * Rewritten for XI2 by Florian Echtler (c) 2009 */ + +#include + +#include "../fg_internal.h" + +#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H + +#include +#include + +#include +#include + +/* convert the XInput button state mask to the regular X mouse event button mask */ +#define BUTTON_MASK(xistate) ((xistate) << 8) + +/* import function from fg_main.c */ +extern int fgPlatformGetModifiers( int state ); + +/* extension opcode for XInput */ +static int xi_opcode = -1; + +/** + * \brief Sets window up for XI2 events. + */ +void fgRegisterDevices(Display* dpy, Window win) +{ + XIEventMask mask; + unsigned char flags[2] = { 0, 0 }; + int event, error; + + /* get XInput extension opcode */ + if(!XQueryExtension(dpy, "XInputExtension", &xi_opcode, &event, &error)) { + xi_opcode = -1; + } + + /* Select for motion events */ + mask.deviceid = XIAllMasterDevices; + mask.mask_len = 2; + mask.mask = flags; + + XISetMask(mask.mask, XI_Enter); + XISetMask(mask.mask, XI_Motion); + XISetMask(mask.mask, XI_ButtonPress); + XISetMask(mask.mask, XI_ButtonRelease); + XISetMask(mask.mask, XI_Leave); + /*XISetMask(mask.mask, XI_KeyPress); + XISetMask(mask.mask, XI_KeyRelease); + XISetMask(mask.mask, XI_DeviceChanged); + XISetMask(mask.mask, XI_RawEvent); + XISetMask(mask.mask, XI_FocusIn); + XISetMask(mask.mask, XI_FocusOut); + XISetMask(mask.mask, XI_HierarchyChanged);*/ + + XISelectEvents(dpy, win, &mask, 1); +} + + +void fgPrintXILeaveEvent(XILeaveEvent* event) +{ + char* mode = ""; + char* detail = ""; + int i; + + printf(" windows: root 0x%lx event 0x%lx child 0x%ld\n", + event->root, event->event, event->child); + switch(event->mode) + { + case NotifyNormal: mode = "NotifyNormal"; break; + case NotifyGrab: mode = "NotifyGrab"; break; + case NotifyUngrab: mode = "NotifyUngrab"; break; + case NotifyWhileGrabbed: mode = "NotifyWhileGrabbed"; break; + } + switch (event->detail) + { + case NotifyAncestor: detail = "NotifyAncestor"; break; + case NotifyVirtual: detail = "NotifyVirtual"; break; + case NotifyInferior: detail = "NotifyInferior"; break; + case NotifyNonlinear: detail = "NotifyNonlinear"; break; + case NotifyNonlinearVirtual: detail = "NotifyNonlinearVirtual"; break; + case NotifyPointer: detail = "NotifyPointer"; break; + case NotifyPointerRoot: detail = "NotifyPointerRoot"; break; + case NotifyDetailNone: detail = "NotifyDetailNone"; break; + } + printf(" mode: %s (detail %s)\n", mode, detail); + printf(" flags: %s %s\n", event->focus ? "[focus]" : "", + event->same_screen ? "[same screen]" : ""); + printf(" buttons:"); + for (i = 0; i < event->buttons.mask_len * 8; i++) + if (XIMaskIsSet(event->buttons.mask, i)) + printf(" %d", i); + printf("\n"); + + printf(" modifiers: locked 0x%x latched 0x%x base 0x%x\n", + event->mods.locked, event->mods.latched, + event->mods.base); + printf(" group: locked 0x%x latched 0x%x base 0x%x\n", + event->group.locked, event->group.latched, + event->group.base); + + printf(" root x/y: %.2f / %.2f\n", event->root_x, event->root_y); + printf(" event x/y: %.2f / %.2f\n", event->event_x, event->event_y); + +} + + +void fgPrintXIDeviceEvent(XIDeviceEvent* event) +{ + double *val; + int i; + + printf(" device: %d (%d)\n", event->deviceid, event->sourceid); + printf(" detail: %d\n", event->detail); + printf(" buttons:"); + for (i = 0; i < event->buttons.mask_len * 8; i++) + if (XIMaskIsSet(event->buttons.mask, i)) + printf(" %d", i); + printf("\n"); + + printf(" modifiers: locked 0x%x latched 0x%x base 0x%x\n", + event->mods.locked, event->mods.latched, + event->mods.base); + printf(" group: locked 0x%x latched 0x%x base 0x%x\n", + event->group.locked, event->group.latched, + event->group.base); + printf(" valuators:"); + + val = event->valuators.values; + for (i = 0; i < event->valuators.mask_len * 8; i++) + if (XIMaskIsSet(event->valuators.mask, i)) + printf(" %d: %.2f", i, *val++); + printf("\n"); + + printf(" windows: root 0x%lx event 0x%lx child 0x%ld\n", + event->root, event->event, event->child); + printf(" root x/y: %.2f / %.2f\n", event->root_x, event->root_y); + printf(" event x/y: %.2f / %.2f\n", event->event_x, event->event_y); + +} + +/** + * \brief This function is called when an Extension Event is received + * and calls the corresponding callback functions for these events. + */ +void fgHandleExtensionEvents( XEvent* base_ev ) +{ + XEvent std_ev; /* standard single-pointer event to be added to the event queue */ + int i, button = 0; + XGenericEventCookie* cookie = (XGenericEventCookie*)&(base_ev->xcookie); + + /* initialize the generic fields from base_ev */ + std_ev.xany = base_ev->xany; + + if ( XGetEventData( fgDisplay.pDisplay.Display, cookie ) && (cookie->type == GenericEvent) && (cookie->extension == xi_opcode) ) { + + XIDeviceEvent* event = (XIDeviceEvent*)(cookie->data); + XIEnterEvent *evcross; + /*printf("XI2 event type: %d - %d\n", cookie->evtype, event->type );*/ + + SFG_Window* window = fgWindowByHandle( event->event ); + if (!window) return; + + switch (cookie->evtype) { + case XI_Enter: + case XI_Leave: + evcross = (XIEnterEvent*)event; + + fgState.Modifiers = fgPlatformGetModifiers( evcross->mods.base ); + INVOKE_WCB( *window, MultiEntry, ( + event->deviceid, + (event->evtype == XI_Enter ? GLUT_ENTERED : GLUT_LEFT) + )); + #if _DEBUG + fgPrintXILeaveEvent((XILeaveEvent*)event); + #endif + + /* Also process the standard crossing event */ + std_ev.type = evcross->evtype == XI_Enter ? EnterNotify : LeaveNotify; + std_ev.xcrossing.window = evcross->event; + std_ev.xcrossing.root = evcross->root; + std_ev.xcrossing.subwindow = evcross->child; + std_ev.xcrossing.x = evcross->event_x; + std_ev.xcrossing.y = evcross->event_y; + std_ev.xcrossing.x_root = evcross->root_x; + std_ev.xcrossing.y_root = evcross->root_y; + std_ev.xcrossing.mode = evcross->mode; + std_ev.xcrossing.detail = evcross->detail; + std_ev.xcrossing.same_screen = evcross->same_screen; + std_ev.xcrossing.focus = evcross->focus; + std_ev.xcrossing.state = BUTTON_MASK(*(unsigned int*)evcross->buttons.mask); + + XPutBackEvent(fgDisplay.pDisplay.Display, &std_ev); + break; + + case XI_ButtonPress: + case XI_ButtonRelease: + fgState.Modifiers = fgPlatformGetModifiers( event->mods.base ); + INVOKE_WCB( *window, MultiButton, ( + event->deviceid, + event->event_x, + event->event_y, + event->detail-1, + (event->evtype == XI_ButtonPress ? GLUT_DOWN : GLUT_UP) + )); + + /* Also process the standard button event */ + std_ev.type = event->evtype == XI_ButtonPress ? ButtonPress : ButtonRelease; + std_ev.xbutton.window = event->event; + std_ev.xbutton.root = event->root; + std_ev.xbutton.subwindow = event->child; + std_ev.xbutton.x = event->event_x; + std_ev.xbutton.y = event->event_y; + std_ev.xbutton.x_root = event->root_x; + std_ev.xbutton.y_root = event->root_y; + std_ev.xbutton.state = event->mods.base; + std_ev.xbutton.button = event->detail; + + XPutBackEvent(fgDisplay.pDisplay.Display, &std_ev); + break; + + case XI_Motion: + fgState.Modifiers = fgPlatformGetModifiers( event->mods.base ); + for (i = 0; i < event->buttons.mask_len; i++) { + if (event->buttons.mask[i]) { + button = 1; + } + } + if (button) { + INVOKE_WCB( *window, MultiMotion, ( event->deviceid, event->event_x, event->event_y ) ); + } else { + INVOKE_WCB( *window, MultiPassive, ( event->deviceid, event->event_x, event->event_y ) ); + } + #if _DEBUG + fgPrintXIDeviceEvent(event); + #endif + + /* Also process the standard motion event */ + std_ev.type = MotionNotify; + std_ev.xmotion.window = event->event; + std_ev.xmotion.root = event->root; + std_ev.xmotion.subwindow = event->child; + std_ev.xmotion.time = event->time; + std_ev.xmotion.x = event->event_x; + std_ev.xmotion.y = event->event_y; + std_ev.xmotion.x_root = event->root_x; + std_ev.xmotion.y_root = event->root_y; + std_ev.xmotion.state = BUTTON_MASK(*(unsigned int*)event->buttons.mask); + std_ev.xmotion.is_hint = NotifyNormal; + + XPutBackEvent(fgDisplay.pDisplay.Display, &std_ev); + break; + + default: + #if _DEBUG + fgWarning( "Unknown XI2 device event:" ); + fgPrintXIDeviceEvent( event ); + #endif + break; + } + fgState.Modifiers = INVALID_MODIFIERS; + } + XFreeEventData( fgDisplay.pDisplay.Display, cookie ); +} + +#endif