FLTK logo

[master] 04ccc8c - Remove experimental platforms Android, Pico, SDL (PR #376)

FLTK matrix user chat room
(using Element browser app)   FLTK gitter user chat room   GitHub FLTK Project   FLTK News RSS Feed  
  FLTK Apps      FLTK Library      Forums      Links     Login 
 All Forums  |  Back to fltk.commit  ]
 
Previous Message ]Next Message ]

[master] 04ccc8c - Remove experimental platforms Android, Pico, SDL (PR #376) "Albrecht Schlosser" Jan 23, 2022  
 
commit 04ccc8cc46c45b81e6138bec0b48a188c4ffe406
Author:     Albrecht Schlosser <albrechts.fltk@online.de>
AuthorDate: Sun Jan 23 01:33:47 2022 +0100
Commit:     Albrecht Schlosser <albrechts.fltk@online.de>
CommitDate: Sun Jan 23 18:12:47 2022 +0100

    Remove experimental platforms Android, Pico, SDL (PR #376)
    
    ... as discussed in fltk.coredev: "FLTK 1.4.0 release schedule"
    https://groups.google.com/g/fltkcoredev/c/PDbHTRpXVh0/m/JqboexZ_AwAJ

 .gitattributes                                     |    3 -
 CMake/Android/AndroidManifest.xml.in               |   22 -
 CMake/Android/CMakeList.txt.in                     |   60 -
 CMake/Android/HelloAndroid.cxx.in                  |  137 -
 CMake/Android/Roboto-Regular.ttf                   |  Bin 306672 -> 0 bytes
 CMake/Android/app.build.gradle.in                  |   26 -
 CMake/Android/build.gradle.in                      |   17 -
 CMake/Android/fl_config.cmake.in                   |   25 -
 CMake/Android/hdpi.ic_launcher.png                 |  Bin 3059 -> 0 bytes
 CMake/Android/mdpi.ic_launcher.png                 |  Bin 1715 -> 0 bytes
 CMake/Android/settings.gradle.in                   |    1 -
 CMake/Android/strings.xml.in                       |    4 -
 CMake/Android/xhdpi.ic_launcher.png                |  Bin 4082 -> 0 bytes
 CMake/Android/xxhdpi.ic_launcher.png               |  Bin 7266 -> 0 bytes
 CMake/FindSDL2.cmake                               |  169 -
 CMake/android.cmake                                |  141 -
 CMake/fl_create_example.cmake                      |   25 +-
 CMake/options.cmake                                |   15 -
 CMake/setup.cmake                                  |    3 -
 CMake/variables.cmake                              |    2 -
 CMakeLists.txt                                     |   19 +-
 FL/android.H                                       |  159 -
 FL/platform.H                                      |    2 -
 FL/platform_types.h                                |   22 -
 README.Android.md                                  |   80 -
 README.IDE.txt                                     |   10 +-
 README.Pico.txt                                    |   72 -
 README.experimental.txt                            |   29 +
 configh.cmake.in                                   |    9 -
 configh.in                                         |   10 -
 examples/CMakeLists.txt                            |    2 +-
 fluid/CMakeLists.txt                               |    8 +-
 src/CMakeLists.txt                                 |   69 +-
 src/Fl_Device.cxx                                  |    2 +-
 src/Fl_System_Driver.cxx                           |    2 +-
 src/drivers/Android/Fl_Android_Application.H       |  270 --
 src/drivers/Android/Fl_Android_Application.cxx     |  843 ----
 src/drivers/Android/Fl_Android_Graphics_Clipping.H |  183 -
 .../Android/Fl_Android_Graphics_Clipping.cxx       |  808 ----
 src/drivers/Android/Fl_Android_Graphics_Driver.H   |  352 --
 src/drivers/Android/Fl_Android_Graphics_Driver.cxx | 1257 -----
 src/drivers/Android/Fl_Android_Graphics_Font.H     |  132 -
 src/drivers/Android/Fl_Android_Graphics_Font.cxx   |  797 ----
 .../Android/Fl_Android_Image_Surface_Driver.cxx    |  115 -
 src/drivers/Android/Fl_Android_Screen_Driver.H     |  176 -
 src/drivers/Android/Fl_Android_Screen_Driver.cxx   |  568 ---
 src/drivers/Android/Fl_Android_Screen_Keyboard.cxx |  452 --
 src/drivers/Android/Fl_Android_System_Driver.H     |  132 -
 src/drivers/Android/Fl_Android_System_Driver.cxx   |  957 ----
 src/drivers/Android/Fl_Android_Window_Driver.H     |  143 -
 src/drivers/Android/Fl_Android_Window_Driver.cxx   |  826 ----
 src/drivers/Android/README.txt                     |   12 -
 src/drivers/Android/stb_truetype.h                 | 4853 --------------------
 src/drivers/Pico/Fl_Pico_Copy_Surface.cxx          |    1 -
 src/drivers/Pico/Fl_Pico_Graphics_Driver.H         |  211 -
 src/drivers/Pico/Fl_Pico_Graphics_Driver.cxx       |  506 --
 src/drivers/Pico/Fl_Pico_Image_Surface.cxx         |    1 -
 src/drivers/Pico/Fl_Pico_Screen_Driver.H           |   58 -
 src/drivers/Pico/Fl_Pico_Screen_Driver.cxx         |  132 -
 src/drivers/Pico/Fl_Pico_System_Driver.H           |   32 -
 src/drivers/Pico/Fl_Pico_System_Driver.cxx         |   19 -
 src/drivers/Pico/Fl_Pico_Window_Driver.H           |   41 -
 src/drivers/Pico/Fl_Pico_Window_Driver.cxx         |   46 -
 .../PicoAndroid/Fl_PicoAndroid_Copy_Surface.cxx    |    1 -
 .../PicoAndroid/Fl_PicoAndroid_Graphics_Driver.H   |  119 -
 .../PicoAndroid/Fl_PicoAndroid_Graphics_Driver.cxx |   97 -
 .../PicoAndroid/Fl_PicoAndroid_Image_Surface.cxx   |    1 -
 .../PicoAndroid/Fl_PicoAndroid_Screen_Driver.H     |   73 -
 .../PicoAndroid/Fl_PicoAndroid_Screen_Driver.cxx   |  562 ---
 .../PicoAndroid/Fl_PicoAndroid_System_Driver.H     |    1 -
 .../PicoAndroid/Fl_PicoAndroid_System_Driver.cxx   |    1 -
 .../PicoAndroid/Fl_PicoAndroid_Window_Driver.H     |   55 -
 .../PicoAndroid/Fl_PicoAndroid_Window_Driver.cxx   |  122 -
 src/drivers/PicoSDL/Fl_PicoSDL_Copy_Surface.cxx    |    1 -
 src/drivers/PicoSDL/Fl_PicoSDL_Graphics_Driver.H   |  118 -
 src/drivers/PicoSDL/Fl_PicoSDL_Graphics_Driver.cxx |   68 -
 src/drivers/PicoSDL/Fl_PicoSDL_Image_Surface.cxx   |    1 -
 src/drivers/PicoSDL/Fl_PicoSDL_Screen_Driver.H     |   38 -
 src/drivers/PicoSDL/Fl_PicoSDL_Screen_Driver.cxx   |  135 -
 src/drivers/PicoSDL/Fl_PicoSDL_System_Driver.H     |    1 -
 src/drivers/PicoSDL/Fl_PicoSDL_System_Driver.cxx   |   30 -
 src/drivers/PicoSDL/Fl_PicoSDL_Window_Driver.H     |   51 -
 src/drivers/PicoSDL/Fl_PicoSDL_Window_Driver.cxx   |  104 -
 test/CMakeLists.txt                                |   40 +-
 84 files changed, 74 insertions(+), 16613 deletions(-)

diff --git .gitattributes .gitattributes
index bdc4e59..f6fe0d6 100644
--- .gitattributes
+++ .gitattributes
@@ -41,9 +41,6 @@ misc/update_config_scripts      eol=lf
 *.rc            eol=crlf
 *.bat           eol=crlf
 
-# Android Studio special support file (Windows .bat file)
-ide/AndroidStudio3/gradlew.rename_to_bat eol=crlf
-
 # binary files
 
 *.ico           binary
diff --git CMake/Android/AndroidManifest.xml.in CMake/Android/AndroidManifest.xml.in
deleted file mode 100644
index 4e5c615..0000000
--- CMake/Android/AndroidManifest.xml.in
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android";
-          package="org.fltk.@ANDROID_APP_NAME@"
-          android:versionCode="1"
-          android:versionName="1.0">
-  <application
-      android:allowBackup="false"
-      android:fullBackupContent="false"
-      android:icon="@mipmap/ic_launcher"
-      android:label="@string/app_name"
-      android:hasCode="false">
-    <activity android:name="android.app.NativeActivity"
-              android:label="@string/app_name">
-      <meta-data android:name="android.app.lib_name"
-                 android:value="test_@ANDROID_APP_NAME@" />
-      <intent-filter>
-        <action android:name="android.intent.action.MAIN" />
-        <category android:name="android.intent.category.LAUNCHER" />
-      </intent-filter>
-    </activity>
-  </application>
-</manifest>
diff --git CMake/Android/CMakeList.txt.in CMake/Android/CMakeList.txt.in
deleted file mode 100644
index 7c7aeb1..0000000
--- CMake/Android/CMakeList.txt.in
+++ /dev/null
@@ -1,60 +0,0 @@
-#
-# Copyright (C)  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.
-#
-# Modified to be a template for Android builds in FLTK
-# Copyright 2019  Matthias Melcher and others
-#
-
-cmake_minimum_required(VERSION 3.4.1)
-
-set(FLTK_DIR "@ANDROID_FLTK_DIR@")
-set(FLTK_IDE_DIR "../../../..")
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
-
-
-# FIXME: this includes the entire CMakeLists again, creating an entire library
-#        build in every target
-# TODO:  create separate targets for all fltk libraries that can be easily
-#        linked by all app targets
-add_subdirectory("${FLTK_DIR}/" "${CMAKE_CURRENT_BINARY_DIR}/lib" EXCLUDE_FROM_ALL)
-
-# run Fluid build steps for every .fl file, if any
-@ANDROID_FLUID_COMMANDS@
-# now build app's shared lib
-add_library(
-    test_@ANDROID_APP_NAME@ SHARED
-@ANDROID_APP_SOURCES@)
-
-target_include_directories(
-    test_@ANDROID_APP_NAME@ PRIVATE
-    ${FLTK_DIR}/
-    ${FLTK_IDE_DIR}/ )
-
-# Export ANativeActivity_onCreate()
-# Refer to: https://github.com/android-ndk/ndk/issues/381.
-set(CMAKE_SHARED_LINKER_FLAGS
-    "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")
-
-# add lib dependencies
-# FIXME: apps may depend on additional fltk libraries; thise dependencies
-#        must be created in the CREATE_ANDROID_IDE_FOR_TEST macro
-target_link_libraries(
-    test_@ANDROID_APP_NAME@
-    fltk
-    android
-    log
-    m
-)
-
diff --git CMake/Android/HelloAndroid.cxx.in CMake/Android/HelloAndroid.cxx.in
deleted file mode 100644
index edba702..0000000
--- CMake/Android/HelloAndroid.cxx.in
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * 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 "../../../test/@ANDROID_APP_NAME@.cxx"
-
-
-/*
-
- Missing:
-  - screen scale and size: most desktop apps expect to be in a draggable window
-    on a larger desktop surface. For Android, there is usually no desktop, and
-    screen resolution is often very high, so that a regular FLTK window would
-    hide as a tiny gray spot in the top left corner
-      * windows should probably be centered by default
-      ? the screen resolution should adapt to the first opened window
-      ? we should be able to hint at a prefered screen resolution
-      * drawing call must scale at some point (line width!)
-      * rotating the screen must call the app handler and(?) window resize
-      * proportions: pixels should be square
- Need Work:
-  - Fl_Android_Graphics_Driver::pie(int) needs refactoring
-  - ...::line(...) has round ing issues (see rounded box type)
-  - grab() not working when leaving window (adjuster...)
-  - scrolling if implemented as a complete redraw. Must implement real scrolling
-  - the 'hotspot' idea to position dialogs under the mouse cursor makes little sense on touch screen devices
-  - fix screen when keyboard pops up in front of the text cursor or input field (temporarily shift up?)
-  - ending 'message' will not quit the app right away, but wait for some timeout
-  - no support for dead-key entry
-  - no Shift-Tab
-
-  * test/CubeMain.cxx     : UNSUPPORTED - needs OpenGL
-  * test/CubeView.cxx     : UNSUPPORTED - needs OpenGL
-  * test/shape.cxx        : UNSUPPORTED - needs OpenGL
-  * test/cube.cxx         : UNSUPPORTED - needs OpenGL
-  * test/fractals.cxx     : UNSUPPORTED - needs OpenGL
-  * test/fracviewer.cxx   : UNSUPPORTED - needs OpenGL
-  * test/fullscreen.cxx   : UNSUPPORTED - needs OpenGL
-  * test/gl_overlay.cxx   : UNSUPPORTED - needs OpenGL
-  * test/glpuzzle.cxx     : UNSUPPORTED - needs OpenGL
-  * test/mandelbrot.cxx   : UNSUPPORTED - needs Fluid
-  * test/keyboard.cxx     : UNSUPPORTED - needs Fluid
-  * test/CubeViewUI.fl
-  * test/keyboard_ui.fl
-  * test/radio.fl
-  * test/tree.fl
-  * test/fast_slow.fl
-  * test/mandelbrot_ui.fl
-  * test/resize.fl
-  * test/valuators.fl
-  * test/inactive.fl
-  * test/preferences.fl
-  * test/tabs.fl
-  * test/cairo_test.cxx   : UNSUPPORTED - needs Cairo
-  * test/tiled_image.cxx  : UNSUPPORTED - X11 only
-  * test/forms.cxx        : UNSUPPORTED - needs Forms
-
-  * test/doublebuffer.cxx : FIXME - redering is completely wrong
-  * test/line_style.cxx   : TODO - no line styles yet
-  * test/list_visuals.cxx : TODO - needs config.h
-  * test/threads.cxx      : TODO - needs config.h for pthreads
-  * test/animated.cxx     : TODO - redering errors (alpha channel?)
-  * test/native-filechooser.cxx : TODO - not yet implemented
-  * test/blocks.cxx       : TODO - needs config.h
-  * test/offscreen.cxx    : TODO - not yet implemented
-  * test/overlay.cxx      : TODO - no overlay yet
-  * test/pixmap_browser.cxx : TODO - filebrowser not yet implemented, no images, no printer
-  * test/clock.cxx        : TODO - no system clock call yet
-  * test/resizebox.cxx    : TODO - no window manager yet
-  * test/rotated_text.cxx : TODO - no rotated text
-  * test/subwindow.cxx    : TODO - no subwindows yet
-  * test/sudoku.cxx       : TODO - sound support is in our way
-  * test/demo.cxx         : TODO - fails to open window, but is is useful at all?
-  * test/device.cxx       : TODO - printing support
-  * test/tile.cxx         : TODO - subwindow support
-  * test/editor.cxx       : TODO - file chooser missing
-  * test/file_chooser.cxx : TODO - file chooser missing
-  * test/fonts.cxx        : TODO - works, but does not list system fonts or resource fonts
-  * test/help_dialog.cxx  : TODO - not implemented
-  * test/icon.cxx         : TODO - what does this do on Android?
-  * test/iconize.cxx      : TODO - no window manager
-  * test/utf8.cxx         : TODO - window manager, clipping
-  * test/windowfocus.cxx  : TODO - what does this do?
-  * test/browser.cxx      : TODO - needs text resource to load browser content
-  * test/unittests.cxx    : TODO - crashing, no alpha in image drawing, clipping issues
-
-  * test/image.cxx        : + works
-  * test/twowin.cxx       : + works
-  * test/table.cxx        : + works, but window is much too large for mobile device
-  * test/cursor.cxx       : + works, but no cursor on Android
-  * test/colbrowser.cxx   : + works
-  * test/checkers.cxx     : + works
-  * test/pixmap.cxx       : + works
-  * test/navigation.cxx   : + works
-  * test/curve.cxx        : + works
-  * test/input_choice.cxx : + works
-  * test/input.cxx        : + works
-  * test/scroll.cxx       : - works ok
-                            - some dirt when a popup draws over another menu button!?
-                            - on touch-screens, menuitem should be selected when released
-                            - on touch-screens, scroll groups should scroll on multitouch, or when not causing any other action
-  * test/bitmap.cxx       : + 'bitmap' works
-  * test/message.cxx      : - 'message' mostly works
-                            - when ending the app, it will not close right away but instead hang around for a few seconds
-  * test/menubar.cxx      : - 'menubar' mostly works including unicode
-                            ! pressing 'button' will hang the app
-                            - shortcut modifiers don't work
-                            - right-click does not work (should this be emulated via click-and-hold?)
-  * test/output.cxx       : + 'output' works
-  * test/ask.cxx          : + 'ask' works
-  * test/button.cxx       : + 'button' works, including beep
-  * test/pack.cxx         : + 'pack' works
-  * test/adjuster.cxx     : + 'adjuster' works
-  * test/arc.cxx          : + 'arc' works as expected
-  * test/minimum.cxx      : + 'minimum' works
-  * test/boxtype.cxx      : + 'boxtype' works
-  * test/buttons.cxx      : + 'buttons' works
-  * test/color_chooser.cxx: + 'color_chooser' works
-  * test/symbols.cxx      : + 'symbols' working as expected
-  * test/hello.cxx        : + 'hello' works fine, italics, shadow, etc.
-  * test/label.cxx        : + 'label' works
-
- */
diff --git CMake/Android/Roboto-Regular.ttf CMake/Android/Roboto-Regular.ttf
deleted file mode 100644
index 88dae90..0000000
Binary files CMake/Android/Roboto-Regular.ttf and /dev/null differ
diff --git CMake/Android/app.build.gradle.in CMake/Android/app.build.gradle.in
deleted file mode 100644
index 9e579a4..0000000
--- CMake/Android/app.build.gradle.in
+++ /dev/null
@@ -1,26 +0,0 @@
-apply plugin: 'com.android.application'
-
- android {
-     compileSdkVersion 25
-
-     defaultConfig {
-         applicationId 'org.fltk.@ANDROID_APP_NAME@'
-         minSdkVersion 14
-         targetSdkVersion 25
-         externalNativeBuild {
-             cmake {
-                 arguments '-DANDROID_STL=c++_shared'
-             }
-         }
-     }
-     buildTypes {
-         release {
-             minifyEnabled false
-         }
-     }
-     externalNativeBuild {
-         cmake {
-             path 'src/main/cpp/CMakeLists.txt'
-         }
-     }
- }
diff --git CMake/Android/build.gradle.in CMake/Android/build.gradle.in
deleted file mode 100644
index f48a2c6..0000000
--- CMake/Android/build.gradle.in
+++ /dev/null
@@ -1,17 +0,0 @@
-// Top-level build file where you can add configuration options common to all sub-projects/modules.
-buildscript {
-    repositories {
-       jcenter()
-       google()
-    }
-    dependencies {
-        classpath 'com.android.tools.build:gradle:3.2.1'
-    }
-}
-
-allprojects {
-    repositories {
-        jcenter()
-        google()
-    }
-}
diff --git CMake/Android/fl_config.cmake.in CMake/Android/fl_config.cmake.in
deleted file mode 100644
index 5200197..0000000
--- CMake/Android/fl_config.cmake.in
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Configuration file for the Fast Light Tool Kit (FLTK).
- *
- * Copyright 1998-2020 by Bill Spitzak and others.
- *
- * This library is free software. Distribution and use rights are outlined in
- * the file "COPYING" which should have been included with this file.  If this
- * file is missing or damaged, see the license at:
- *
- *     https://www.fltk.org/COPYING.php
- *
- * Please see the following page on how to report bugs and issues:
- *
- *     https://www.fltk.org/bugs.php
- */
-
-/*
-  ============================================================================
-    DO NOT EDIT - This file is generated by CMake !
-  ============================================================================
-*/
-
-/* define FL_ABI_VERSION as 10x0y for FLTK ABI version 1.x.y */
-
-/* #undef FL_ABI_VERSION */
diff --git CMake/Android/hdpi.ic_launcher.png CMake/Android/hdpi.ic_launcher.png
deleted file mode 100755
index 1c28eb2..0000000
Binary files CMake/Android/hdpi.ic_launcher.png and /dev/null differ
diff --git CMake/Android/mdpi.ic_launcher.png CMake/Android/mdpi.ic_launcher.png
deleted file mode 100755
index 4f12dba..0000000
Binary files CMake/Android/mdpi.ic_launcher.png and /dev/null differ
diff --git CMake/Android/settings.gradle.in CMake/Android/settings.gradle.in
deleted file mode 100644
index 8b13789..0000000
--- CMake/Android/settings.gradle.in
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git CMake/Android/strings.xml.in CMake/Android/strings.xml.in
deleted file mode 100644
index 3513152..0000000
--- CMake/Android/strings.xml.in
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string name="app_name">@ANDROID_APP_NAME@</string>
-</resources>
diff --git CMake/Android/xhdpi.ic_launcher.png CMake/Android/xhdpi.ic_launcher.png
deleted file mode 100755
index aa48b85..0000000
Binary files CMake/Android/xhdpi.ic_launcher.png and /dev/null differ
diff --git CMake/Android/xxhdpi.ic_launcher.png CMake/Android/xxhdpi.ic_launcher.png
deleted file mode 100755
index 91aad38..0000000
Binary files CMake/Android/xxhdpi.ic_launcher.png and /dev/null differ
diff --git CMake/FindSDL2.cmake CMake/FindSDL2.cmake
deleted file mode 100644
index 28cb8c6..0000000
--- CMake/FindSDL2.cmake
+++ /dev/null
@@ -1,169 +0,0 @@
-
-# This module defines
-# SDL2_LIBRARY, the name of the library to link against
-# SDL2_FOUND, if false, do not try to link to SDL2
-# SDL2_INCLUDE_DIR, where to find SDL.h
-#
-# This module responds to the the flag:
-# SDL2_BUILDING_LIBRARY
-# If this is defined, then no SDL2main will be linked in because
-# only applications need main().
-# Otherwise, it is assumed you are building an application and this
-# module will attempt to locate and set the the proper link flags
-# as part of the returned SDL2_LIBRARY variable.
-#
-# Don't forget to include SDLmain.h and SDLmain.m your project for the
-# OS X framework based version. (Other versions link to -lSDL2main which
-# this module will try to find on your behalf.) Also for OS X, this
-# module will automatically add the -framework Cocoa on your behalf.
-#
-#
-# Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your configuration
-# and no SDL2_LIBRARY, it means CMake did not find your SDL2 library
-# (SDL2.dll, libsdl2.so, SDL2.framework, etc).
-# Set SDL2_LIBRARY_TEMP to point to your SDL2 library, and configure again.
-# Similarly, if you see an empty SDL2MAIN_LIBRARY, you should set this value
-# as appropriate. These values are used to generate the final SDL2_LIBRARY
-# variable, but when these values are unset, SDL2_LIBRARY does not get created.
-#
-#
-# $SDL2DIR is an environment variable that would
-# correspond to the ./configure --prefix=$SDL2DIR
-# used in building SDL2.
-# l.e.galup  9-20-02
-#
-# Modified by Eric Wing.
-# Added code to assist with automated building by using environmental variables
-# and providing a more controlled/consistent search behavior.
-# Added new modifications to recognize OS X frameworks and
-# additional Unix paths (FreeBSD, etc).
-# Also corrected the header search path to follow "proper" SDL guidelines.
-# Added a search for SDL2main which is needed by some platforms.
-# Added a search for threads which is needed by some platforms.
-# Added needed compile switches for MinGW.
-#
-# On OSX, this will prefer the Framework version (if found) over others.
-# People will have to manually change the cache values of
-# SDL2_LIBRARY to override this selection or set the CMake environment
-# CMAKE_INCLUDE_PATH to modify the search paths.
-#
-# Note that the header path has changed from SDL2/SDL.h to just SDL.h
-# This needed to change because "proper" SDL convention
-# is #include "SDL.h", not <SDL2/SDL.h>. This is done for portability
-# reasons because not all systems place things in SDL2/ (see FreeBSD).
-
-#=============================================================================
-# Copyright 2003-2009 Kitware, Inc.
-#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
-#=============================================================================
-# (To distribute this file outside of CMake, substitute the full
-#  License text for the above reference.)
-
-message("<FindSDL2.cmake>")
-
-SET(SDL2_SEARCH_PATHS
-        ~/Library/Frameworks
-        /Library/Frameworks
-        /usr/local
-        /usr
-        /sw # Fink
-        /opt/local # DarwinPorts
-        /opt/csw # Blastwave
-        /opt
-        ${SDL2_PATH}
-)
-
-FIND_PATH(SDL2_INCLUDE_DIR SDL.h
-        HINTS
-        $ENV{SDL2DIR}
-        PATH_SUFFIXES include/SDL2 include
-        PATHS ${SDL2_SEARCH_PATHS}
-)
-
-FIND_LIBRARY(SDL2_LIBRARY_TEMP
-        NAMES SDL2
-        HINTS
-        $ENV{SDL2DIR}
-        PATH_SUFFIXES lib64 lib
-        PATHS ${SDL2_SEARCH_PATHS}
-)
-
-IF(NOT SDL2_BUILDING_LIBRARY)
-        IF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
-                # Non-OS X framework versions expect you to also dynamically link to
-                # SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms
-                # seem to provide SDL2main for compatibility even though they don't
-                # necessarily need it.
-                FIND_LIBRARY(SDL2MAIN_LIBRARY
-                        NAMES SDL2main
-                        HINTS
-                        $ENV{SDL2DIR}
-                        PATH_SUFFIXES lib64 lib
-                        PATHS ${SDL2_SEARCH_PATHS}
-                )
-        ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
-ENDIF(NOT SDL2_BUILDING_LIBRARY)
-
-# SDL2 may require threads on your system.
-# The Apple build may not need an explicit flag because one of the
-# frameworks may already provide it.
-# But for non-OSX systems, I will use the CMake Threads package.
-IF(NOT APPLE)
-        FIND_PACKAGE(Threads)
-ENDIF(NOT APPLE)
-
-# MinGW needs an additional library, mwindows
-# It's total link flags should look like -lmingw32 -lSDL2main -lSDL2 -lmwindows
-# (Actually on second look, I think it only needs one of the m* libraries.)
-IF(MINGW)
-        SET(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW")
-ENDIF(MINGW)
-
-IF(SDL2_LIBRARY_TEMP)
-        # For SDL2main
-        IF(NOT SDL2_BUILDING_LIBRARY)
-                IF(SDL2MAIN_LIBRARY)
-                        SET(SDL2_LIBRARY_TEMP ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARY_TEMP})
-                ENDIF(SDL2MAIN_LIBRARY)
-        ENDIF(NOT SDL2_BUILDING_LIBRARY)
-
-        # For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa.
-        # CMake doesn't display the -framework Cocoa string in the UI even
-        # though it actually is there if I modify a pre-used variable.
-        # I think it has something to do with the CACHE STRING.
-        # So I use a temporary variable until the end so I can set the
-        # "real" variable in one-shot.
-        IF(APPLE)
-                SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} "-framework Cocoa")
-        ENDIF(APPLE)
-
-        # For threads, as mentioned Apple doesn't need this.
-        # In fact, there seems to be a problem if I used the Threads package
-        # and try using this line, so I'm just skipping it entirely for OS X.
-        IF(NOT APPLE)
-                SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT})
-        ENDIF(NOT APPLE)
-
-        # For MinGW library
-        IF(MINGW)
-                SET(SDL2_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_LIBRARY_TEMP})
-        ENDIF(MINGW)
-
-        # Set the final string here so the GUI reflects the final state.
-        SET(SDL2_LIBRARY ${SDL2_LIBRARY_TEMP} CACHE STRING "Where the SDL2 Library can be found")
-        # Set the temp variable to INTERNAL so it is not seen in the CMake GUI
-        SET(SDL2_LIBRARY_TEMP "${SDL2_LIBRARY_TEMP}" CACHE INTERNAL "")
-ENDIF(SDL2_LIBRARY_TEMP)
-
-message("</FindSDL2.cmake>")
-
-INCLUDE(FindPackageHandleStandardArgs)
-
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR)
-
diff --git CMake/android.cmake CMake/android.cmake
deleted file mode 100644
index 9fc78d8..0000000
--- CMake/android.cmake
+++ /dev/null
@@ -1,141 +0,0 @@
-#
-# android.cmake to build the FLTK AndroidStudio project using CMake
-# Written by Matthias Melcher
-#
-# Copyright 1998-2019 by Bill Spitzak and others.
-#
-# This library is free software. Distribution and use rights are outlined in
-# the file "COPYING" which should have been included with this file.  If this
-# file is missing or damaged, see the license at:
-#
-#     https://www.fltk.org/COPYING.php
-#
-# Please see the following page on how to report bugs and issues:
-#
-#     https://www.fltk.org/bugs.php
-#
-
-# all target modules will be added here later
-configure_file(
-  "${CMAKE_CURRENT_SOURCE_DIR}/CMake/Android/settings.gradle.in"
-  "${CMAKE_CURRENT_BINARY_DIR}/AndroidStudio/settings.gradle"
-  @ONLY
-)
-
-# configuration file for all modules
-configure_file(
-  "${CMAKE_CURRENT_SOURCE_DIR}/CMake/Android/build.gradle.in"
-  "${CMAKE_CURRENT_BINARY_DIR}/AndroidStudio/build.gradle"
-  @ONLY
-)
-
-# create a custom abi file for this setup
-configure_file(
-  "${CMAKE_CURRENT_SOURCE_DIR}/fl_config.cmake.in"
-  "${CMAKE_CURRENT_BINARY_DIR}/AndroidStudio/FL/fl_config.h"
-  @ONLY
-)
-
-# TODO: where should we create config.h?
-
-macro(CREATE_ANDROID_IDE_FOR_TEST NAME SOURCES LIBRARIES)
-
-  # message(STATUS "Creating Android IDE for ${NAME}")
-
-  set (ANDROID_APP_NAME ${NAME})
-  set (ANDROID_FLTK_DIR ${CMAKE_SOURCE_DIR})
-
-  set (srcs)
-  set (ANDROID_APP_SOURCES)
-  set (ANDROID_FLUID_COMMANDS)
-  set (flsrcs)        # fluid source files
-  foreach(src ${SOURCES})
-    if ("${src}" MATCHES "\\.fl$")
-      list(APPEND flsrcs ${src})
-      string(REGEX REPLACE "(.*).fl" \\1 basename ${src})
-      string(APPEND ANDROID_FLUID_COMMANDS
-        "add_custom_command(\n"
-        "  OUTPUT \"\${FLTK_DIR}/test/${basename}.cxx\" \"\${FLTK_DIR}/test/${basename}.h\"\n"
-        "  COMMAND fluid -c \"${src}\"\n"
-        "  WORKING_DIRECTORY \"\${FLTK_DIR}/test\"\n"
-        "  DEPENDS \"\${FLTK_DIR}/test/${src}\"\n"
-        "  MAIN_DEPENDENCY \"\${FLTK_DIR}/test/${src}\"\n"
-        ")\n\n"
-      )
-      file(TOUCH "${basename}.cxx")
-      file(TOUCH "${basename}.h")
-      file(TOUCH "${basename}.fl")
-      set(src_cxx ${basename}.cxx)
-    else ()
-      list(APPEND srcs ${src})
-      set(src_cxx ${src})
-    endif ("${src}" MATCHES "\\.fl$")
-    string(APPEND ANDROID_APP_SOURCES "    \"\${FLTK_DIR}/test/${src_cxx}\"\n")
-  endforeach(src)
-
-  configure_file(
-    "${CMAKE_SOURCE_DIR}/CMake/Android/app.build.gradle.in"
-    "${CMAKE_BINARY_DIR}/AndroidStudio/${ANDROID_APP_NAME}/build.gradle"
-    @ONLY
-  )
-
-  configure_file(
-    "${CMAKE_SOURCE_DIR}/CMake/Android/AndroidManifest.xml.in"
-    "${CMAKE_BINARY_DIR}/AndroidStudio/${ANDROID_APP_NAME}/src/main/AndroidManifest.xml"
-    @ONLY
-  )
-
-  configure_file(
-    "${CMAKE_SOURCE_DIR}/CMake/Android/Roboto-Regular.ttf"
-    "${CMAKE_BINARY_DIR}/AndroidStudio/${ANDROID_APP_NAME}/src/main/assets/fonts/Roboto-Regular.ttf"
-    COPYONLY
-  )
-
-  configure_file(
-    "${CMAKE_SOURCE_DIR}/CMake/Android/mdpi.ic_launcher.png"
-    "${CMAKE_BINARY_DIR}/AndroidStudio/${ANDROID_APP_NAME}/src/main/res/mipmap-mdpi/ic_launcher.png"
-    COPYONLY
-  )
-
-  configure_file(
-    "${CMAKE_SOURCE_DIR}/CMake/Android/hdpi.ic_launcher.png"
-    "${CMAKE_BINARY_DIR}/AndroidStudio/${ANDROID_APP_NAME}/src/main/res/mipmap-hdpi/ic_launcher.png"
-    COPYONLY
-  )
-
-  configure_file(
-    "${CMAKE_SOURCE_DIR}/CMake/Android/xhdpi.ic_launcher.png"
-    "${CMAKE_BINARY_DIR}/AndroidStudio/${ANDROID_APP_NAME}/src/main/res/mipmap-xhdpi/ic_launcher.png"
-    COPYONLY
-  )
-
-  configure_file(
-    "${CMAKE_SOURCE_DIR}/CMake/Android/xxhdpi.ic_launcher.png"
-    "${CMAKE_BINARY_DIR}/AndroidStudio/${ANDROID_APP_NAME}/src/main/res/mipmap-xxhdpi/ic_launcher.png"
-    COPYONLY
-  )
-
-  configure_file(
-    "${CMAKE_SOURCE_DIR}/CMake/Android/strings.xml.in"
-    "${CMAKE_BINARY_DIR}/AndroidStudio/${ANDROID_APP_NAME}/src/main/res/values/strings.xml"
-    @ONLY
-  )
-
-  configure_file(
-    "${CMAKE_SOURCE_DIR}/CMake/Android/CMakeList.txt.in"
-    "${CMAKE_BINARY_DIR}/AndroidStudio/${ANDROID_APP_NAME}/src/main/cpp/CMakeLists.txt"
-    @ONLY
-  )
-
-  file(APPEND "${CMAKE_BINARY_DIR}/AndroidStudio/settings.gradle" "include ':${ANDROID_APP_NAME}'\n")
-
-endmacro(CREATE_ANDROID_IDE_FOR_TEST NAME SOURCES LIBRARIES)
-
-
-macro(CREATE_ANDROID_IDE_WRAPUP)
-
-  # message(STATUS "Wrapping up Android IDE creation")
-
-endmacro(CREATE_ANDROID_IDE_WRAPUP)
-
-
diff --git CMake/fl_create_example.cmake CMake/fl_create_example.cmake
index c2db54e..09c99ec 100644
--- CMake/fl_create_example.cmake
+++ CMake/fl_create_example.cmake
@@ -46,8 +46,7 @@
 #   quotes if more than one library is required, e.g. "fltk_gl;fltk"
 #
 # CREATE_EXAMPLE can have an optional fourth argument with a list of options
-# - the option ANDROID_OK is set if CREATE_EXAMPLE creates code for Android
-#   builds in addition to the native build
+# - these options are currently not used
 #
 ################################################################################
 
@@ -62,11 +61,11 @@ macro (CREATE_EXAMPLE NAME SOURCES LIBRARIES)
 
   # create macOS bundle? 0 = no, 1 = yes
 
-  if (APPLE AND (NOT OPTION_APPLE_X11) AND (NOT OPTION_APPLE_SDL))
+  if (APPLE AND (NOT OPTION_APPLE_X11))
     set (MAC_BUNDLE 1)
   else ()
     set (MAC_BUNDLE 0)
-  endif (APPLE AND (NOT OPTION_APPLE_X11) AND (NOT OPTION_APPLE_SDL))
+  endif (APPLE AND (NOT OPTION_APPLE_X11))
 
   # rename target name "help" (reserved since CMake 2.8.12)
   # FIXME: not necessary in FLTK 1.4 but left for compatibility (06/2020)
@@ -164,15 +163,17 @@ macro (CREATE_EXAMPLE NAME SOURCES LIBRARIES)
   endif (MAC_BUNDLE)
 
   ######################################################################
-  # Parse optional fourth argument "ANDROID_OK", see description above.
+  # Parse optional fourth argument, see description above.
   ######################################################################
 
-  if (${ARGC} GREATER 3)
-    foreach (OPTION ${ARGV3})
-      if (${OPTION} STREQUAL "ANDROID_OK" AND OPTION_CREATE_ANDROID_STUDIO_IDE)
-        CREATE_ANDROID_IDE_FOR_TEST (${NAME} ${SOURCES} ${LIBRARIES})
-      endif ()
-    endforeach ()
-  endif ()
+  # code left commented out as an example
+
+  # *unused* #  if (${ARGC} GREATER 3)
+  # *unused* #    foreach (OPTION ${ARGV3})
+  # *unused* #      if (${OPTION} STREQUAL "xxx")
+  # *unused* #        # do something ...
+  # *unused* #      endif ()
+  # *unused* #    endforeach ()
+  # *unused* #  endif ()
 
 endmacro (CREATE_EXAMPLE NAME SOURCES LIBRARIES)
diff --git CMake/options.cmake CMake/options.cmake
index f1e347f..eb8f1fe 100644
--- CMake/options.cmake
+++ CMake/options.cmake
@@ -65,7 +65,6 @@ endif (WIN32)
 #######################################################################
 if (APPLE)
   option (OPTION_APPLE_X11 "use X11" OFF)
-  option (OPTION_APPLE_SDL "use SDL" OFF)
   if (CMAKE_OSX_SYSROOT)
     list (APPEND FLTK_CFLAGS "-isysroot ${CMAKE_OSX_SYSROOT}")
   endif (CMAKE_OSX_SYSROOT)
@@ -100,14 +99,6 @@ if (OPTION_APPLE_X11)
   endif (X11_INCLUDE_DIR)
 endif (OPTION_APPLE_X11)
 
-if (OPTION_APPLE_SDL)
-  find_package (SDL2 REQUIRED)
-  if (SDL2_FOUND)
-    set (USE_SDL 1)
-    list (APPEND FLTK_LDLIBS SDL2_LIBRARY)
-  endif (SDL2_FOUND)
-endif (OPTION_APPLE_SDL)
-
 #######################################################################
 option (OPTION_USE_POLL "use poll if available" OFF)
 mark_as_advanced (OPTION_USE_POLL)
@@ -238,8 +229,6 @@ if (OPTION_USE_GL)
     set (OPENGL_LIBRARIES -L${PATH_TO_XLIBS} -lGLU -lGL)
     unset(HAVE_GL_GLU_H CACHE)
     find_file (HAVE_GL_GLU_H GL/glu.h PATHS ${X11_INCLUDE_DIR})
-  elseif (OPTION_APPLE_SDL)
-    set (OPENGL_FOUND FALSE)
   else()
     include (FindOpenGL)
     if (APPLE)
@@ -619,10 +608,6 @@ endif (OPTION_USE_KDIALOG)
 #######################################################################
 
 #######################################################################
-option (OPTION_CREATE_ANDROID_STUDIO_IDE "create files needed to compile FLTK for Android" OFF)
-#######################################################################
-
-#######################################################################
 option (CMAKE_SUPPRESS_REGENERATION "suppress rules to re-run CMake on rebuild" OFF)
 mark_as_advanced (CMAKE_SUPPRESS_REGENERATION)
 
diff --git CMake/setup.cmake CMake/setup.cmake
index 84b3ebd..e2fd792 100644
--- CMake/setup.cmake
+++ CMake/setup.cmake
@@ -89,9 +89,6 @@ if (APPLE)
     if (NOT(${CMAKE_SYSTEM_VERSION} VERSION_LESS 17.0.0)) # a.k.a. macOS version â?¥ 10.13
       set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_LIBCPP_HAS_THREAD_API_PTHREAD")
     endif (NOT(${CMAKE_SYSTEM_VERSION} VERSION_LESS 17.0.0))
-  elseif (OPTION_APPLE_SDL)
-    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SDL2_INCLUDE_DIRS} -U__APPLE__")
-    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SDL2_INCLUDE_DIRS} -U__APPLE__")
   else ()
     set (__APPLE_QUARTZ__ 1)
     set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework Cocoa")
diff --git CMake/variables.cmake CMake/variables.cmake
index 7ff8a53..27672c7 100644
--- CMake/variables.cmake
+++ CMake/variables.cmake
@@ -41,8 +41,6 @@ endif (DEBUG_VARIABLES_CMAKE)
 
 if (WIN32)
   list (APPEND FLTK_LDLIBS -lole32 -luuid -lcomctl32 -lws2_32)
-elseif (APPLE AND OPTION_APPLE_SDL)
-  # FIXME: do nothing?
 elseif (APPLE AND NOT OPTION_APPLE_X11)
   list (APPEND FLTK_LDLIBS "-framework Cocoa")
 else ()
diff --git CMakeLists.txt CMakeLists.txt
index f472c4e..eb4e8ec 100644
--- CMakeLists.txt
+++ CMakeLists.txt
@@ -81,13 +81,6 @@ include (CMake/resources.cmake)
 include (CMake/options.cmake)
 
 #######################################################################
-# Android Studio setup
-#######################################################################
-if (OPTION_CREATE_ANDROID_STUDIO_IDE)
-  include (CMake/android.cmake)
-endif (OPTION_CREATE_ANDROID_STUDIO_IDE)
-
-#######################################################################
 # print (debug) several build variables and options
 #######################################################################
 
@@ -102,7 +95,6 @@ if (debug_build)
   fl_debug_var (MSVC)
   fl_debug_var (UNIX)
   fl_debug_var (APPLE)
-  fl_debug_var (ANDROID)
   fl_debug_var (CMAKE_BUILD_TYPE)
   fl_debug_var (CMAKE_SIZEOF_VOID_P)
   fl_debug_var (OPTION_OPTIM)
@@ -124,9 +116,7 @@ add_subdirectory(src)
 # build fluid
 #######################################################################
 
-if (NOT ANDROID)
-  add_subdirectory(fluid)
-endif()
+add_subdirectory(fluid)
 
 #######################################################################
 # variables shared by export and install
@@ -160,13 +150,6 @@ if (FLTK_BUILD_EXAMPLES)
 endif (FLTK_BUILD_EXAMPLES)
 
 #######################################################################
-# Android Studio wrapup
-#######################################################################
-if (OPTION_CREATE_ANDROID_STUDIO_IDE)
-  CREATE_ANDROID_IDE_WRAPUP()
-endif (OPTION_CREATE_ANDROID_STUDIO_IDE)
-
-#######################################################################
 # installation
 #######################################################################
 include (CMake/install.cmake)
diff --git FL/android.H FL/android.H
deleted file mode 100644
index f1ad220..0000000
--- FL/android.H
+++ /dev/null
@@ -1,159 +0,0 @@
-//
-// Template header file for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2016-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-// Do not directly include this file, instead use <FL/android.H>.
-
-// These types and variables give access to internal, platform-specific data through the public API.
-// They require to include platform.H (in contrast to types defined in platform_types.h)
-
-#if !defined(FL_PLATFORM_H)
-#  error "Never use <FL/android.H> directly; include <FL/platform.H> instead."
-#endif // !FL_PLATFORM_H
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- This is the function that application code must implement, representing
- the main entry to the app.
- */
-extern int main(int argc, char **argv);
-
-#ifdef __cplusplus
-}
-#endif
-
-
-
-typedef void *Window; // used by fl_find(), fl_xid() and class Fl_X
-
-/* Reference to the current device context
- For back-compatibility only. The preferred procedure to get this reference is
- Fl_Surface_Device::surface()->driver()->gc().
- */
-extern void *fl_gc;
-
-/**
- These events are specific to the Android OS driver system. They can
- be read by adding a callback via Fl::add_system_handler() and reading Fl::event()
- Don't change the order of these enums! See Fl_Android_Application.H .
- */
-enum Fl_Android_Platform_Event
-{
-  FL_ANDROID_EVENTS = 0x00010000,
-
-  /**
-   * Command from main thread: the AInputQueue has changed.  Upon processing
-   * this command, android_app->inputQueue will be updated to the new queue
-   * (or NULL).
-   */
-  FL_ANDROID_EVENT_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.
-   */
-  FL_ANDROID_EVENT_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.
-   */
-  FL_ANDROID_EVENT_TERM_WINDOW,
-
-  /**
-   * Command from main thread: the current ANativeWindow has been resized.
-   * Please redraw with its new size.
-   */
-  FL_ANDROID_EVENT_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.
-   */
-  FL_ANDROID_EVENT_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.
-   */
-  FL_ANDROID_EVENT_CONTENT_RECT_CHANGED,
-
-  /**
-   * Command from main thread: the app's activity window has gained
-   * input focus.
-   */
-  FL_ANDROID_EVENT_GAINED_FOCUS,
-
-  /**
-   * Command from main thread: the app's activity window has lost
-   * input focus.
-   */
-  FL_ANDROID_EVENT_LOST_FOCUS,
-
-  /**
-   * Command from main thread: the current device configuration has changed.
-   */
-  FL_ANDROID_EVENT_CONFIG_CHANGED,
-
-  /**
-   * Command from main thread: the system is running low on memory.
-   * Try to reduce your memory use.
-   */
-  FL_ANDROID_EVENT_LOW_MEMORY,
-
-  /**
-   * Command from main thread: the app's activity has been started.
-   */
-  FL_ANDROID_EVENT_START,
-
-  /**
-   * Command from main thread: the app's activity has been resumed.
-   */
-  FL_ANDROID_EVENT_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.
-   */
-  FL_ANDROID_EVENT_SAVE_STATE,
-
-  /**
-   * Command from main thread: the app's activity has been paused.
-   */
-  FL_ANDROID_EVENT_PAUSE,
-
-  /**
-   * Command from main thread: the app's activity has been stopped.
-   */
-  FL_ANDROID_EVENT_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.
-   */
-  FL_ANDROID_EVENT_DESTROY
-};
diff --git FL/platform.H FL/platform.H
index 80c1395..4e068c2 100644
--- FL/platform.H
+++ FL/platform.H
@@ -37,8 +37,6 @@ class Fl_Window;
 #    include "win32.H"
 #  elif defined(__APPLE__)
 #    include "mac.H"
-#  elif defined(__ANDROID__)
-#    include "android.H"
 #  elif defined(FLTK_USE_X11)
 #    include "x11.H"
 #  endif // _WIN32
diff --git FL/platform_types.h FL/platform_types.h
index cafeae0..51963d6 100644
--- FL/platform_types.h
+++ FL/platform_types.h
@@ -72,12 +72,6 @@ typedef opaque GLContext; /**< an OpenGL graphics context, into which all OpenGL
 typedef intptr_t fl_intptr_t;
 typedef uintptr_t fl_uintptr_t;
 
-#elif defined(__ANDROID__)
-
-#include <sys/stat.h>
-typedef intptr_t fl_intptr_t;
-typedef uintptr_t fl_uintptr_t;
-
 #else /* ! _WIN64 */
 
 typedef long fl_intptr_t;
@@ -122,22 +116,6 @@ typedef struct HGLRC__ *GLContext;
    struct dirent {char d_name[1];};
 #endif
 
-#elif defined(__ANDROID__)
-
-#ifdef __cplusplus
-typedef class Fl_Rect_Region *Fl_Region;
-#else
-typedef struct Fl_Rect_Region *Fl_Region;
-#endif
-
-// TODO: the types below have not yet been ported
-typedef unsigned long Fl_Offscreen;
-typedef unsigned long Fl_Bitmask;
-typedef int FL_SOCKET;
-typedef struct __GLXcontextRec *GLContext;
-#include <sys/types.h>
-#include <dirent.h>
-
 #elif defined(FLTK_USE_X11)
 
 typedef unsigned long Fl_Offscreen;
diff --git README.Android.md README.Android.md
deleted file mode 100644
index 4dfba17..0000000
--- README.Android.md
+++ /dev/null
@@ -1,80 +0,0 @@
-README.Android.md
-
-# Building and Running FLTK with Android Studio 3
-
-
-WARNING: FLTK FOR ANDROID IS WORK IN PROGRESS IN A PRETTY EARLY STAGE.
-
-
-## Contents
-
-1. Building FLTK with Android Studio 3
-2. Extensions and limitation of FLTK on Android
-3. Document History
-
-
-## Building FLTK with Android Studio 3
-
-There is no need to ever write a single line of Java.
-
-Download and install AndroidStudio on your developer machine. If you use
-AndroidStudio for the first time, use the IDE to download and build the
-"Native Plasm" sample app. In the process, all resources required to build
-FLTK will be installed. Once Native Plasm runs on your emulator or physical
-device, you are ready to install FLTK.
-
-Build FLTK for your native platform first using CMake. AndroidStudio will need a native
-version of the user interface design tool _Fluid_.
-
-The following example is for the _Xcode_ IDE on _macOS_. The same should work for
-other IDEs and Makefiles on other platforms that run _AndroidStudio_.
-
-```bash
-git clone https://github.com/fltk/fltk.git fltk-1.4.git
-cd fltk-1.4.git
-mkdir build
-cd build
-mkdir Xcode
-cd Xcode
-cmake -G "Unix Makefiles" \
-  -D OPTION_USE_SYSTEM_LIBJPEG=Off \
-  -D OPTION_USE_SYSTEM_ZLIB=Off \
-  -D OPTION_USE_SYSTEM_LIBPNG=Off \
-  -D OPTION_CREATE_ANDROID_STUDIO_IDE=On \
-  ../..
-```
-Note the last option, `-D OPTION_CREATE_ANDROID_STUDIO_IDE=On`. This option will
-create the file needed to create an FLTK demo project in
-`fltk-1.4.git/build/Xcode/AndroidStudio`.
-
-- open the `build/Xcode/AndroidStudio/` directory as a project in AndroidStudio3
-
-- click "run"; the project should compile and run out of the box
-
-
-## Extensions and limitation of FLTK on Android
-
-Android support for FLTK is in an early stage. As of January 2019, most
-rendering works, fonts work, bitmaps and pixmaps work, clipping works, window
-layering works, and mouse clicks and keyboard events are handled
-
-When loading fonts:
- - font names starting with a $ will have the system font path inserted
- - font names starting with an @ will be loaded via the Asset Manager
- - all other names will be used verbatim
-
-Limitations:
- - the screen size is currently fixed to 600x800 and is scaled up
- - many many big and little functions are not yet implemented
-
-
-## Document History
-
-Jan 15 2019 - matt: rewrote document to explain the new CMake process
-Mar 29 2018 - matt: many graphics functions have been implemented, keyboard
-Mar 17 2018 - matt: added Android extensions for fonts
-Mar 12 2018 - matt: started list of limitation that serevs as information to the
-                    user as much as a todo list for core developers
-Mar  6 2018 - matt: moved project to ide/AndroidStudio3/
-Mar  2 2018 - matt: rewriting Android port and documentation from scratch
-Feb  9 2016 - matt: recreated document with more warnings and active support
diff --git README.IDE.txt README.IDE.txt
index 8662605..223da0c 100644
--- README.IDE.txt
+++ README.IDE.txt
@@ -3,10 +3,10 @@
 -----------------------------------------
 
 Since FLTK 1.4 we do no longer include IDE [1] solution files in our
-source distribution. [2]
+source distribution.
 
 If you want to build the FLTK library with an IDE you need to use
-CMake [3] to generate the IDE files from the source distribution.
+CMake [2] to generate the IDE files from the source distribution.
 
 The FLTK team will officially support generation of selected IDE projects,
 particularly Visual C++ and Xcode. Older version support of these IDE
@@ -45,8 +45,4 @@ Note: "Not supported" doesn't mean that a particular generator does not work,
     for instance Visual Studio, Xcode, Eclipse, ...
     https://en.wikipedia.org/wiki/Integrated_development_environment
 
-[2] The only exception is the Android Studio IDE in ide/AndroidStudio3
-    currently provided for testing. This IDE solution is likely to be
-    moved elsewhere or removed entirely before FLTK 1.4 will be released.
-
-[3] https://cmake.org/
+[2] https://cmake.org/
diff --git README.Pico.txt README.Pico.txt
deleted file mode 100644
index a4c836e..0000000
--- README.Pico.txt
+++ /dev/null
@@ -1,72 +0,0 @@
-This documentation will explain how to quickly port FLTK to a new
-platform using the Pico driver system. For now, only the sample
-SDL Pico driver on macOS compiles and barely runs.
-
-> mkdir build
-> cd build
-> mkdir XcodeSDL
-> cd XcodeSDL
-> cmake -G Xcode -D OPTION_APPLE_SDL=ON ../..
-
-tl;dr - the recent commit should be transparent to all developers on
-other platforms. On macOS, the CMake setup adds 'OPTION_APPLE_SDL=ON'
-that will run FLTK on top of SDL, which in turn runs on top of the
-new "Pico" driver set.
-
-The greatest help I can get from the core developers is to continue
-to refactor the platform specific functionalities into the drivers.
-
----
-
-OK, long version. I know that I am repeating myself and I don't expect
-those of you who "got it" weeks ago to read this again. Writing this
-down is also for me to avoid losing track ;-)
-
-Goal 1: find all the stuff that must still go into drivers
-Goal 2: have a base driver for all future porting efforts
-Goal 3: make porting fun with early gratification to the coder
-Goal 4: extensively document a sample port (SDL), and how to improve it
-Goal 5: use SDL as a base library, thereby porting FLTK to iOS and Android
-
-
-This is the start of a new driver, named "Pico". "Pico" is here to
-implement what I called the minimal driver.
-
-"Pico" implements (eventually) a complete set of drivers. The drivers
-will be limited in functionality, but they will be good enough to
-allow basic UI's with most FLTK widget types.
-
-If "Pico" compiles without any "USE_PICO" or similar defines, we
-have reached goal 1.
-
-"Pico" will implement all driver functionalities "in good faith",
-meaning, in a way that FLTK runs without crashing. Only very very
-basic functions are not implemented. A driver that derives from "Pico"
-needs only to implement those missing functions, thereby reaching goals
-2 and 3. As far as I can tell, those will be:
-
-- open a single fixed size window
-- setting a pixel in a color inside that window
-- polling and waiting for PUSH and RELEASE events and their positions
-
-By implementing these three simple functions in the SDL driver,
-"test/hello" and quite a bunch of other tests will run (yes, they
-will be slow, but the will work).
-
-This will give the person who is porting FLTK to their platform a
-very early confirmation that their build setup is working and a
-very early gratification, reaching goal 3.
-
-Obviously, SDL is much more powerful, and by the nature of the
-virtual functions in the driver system, we can incrementally add
-functionality to the SDL driver, and document this incremental
-nature, reaching goal 4.
-
-If we do all this right, we have goal 5.
-
-If SDL is too big or complex for, say, Android, we can simply start
-a new native Android driver set by implementing the three functions
-mentioned above, and then go from there.
-
-
-- Matthias
diff --git README.experimental.txt README.experimental.txt
new file mode 100644
index 0000000..01d8e18
--- /dev/null
+++ README.experimental.txt
@@ -0,0 +1,29 @@
+Removed Experimental Platforms
+------------------------------
+
+Removed platforms and drivers include:
+
+- Android
+- Pico
+- PicoAndroid
+- PicoSDL
+
+These platforms and their drivers were experimental and undocumented.
+
+They have been removed in January 2022 for maintenance reasons as
+discussed in fltk.coredev: "FLTK 1.4.0 release schedule", see:
+https://groups.google.com/g/fltkcoredev/c/PDbHTRpXVh0/m/JqboexZ_AwAJ
+
+More information, for instance where to find further development
+(if any) will be added in this file.
+
+If you want to take a look at the removed drivers you can checkout
+the git tag "experimental-2022-01":
+
+$ git clone https://github.com/fltk/fltk.git fltk-experimental
+$ cd fltk-experimental
+$ git checkout experimental-2022-01
+
+You can also browse the files on GitHub:
+
+https://github.com/fltk/fltk/tree/b275ff07158e80d1744ddb2f6c51094a87cf079a
diff --git configh.cmake.in configh.cmake.in
index f489cdb..cf537af 100644
--- configh.cmake.in
+++ configh.cmake.in
@@ -158,15 +158,6 @@
 #cmakedefine __APPLE_QUARTZ__ 1
 
 /*
- * USE_SDL
- *
- * Should we use SDL for the current platform
- *
- */
-
-#cmakedefine USE_SDL 1
-
-/*
  * HAVE_GL_OVERLAY:
  *
  * It is possible your GL has an overlay even if X does not.  If so,
diff --git configh.in configh.in
index 0317e97..86e6897 100644
--- configh.in
+++ configh.in
@@ -157,16 +157,6 @@
 #undef __APPLE_QUARTZ__
 
 /*
- * USE_SDL
- *
- * Should we use SDL for the current platform
- * *FIXME* USE_SDL not yet implemented in configure !
- *
- */
-
-#undef USE_SDL
-
-/*
  * HAVE_GL_OVERLAY:
  *
  * It is possible your GL has an overlay even if X does not.  If so,
diff --git examples/CMakeLists.txt examples/CMakeLists.txt
index 2ccafc6..eb055ce 100644
--- examples/CMakeLists.txt
+++ examples/CMakeLists.txt
@@ -146,7 +146,7 @@ endforeach (src)
 
 # Note: macOS does not need libGLEW
 
-if (APPLE AND (NOT OPTION_APPLE_X11) AND (NOT OPTION_APPLE_SDL))
+if (APPLE AND (NOT OPTION_APPLE_X11))
   if (NOT LIB_GLEW)
     set (LIB_GLEW TRUE)
   endif ()
diff --git fluid/CMakeLists.txt fluid/CMakeLists.txt
index f25e0ab..a5676ae 100644
--- fluid/CMakeLists.txt
+++ fluid/CMakeLists.txt
@@ -84,7 +84,7 @@ endif (WIN32)
 
 source_group("Header Files" FILES ${HEADERFILES})
 
-if (APPLE AND (NOT OPTION_APPLE_X11) AND (NOT OPTION_APPLE_SDL))
+if (APPLE AND (NOT OPTION_APPLE_X11))
   set (ICON_NAME fluid.icns)
   set (ICON_PATH "${CMAKE_CURRENT_SOURCE_DIR}/icons/${ICON_NAME}")
   add_executable (fluid MACOSX_BUNDLE ${CPPFILES} ${HEADERFILES} ${ICON_PATH})
@@ -104,7 +104,7 @@ if (APPLE AND (NOT OPTION_APPLE_X11) AND (NOT OPTION_APPLE_SDL))
 
 else ()
   add_executable (fluid WIN32 ${CPPFILES} ${HEADERFILES})
-endif (APPLE AND (NOT OPTION_APPLE_X11) AND (NOT OPTION_APPLE_SDL))
+endif (APPLE AND (NOT OPTION_APPLE_X11))
 
 target_link_libraries (fluid fltk fltk_images)
 
@@ -123,7 +123,7 @@ endif (USE_GDIPLUS)
 
 # install fluid
 
-if (APPLE AND (NOT OPTION_APPLE_X11) AND (NOT OPTION_APPLE_SDL))
+if (APPLE AND (NOT OPTION_APPLE_X11))
 
   # On macOS, Fluid must be installed twice. The bundled version of Fluid needs
   # to go into the /Applications folder to make it visible as a user App with
@@ -149,7 +149,7 @@ else()
     LIBRARY DESTINATION ${FLTK_LIBDIR}
     ARCHIVE DESTINATION ${FLTK_LIBDIR}
   )
-endif (APPLE AND (NOT OPTION_APPLE_X11) AND (NOT OPTION_APPLE_SDL))
+endif (APPLE AND (NOT OPTION_APPLE_X11))
 
 # install desktop files
 
diff --git src/CMakeLists.txt src/CMakeLists.txt
index 17c6479..bca6d98 100644
--- src/CMakeLists.txt
+++ src/CMakeLists.txt
@@ -178,7 +178,7 @@ list (APPEND HEADER_FILES
 
 set (GL_HEADER_FILES)  # FIXME: not (yet?) defined
 
-if ((FLTK_USE_X11 OR USE_SDL) AND NOT OPTION_PRINT_SUPPORT)
+if (FLTK_USE_X11 AND NOT OPTION_PRINT_SUPPORT)
   set (PSFILES
   )
 else ()
@@ -186,7 +186,7 @@ else ()
     drivers/PostScript/Fl_PostScript.cxx
     drivers/PostScript/Fl_PostScript_image.cxx
   )
-endif ((FLTK_USE_X11 OR USE_SDL) AND NOT OPTION_PRINT_SUPPORT)
+endif (FLTK_USE_X11 AND NOT OPTION_PRINT_SUPPORT)
 
 set (DRIVER_FILES)
 
@@ -241,35 +241,6 @@ if (FLTK_USE_X11)
     drivers/Xlib/Fl_Font.H
   )
 
-elseif (USE_SDL)
-
-  # SDL2
-
-  set (DRIVER_FILES
-    drivers/Pico/Fl_Pico_System_Driver.cxx
-    drivers/Pico/Fl_Pico_Screen_Driver.cxx
-    drivers/Pico/Fl_Pico_Window_Driver.cxx
-    drivers/Pico/Fl_Pico_Graphics_Driver.cxx
-    drivers/Pico/Fl_Pico_Copy_Surface.cxx
-    drivers/Pico/Fl_Pico_Image_Surface.cxx
-    drivers/PicoSDL/Fl_PicoSDL_System_Driver.cxx
-    drivers/PicoSDL/Fl_PicoSDL_Screen_Driver.cxx
-    drivers/PicoSDL/Fl_PicoSDL_Window_Driver.cxx
-    drivers/PicoSDL/Fl_PicoSDL_Graphics_Driver.cxx
-    drivers/PicoSDL/Fl_PicoSDL_Copy_Surface.cxx
-    drivers/PicoSDL/Fl_PicoSDL_Image_Surface.cxx
-  )
-  set (DRIVER_HEADER_FILES
-    drivers/Pico/Fl_Pico_System_Driver.H
-    drivers/Pico/Fl_Pico_Screen_Driver.H
-    drivers/Pico/Fl_Pico_Window_Driver.H
-    drivers/Pico/Fl_Pico_Graphics_Driver.H
-    drivers/PicoSDL/Fl_PicoSDL_System_Driver.H
-    drivers/PicoSDL/Fl_PicoSDL_Screen_Driver.H
-    drivers/PicoSDL/Fl_PicoSDL_Window_Driver.H
-    drivers/PicoSDL/Fl_PicoSDL_Graphics_Driver.H
-  )
-
 elseif (APPLE)
 
   # Apple Quartz
@@ -302,34 +273,6 @@ elseif (APPLE)
     drivers/Quartz/Fl_Font.H
   )
 
-elseif (ANDROID)
-
-  # Android
-
-  set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
-
-  set (DRIVER_FILES
-    drivers/Android/Fl_Android_Application.cxx
-    drivers/Android/Fl_Android_System_Driver.cxx
-    drivers/Android/Fl_Android_Screen_Driver.cxx
-    drivers/Android/Fl_Android_Screen_Keyboard.cxx
-    drivers/Android/Fl_Android_Window_Driver.cxx
-    drivers/Android/Fl_Android_Image_Surface_Driver.cxx
-    drivers/Android/Fl_Android_Graphics_Driver.cxx
-    drivers/Android/Fl_Android_Graphics_Clipping.cxx
-    drivers/Android/Fl_Android_Graphics_Font.cxx
-  )
-  set (DRIVER_HEADER_FILES
-    drivers/Android/Fl_Android_Application.H
-    drivers/Android/Fl_Android_System_Driver.H
-    drivers/Android/Fl_Android_Screen_Driver.H
-    drivers/Android/Fl_Android_Window_Driver.H
-    drivers/Android/Fl_Android_Graphics_Driver.H
-    drivers/Android/Fl_Android_Graphics_Clipping.H
-    drivers/Android/Fl_Android_Graphics_Font.H
-  )
-
-
 else ()
 
   # Windows (GDI)
@@ -473,7 +416,7 @@ if (WIN32)
   )
 endif (WIN32)
 
-if (APPLE AND (NOT OPTION_APPLE_X11) AND (NOT OPTION_APPLE_SDL))
+if (APPLE AND (NOT OPTION_APPLE_X11))
   set (MMFILES
     Fl_cocoa.mm
     drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm
@@ -483,7 +426,7 @@ if (APPLE AND (NOT OPTION_APPLE_X11) AND (NOT OPTION_APPLE_SDL))
 else()
   set (MMFILES
   )
-endif (APPLE AND (NOT OPTION_APPLE_X11) AND (NOT OPTION_APPLE_SDL))
+endif (APPLE AND (NOT OPTION_APPLE_X11))
 
 
 #######################################################################
@@ -519,10 +462,6 @@ if (FLTK_USE_X11)
   list (APPEND OPTIONAL_LIBS ${X11_LIBRARIES})
 endif (FLTK_USE_X11)
 
-if (USE_SDL)
-  list (APPEND OPTIONAL_LIBS ${SDL2_LIBRARY})
-endif (USE_SDL)
-
 if (WIN32)
   list (APPEND OPTIONAL_LIBS comctl32 ws2_32)
 endif (WIN32)
diff --git src/Fl_Device.cxx src/Fl_Device.cxx
index f977210..7344ff1 100644
--- src/Fl_Device.cxx
+++ src/Fl_Device.cxx
@@ -50,7 +50,7 @@
       |
       +- Fl_PostScript_Graphics_Driver: platform-independent graphics driver for PostScript drawing
       +- Fl_SVG_Graphics_Driver: platform-independent graphics driver for Scalable Vector Graphics drawing
-      +- Fl_..._Graphics_Driver: platform-specific graphics driver (MacOS, Android, Pico)
+      +- Fl_..._Graphics_Driver: platform-specific graphics driver (MacOS)
           +- Fl_Quartz_Printer_Graphics_Driver: MacOS-specific, for drawing to printers
       +- Fl_Scalable_Graphics_Driver: helper class to support GUI scaling
           +- Fl_Xlib_Graphics_Driver: X11-specific graphics driver
diff --git src/Fl_System_Driver.cxx src/Fl_System_Driver.cxx
index 75bbf3e..45927ae 100644
--- src/Fl_System_Driver.cxx
+++ src/Fl_System_Driver.cxx
@@ -43,7 +43,7 @@ const int Fl_System_Driver::fl_YNegative =   0x0020;
 // and/or use their own table. It is defined here "static" and assigned
 // in the constructor to avoid static initialization race conditions.
 //
-// As of June 2018 these platforms are Windows and Android. X11 does not
+// As of January 2022 the only platform is Windows. X11 does not
 // use a key table at all.
 // Platforms that use their own key tables must assign them in their
 // constructors (which overwrites the pointer and size).
diff --git src/drivers/Android/Fl_Android_Application.H src/drivers/Android/Fl_Android_Application.H
deleted file mode 100644
index e511b67..0000000
--- src/drivers/Android/Fl_Android_Application.H
+++ /dev/null
@@ -1,270 +0,0 @@
-//
-// Android Native Application interface
-// for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_Android_Application.H
- \brief Definition of Android Native Application interface
- */
-
-#ifndef FL_ANDROID_APPLICATION_H
-#define FL_ANDROID_APPLICATION_H
-
-#include <FL/Fl.H>
-
-extern void (*fl_unlock_function)();
-extern void (*fl_lock_function)();
-
-
-#include <poll.h>
-#include <pthread.h>
-#include <sched.h>
-
-#include <android/configuration.h>
-#include <android/looper.h>
-#include <android/native_activity.h>
-
-
-/**
- A class to make Java calls from C++ easier.
- */
-class Fl_Android_Java
-{
-  JavaVM *pJavaVM = nullptr;
-  JNIEnv *pJNIEnv = nullptr;
-  jobject pNativeActivity;
-  jclass pNativeActivityClass;
-  bool pAttached = false;
-
-public:
-  Fl_Android_Java();
-  ~Fl_Android_Java();
-  bool is_attached() { return pAttached; }
-  JavaVM *VM() { return pJavaVM; }
-  JNIEnv *env() { return pJNIEnv; }
-  jobject native_ativity() { return pNativeActivity; }
-  jclass native_activity_class() { return pNativeActivityClass; }
-};
-
-
-/**
- Static class that manages all interaction between the Android Native Activity
- and the FLTK library. It also keeps often used data for global access.
-
- On launch, it creates a main thread and communication pipe to
- the Activity. All FLTK code will run in that thread. Activity
- events will be polled by the Screen driver using the provided
- Android Looper, and will also be routed back to this class as needed.
-
- This code is based on the native activity interface
- provided by <android/native_activity.h>. It is based on a set
- of application-provided callbacks that will be called
- by the Activity's main thread when certain events occur.
-
- 1/ The application must provide a function named "int main(argc, argv)" that
-    will be called when the activity is created, in a new thread that is
-    distinct from the activity's main thread.
-
- 2/ The application has access to a static "Fl_Android_Application" class
-    that contains references to other important objects, e.g. the
-    ANativeActivity object instance the application is running in.
-
- 3/ the "Fl_Android_Application" class 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.
-
-    FLTK will add more items to the looper for timers and file and socket
-    communication. (fl_add_timeout, Fl::add_fd(), ...
- */
-class Fl_Android_Application
-{
-public:
-
-  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,
-
-    /**
-     * Timer data ID of all timer events coming from the Unix timer_create()
-     * and friends, used in fl_add_timeout() and colleagues.
-     */
-            LOOPER_ID_TIMER,
-
-    /**
-     * Start of user-defined ALooper identifiers.
-     */
-            LOOPER_ID_USER,
-  };
-
-  /**
-   * @see android.H Fl_Android_Platform_Event
-   */
-  enum {
-            APP_CMD_INPUT_CHANGED,
-            APP_CMD_INIT_WINDOW,
-            APP_CMD_TERM_WINDOW,
-            APP_CMD_WINDOW_RESIZED,
-            APP_CMD_WINDOW_REDRAW_NEEDED,
-            APP_CMD_CONTENT_RECT_CHANGED,
-            APP_CMD_GAINED_FOCUS,
-            APP_CMD_LOST_FOCUS,
-            APP_CMD_CONFIG_CHANGED,
-            APP_CMD_LOW_MEMORY,
-            APP_CMD_START,
-            APP_CMD_RESUME,
-            APP_CMD_SAVE_STATE,
-            APP_CMD_PAUSE,
-            APP_CMD_STOP,
-            APP_CMD_DESTROY,
-  };
-
-public:
-  // --- logging
-  static void log_e(const char *text, ...);
-  static void log_w(const char *text, ...);
-  static void log_i(const char *text, ...);
-  static void log_v(const char *text, ...);
-
-  // --- application state stuff
-  static int8_t read_cmd();
-  static void pre_exec_cmd(int8_t cmd);
-  static void post_exec_cmd(int8_t cmd);
-  static int destroy_requested() { return pDestroyRequested; }
-  static const char *get_internal_data_path() { return pActivity->internalDataPath; }
-  static const char *get_external_data_path() { return pActivity->externalDataPath; }
-  static AAssetManager *get_asset_manager() { return pActivity->assetManager; }
-  static ANativeActivity *get_activity() { return pActivity; }
-
-  // --- event handling
-  static AInputQueue *input_event_queue() { return pInputQueue; }
-
-  // --- screen stuff
-  static bool copy_screen();
-  static inline ANativeWindow *native_window() { return pNativeWindow; }
-  static inline ANativeWindow_Buffer &graphics_buffer() { return pApplicationWindowBuffer; }
-
-  // --- timer stuff
-  static void send_timer_index(uint8_t ix);
-  static uint8_t receive_timer_index();
-
-
-protected:
-  static void free_saved_state();
-  static void print_cur_config();
-  static void destroy();
-  static void* thread_entry(void* param);
-
-  // --- screen handling stuff
-  static void allocate_screen();
-  static bool lock_screen();
-  static void unlock_and_post_screen();
-  static bool screen_is_locked();
-
-  // --- timer stuff
-  static void create_timer_handler();
-  static void destroy_timer_handler();
-
-  static ANativeActivity *pActivity;
-  static AConfiguration *pConfig;
-  static void *pSavedState;
-  static size_t pSavedStateSize;
-  static ALooper *pAppLooper;
-  static AInputQueue *pInputQueue;
-  static ANativeWindow *pNativeWindow;
-  static ANativeWindow_Buffer pNativeWindowBuffer;
-  static ANativeWindow_Buffer pApplicationWindowBuffer;
-  static int pActivityState;
-  static int pDestroyRequested;
-
-  // ---- no need to make these visible to the outside ----
-  static pthread_mutex_t pMutex;
-  static pthread_cond_t pCond;
-  static int pMsgReadPipe;
-  static int pMsgWritePipe;
-  static pthread_t pThread;
-  static int pRunning;
-  static int pStateSaved;
-  static int pDestroyed;
-  static AInputQueue* pPendingInputQueue;
-  static ANativeWindow* pPendingWindow;
-
-  // --- timer variables
-  static int pTimerReadPipe;
-  static int pTimerWritePipe;
-
-};
-
-
-class Fl_Android_Activity : public Fl_Android_Application
-{
-public:
-  static void create(ANativeActivity* activity, void* savedState, size_t savedStateSize);
-
-private:
-  static void set_activity(ANativeActivity *a) { pActivity = a; }
-  static void set_callbacks();
-
-  // ---- Android Native Activity interface
-  static void write_cmd(int8_t cmd);
-  static void set_input(AInputQueue* inputQueue);
-  static void set_window(ANativeWindow* window);
-  static void set_activity_state(int8_t cmd);
-  static void close_activity();
-
-  // ---- Android Native Activity callbacks ----
-  static void onContentRectChanged(ANativeActivity *activity, const ARect *rect);
-  static void onNativeWindowRedrawNeeded(ANativeActivity *activity, ANativeWindow *window);
-  static void onNativeWindowResized(ANativeActivity *activity, ANativeWindow *window);
-  static void onDestroy(ANativeActivity* activity);
-  static void onStart(ANativeActivity* activity);
-  static void onResume(ANativeActivity* activity);
-  static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen);
-  static void onPause(ANativeActivity* activity);
-  static void onStop(ANativeActivity* activity);
-  static void onConfigurationChanged(ANativeActivity* activity);
-  static void onLowMemory(ANativeActivity* activity);
-  static void onWindowFocusChanged(ANativeActivity* activity, int focused);
-  static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window);
-  static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window);
-  static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue);
-  static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue);
-};
-
-
-#endif // FL_ANDROID_APPLICATION_H
diff --git src/drivers/Android/Fl_Android_Application.cxx src/drivers/Android/Fl_Android_Application.cxx
deleted file mode 100644
index 32feee1..0000000
--- src/drivers/Android/Fl_Android_Application.cxx
+++ /dev/null
@@ -1,843 +0,0 @@
-//
-// Android Native Application interface
-// for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_Android_Application.H
- \brief Definition of Android Native Application interface
- */
-
-#include "Fl_Android_Application.H"
-#include "Fl_Android_Window_Driver.H"
-
-#include <FL/platform.H>
-#include <FL/fl_draw.H>
-#include <FL/fl_string_functions.h>
-
-#include <jni.h>
-
-#include <errno.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/resource.h>
-
-#include <android/log.h>
-
-
-void fl_set_status(int x, int y, int w, int h) {}
-
-static const char *LOG_TAG = "FLTK";
-
-
-// The ANativeActivity object instance that this app is running in.
-ANativeActivity *Fl_Android_Application::pActivity = 0L;
-
-// The current configuration the app is running in.
-AConfiguration* Fl_Android_Application::pConfig = 0L;
-
-// 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* Fl_Android_Application::pSavedState = 0;
-size_t Fl_Android_Application::pSavedStateSize = 0;
-
-// The ALooper associated with the app's thread.
-ALooper* Fl_Android_Application::pAppLooper = 0;
-
-// When non-NULL, this is the input queue from which the app will
-// receive user input events.
-AInputQueue* Fl_Android_Application::pInputQueue = 0;
-
-// When non-NULL, this is the window surface that the app can draw in.
-ANativeWindow* Fl_Android_Application::pNativeWindow = 0;
-
-// Use this buffer for direct drawing access
-ANativeWindow_Buffer Fl_Android_Application::pNativeWindowBuffer = { 0 };
-ANativeWindow_Buffer Fl_Android_Application::pApplicationWindowBuffer = { 0 };
-
-// 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 Fl_Android_Application::pActivityState = 0;
-
-// This is non-zero when the application's NativeActivity is being
-// destroyed and waiting for the app thread to complete.
-int Fl_Android_Application::pDestroyRequested = 0;
-
-pthread_mutex_t Fl_Android_Application::pMutex = { 0 };
-pthread_cond_t Fl_Android_Application::pCond = { 0 };
-int Fl_Android_Application::pMsgReadPipe = 0;
-int Fl_Android_Application::pMsgWritePipe = 0;
-pthread_t Fl_Android_Application::pThread = 0;
-int Fl_Android_Application::pRunning = 0;
-int Fl_Android_Application::pStateSaved = 0;
-int Fl_Android_Application::pDestroyed = 0;
-//int Fl_Android_Application::pRedrawNeeded = 0;
-AInputQueue *Fl_Android_Application::pPendingInputQueue = 0;
-ANativeWindow *Fl_Android_Application::pPendingWindow = 0;
-//ARect Fl_Android_Application::pPendingContentRect = { 0 };
-
-int Fl_Android_Application::pTimerReadPipe = -1;
-int Fl_Android_Application::pTimerWritePipe = -1;
-
-
-
-void Fl_Android_Application::log_e(const char *text, ...)
-{
-  va_list args;
-  va_start (args, text);
-  __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, text, args);
-  va_end (args);
-}
-
-
-void Fl_Android_Application::log_w(const char *text, ...)
-{
-  va_list args;
-  va_start (args, text);
-  __android_log_vprint(ANDROID_LOG_WARN, LOG_TAG, text, args);
-  va_end (args);
-}
-
-
-void Fl_Android_Application::log_i(const char *text, ...)
-{
-  va_list args;
-  va_start (args, text);
-  __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, text, args);
-  va_end (args);
-}
-
-
-void Fl_Android_Application::log_v(const char *text, ...)
-{
-#ifdef _DEBUG
-  va_list args;
-  va_start (args, text);
-  __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, text, args);
-  va_end (args);
-#else
-  text = 0;
-#endif
-}
-
-
-void Fl_Android_Application::free_saved_state()
-{
-  pthread_mutex_lock(&pMutex);
-  if (pSavedState != NULL) {
-    free(pSavedState);
-    pSavedState = NULL;
-    pSavedStateSize = 0;
-  }
-  pthread_mutex_unlock(&pMutex);
-}
-
-/**
- Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next
- app command message.
- */
-int8_t Fl_Android_Application::read_cmd()
-{
-  int8_t cmd;
-  if (read(pMsgReadPipe, &cmd, sizeof(cmd)) == sizeof(cmd)) {
-    switch (cmd) {
-      case APP_CMD_SAVE_STATE:
-        free_saved_state();
-        break;
-      default:
-        break;
-    }
-    return cmd;
-  } else {
-    log_e("No data on command pipe!");
-  }
-  return -1;
-}
-
-
-void Fl_Android_Application::print_cur_config()
-{
-  char lang[2], country[2];
-  AConfiguration_getLanguage(pConfig, lang);
-  AConfiguration_getCountry(pConfig, country);
-
-  log_v("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(pConfig),
-       AConfiguration_getMnc(pConfig),
-       lang[0], lang[1], country[0], country[1],
-       AConfiguration_getOrientation(pConfig),
-       AConfiguration_getTouchscreen(pConfig),
-       AConfiguration_getDensity(pConfig),
-       AConfiguration_getKeyboard(pConfig),
-       AConfiguration_getNavigation(pConfig),
-       AConfiguration_getKeysHidden(pConfig),
-       AConfiguration_getNavHidden(pConfig),
-       AConfiguration_getSdkVersion(pConfig),
-       AConfiguration_getScreenSize(pConfig),
-       AConfiguration_getScreenLong(pConfig),
-       AConfiguration_getUiModeType(pConfig),
-       AConfiguration_getUiModeNight(pConfig));
-}
-
-/**
- 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 Fl_Android_Application::pre_exec_cmd(int8_t cmd)
-{
-  switch (cmd) {
-    case APP_CMD_INPUT_CHANGED:
-      log_v("APP_CMD_INPUT_CHANGED\n");
-      pthread_mutex_lock(&pMutex);
-      if (pInputQueue != NULL) {
-        AInputQueue_detachLooper(pInputQueue);
-      }
-      pInputQueue = pPendingInputQueue;
-      if (pInputQueue != NULL) {
-        log_v("Attaching input queue to looper");
-        AInputQueue_attachLooper(pInputQueue, pAppLooper, LOOPER_ID_INPUT, NULL, NULL);
-      }
-      pthread_cond_broadcast(&pCond);
-      pthread_mutex_unlock(&pMutex);
-      break;
-
-    case APP_CMD_INIT_WINDOW:
-      log_v("APP_CMD_INIT_WINDOW\n");
-      // tell the main thread that we received the window handle
-      pthread_mutex_lock(&pMutex);
-      pNativeWindow = pPendingWindow;
-      pthread_cond_broadcast(&pCond);
-      pthread_mutex_unlock(&pMutex);
-      // change the format of the buffers to match our needs
-      // FIXME: current default screen size and format is 600x800xRGB565
-      ANativeWindow_setBuffersGeometry(pNativeWindow,
-                                       600,
-                                       800,
-                                       WINDOW_FORMAT_RGB_565);
-      // tell FLTK that the buffer is available now
-      Fl_Android_Window_Driver::expose_all();
-      break;
-
-    case APP_CMD_TERM_WINDOW:
-      log_v("APP_CMD_TERM_WINDOW\n");
-      pthread_cond_broadcast(&pCond);
-      break;
-
-    case APP_CMD_RESUME:
-    case APP_CMD_START:
-    case APP_CMD_PAUSE:
-    case APP_CMD_STOP:
-      log_v("activityState=%d\n", cmd);
-      pthread_mutex_lock(&pMutex);
-      pActivityState = cmd;
-      pthread_cond_broadcast(&pCond);
-      pthread_mutex_unlock(&pMutex);
-      break;
-
-    case APP_CMD_CONFIG_CHANGED:
-      log_v("APP_CMD_CONFIG_CHANGED\n");
-      AConfiguration_fromAssetManager(pConfig,
-                                      pActivity->assetManager);
-      print_cur_config();
-      break;
-
-    case APP_CMD_DESTROY:
-      log_v("APP_CMD_DESTROY\n");
-      pDestroyRequested = 1;
-      Fl::program_should_quit(1);
-      break;
-
-    default:
-      break;
-  }
-}
-
-/**
- Call with the command returned by 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 Fl_Android_Application::post_exec_cmd(int8_t cmd)
-{
-  switch (cmd) {
-    case APP_CMD_TERM_WINDOW:
-      log_v("APP_CMD_TERM_WINDOW\n");
-      pthread_mutex_lock(&pMutex);
-      pNativeWindow = NULL;
-      pthread_cond_broadcast(&pCond);
-      pthread_mutex_unlock(&pMutex);
-      break;
-
-    case APP_CMD_SAVE_STATE:
-      log_v("APP_CMD_SAVE_STATE\n");
-      pthread_mutex_lock(&pMutex);
-      pStateSaved = 1;
-      pthread_cond_broadcast(&pCond);
-      pthread_mutex_unlock(&pMutex);
-      break;
-
-    case APP_CMD_RESUME:
-      free_saved_state();
-      break;
-  }
-}
-
-
-void Fl_Android_Application::create_timer_handler()
-{
-  int msgpipe[2];
-  if (::pipe(msgpipe)) {
-    log_e("could not create timer pipe: %s", strerror(errno));
-    return;
-  }
-  pTimerReadPipe = msgpipe[0];
-  pTimerWritePipe = msgpipe[1];
-  ALooper_addFd(pAppLooper, pTimerReadPipe, LOOPER_ID_TIMER, ALOOPER_EVENT_INPUT, NULL, NULL);
-}
-
-
-void Fl_Android_Application::destroy_timer_handler()
-{
-  ALooper_removeFd(pAppLooper, pTimerReadPipe);
-  ::close(pTimerWritePipe);
-  ::close(pTimerReadPipe);
-}
-
-
-void Fl_Android_Application::send_timer_index(uint8_t ix)
-{
-  if (pTimerWritePipe!=-1)
-    ::write(pTimerWritePipe, &ix, 1);
-}
-
-
-uint8_t Fl_Android_Application::receive_timer_index()
-{
-  uint8_t ix = 0;
-  if (pTimerReadPipe!=-1)
-    ::read(pTimerReadPipe, &ix, 1);
-  return ix;
-}
-
-
-void Fl_Android_Application::destroy()
-{
-  log_v("android_app_destroy!");
-  free_saved_state();
-  pthread_mutex_lock(&pMutex);
-  if (pInputQueue != NULL) {
-    AInputQueue_detachLooper(pInputQueue);
-  }
-  destroy_timer_handler();
-  AConfiguration_delete(pConfig);
-  pDestroyed = 1;
-  pthread_cond_broadcast(&pCond);
-  pthread_mutex_unlock(&pMutex);
-  // Can't touch android_app object after this.
-}
-
-
-void *Fl_Android_Application::thread_entry(void* param)
-{
-  pConfig = AConfiguration_new();
-  AConfiguration_fromAssetManager(pConfig, pActivity->assetManager);
-
-  print_cur_config();
-
-  pAppLooper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
-  ALooper_addFd(pAppLooper, pMsgReadPipe, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL, NULL);
-
-  create_timer_handler();
-
-  pthread_mutex_lock(&pMutex);
-  pRunning = 1;
-  pthread_cond_broadcast(&pCond);
-  pthread_mutex_unlock(&pMutex);
-
-  char *argv[] = { fl_strdup(pActivity->obbPath), 0 };
-  main(1, argv);
-
-  destroy();
-  return NULL;
-}
-
-/**
- Allocate memory for our internal screen buffer.
-
- FIXME: everything is currently hardcoded to an 600x800 resolution
- TODO: react to screen changes
- */
-void Fl_Android_Application::allocate_screen()
-{
-  pApplicationWindowBuffer.bits = calloc(600*800, 2); // one uint16_t per pixel
-  pApplicationWindowBuffer.width = 600;
-  pApplicationWindowBuffer.height = 800;
-  pApplicationWindowBuffer.stride = 600;
-  pApplicationWindowBuffer.format = WINDOW_FORMAT_RGB_565;
-}
-
-
-bool Fl_Android_Application::copy_screen()
-{
-  bool ret = false;
-  if (lock_screen()) {
-
-#if 0
-    // screen activity viewer
-    static int i = 0;
-    fl_color( (i&1) ? FL_RED : FL_GREEN);
-    fl_rectf(i*10, 600+i*10, 50, 50);
-    i++;
-    if (i>10) i = 0;
-#endif
-
-    // TODO: there are endless possibilities to optimize the following code
-    // We are wasting time by copying the entire screen contents at every dirty frame
-    // We can identify previously written buffers and copy only those pixels
-    // that actually changed.
-    const uint16_t *src = (uint16_t*)pApplicationWindowBuffer.bits;
-    int srcStride = pApplicationWindowBuffer.stride;
-    int ww = pApplicationWindowBuffer.width;
-    int hh = pApplicationWindowBuffer.height;
-
-    uint16_t *dst = (uint16_t*)pNativeWindowBuffer.bits;
-    int dstStride = pNativeWindowBuffer.stride;
-    if (pNativeWindowBuffer.width<ww) ww = pNativeWindowBuffer.width;
-    if (pNativeWindowBuffer.height<ww) ww = pNativeWindowBuffer.height;
-
-    for (int row=hh; row>0; --row) {
-      memcpy(dst, src, size_t(ww * 2));
-      src += srcStride;
-      dst += dstStride;
-    }
-
-    unlock_and_post_screen();
-    ret = true;
-  } else {
-    // wait for screen buffer to be created
-  }
-  return ret;
-}
-
-/**
- Take ownership of screen memory for gaining write access.
-
- If the screen is already locked, it will not be locked again
- and a value of true will be returned.
-
- \return true if we gaines access, false if no access was granted and screen memory must not be writte to
- */
-bool Fl_Android_Application::lock_screen()
-{
-  if (screen_is_locked())
-    return true;
-
-  if (!pNativeWindow) {
-    log_w("Unable to lock window buffer: no native window found.");
-    return false;
-  }
-
-  if (ANativeWindow_lock(pNativeWindow, &pNativeWindowBuffer, 0L) < 0) {
-    log_w("Unable to lock window buffer: Android won't lock.");
-    return false;
-  }
-  return true;
-}
-
-/**
- Release screen memory ownership and give it back to the system.
-
- The memory content will be copied to the physical screen next.
- If the screen is not locked, this call will have no effect.
- */
-void Fl_Android_Application::unlock_and_post_screen()
-{
-  if (!screen_is_locked())
-    return;
-
-  ANativeWindow_unlockAndPost(pNativeWindow);
-  pNativeWindowBuffer.bits = 0L; // avoid any misunderstandings...
-}
-
-/**
- Is the screen currently locked?
- \return true if it is locked and the app has write access.
- */
-bool Fl_Android_Application::screen_is_locked()
-{
-  return (pNativeWindowBuffer.bits!=0L);
-}
-
-
-// --------------------------------------------------------------------
-// Native activity interaction (called from main thread)
-// --------------------------------------------------------------------
-
-
-void Fl_Android_Activity::write_cmd(int8_t cmd)
-{
-  if (write(pMsgWritePipe, &cmd, sizeof(cmd)) != sizeof(cmd)) {
-    log_e("Failure writing android_app cmd: %s\n", strerror(errno));
-  }
-}
-
-
-void Fl_Android_Activity::set_input(AInputQueue* inputQueue)
-{
-  pthread_mutex_lock(&pMutex);
-  pPendingInputQueue = inputQueue;
-  write_cmd(APP_CMD_INPUT_CHANGED);
-  while (pInputQueue != pPendingInputQueue) {
-    pthread_cond_wait(&pCond, &pMutex);
-  }
-  pthread_mutex_unlock(&pMutex);
-}
-
-
-void Fl_Android_Activity::set_window(ANativeWindow* window)
-{
-  pthread_mutex_lock(&pMutex);
-  if (pPendingWindow != NULL) {
-    write_cmd(APP_CMD_TERM_WINDOW);
-  }
-  pPendingWindow = window;
-  if (window != NULL) {
-    write_cmd(APP_CMD_INIT_WINDOW);
-  }
-  while (pNativeWindow != pPendingWindow) {
-    pthread_cond_wait(&pCond, &pMutex);
-  }
-  pthread_mutex_unlock(&pMutex);
-}
-
-
-void Fl_Android_Activity::set_activity_state(int8_t cmd)
-{
-  pthread_mutex_lock(&pMutex);
-  write_cmd(cmd);
-  while (pActivityState != cmd) {
-    pthread_cond_wait(&pCond, &pMutex);
-  }
-  pthread_mutex_unlock(&pMutex);
-}
-
-
-void Fl_Android_Activity::close_activity()
-{
-  pthread_mutex_lock(&pMutex);
-  write_cmd(APP_CMD_DESTROY);
-  while (!pDestroyed) {
-    pthread_cond_wait(&pCond, &pMutex);
-  }
-  pthread_mutex_unlock(&pMutex);
-
-  close(pMsgReadPipe);
-  close(pMsgWritePipe);
-  pthread_cond_destroy(&pCond);
-  pthread_mutex_destroy(&pMutex);
-}
-
-
-// ---- Android Native Activity callbacks ----
-
-/**
- The rectangle in the window in which content should be placed has changed.
- */
-void Fl_Android_Activity::onContentRectChanged(ANativeActivity *activity, const ARect *rect)
-{
-  // TODO: implement me
-}
-
-/**
- The drawing window for this native activity needs to be redrawn. To avoid transient artifacts during screen changes (such resizing after rotation), applications should not return from this function until they have finished drawing their window in its current state.
- */
-void Fl_Android_Activity::onNativeWindowRedrawNeeded(ANativeActivity *activity, ANativeWindow *window)
-{
-  // TODO: implement me
-}
-
-/**
- The drawing window for this native activity has been resized. You should retrieve the new size from the window and ensure that your rendering in it now matches.
- */
-void Fl_Android_Activity::onNativeWindowResized(ANativeActivity *activity, ANativeWindow *window)
-{
-  // TODO: implement me
-}
-
-/**
- NativeActivity is being destroyed. See Java documentation for Activity.onDestroy() for more information.
- */
-void Fl_Android_Activity::onDestroy(ANativeActivity* activity)
-{
-  log_v("Destroy: %p\n", activity);
-  // FIXME: use the correct free()
-  close_activity();
-}
-
-/**
- NativeActivity has started. See Java documentation for Activity.onStart() for more information.
- */
-void Fl_Android_Activity::onStart(ANativeActivity* activity)
-{
-  log_v("Start: %p\n", activity);
-  set_activity_state(APP_CMD_START);
-}
-
-/**
- NativeActivity has resumed. See Java documentation for Activity.onResume() for more information.
- */
-void Fl_Android_Activity::onResume(ANativeActivity* activity)
-{
-  log_v("Resume: %p\n", activity);
-  set_activity_state(APP_CMD_RESUME);
-}
-
-/**
- Framework is asking NativeActivity to save its current instance state. See Java documentation for Activity.onSaveInstanceState() for more information. The returned pointer needs to be created with malloc(); the framework will call free() on it for you. You also must fill in outSize with the number of bytes in the allocation. Note that the saved state will be persisted, so it can not contain any active entities (pointers to memory, file descriptors, etc).
- */
-void *Fl_Android_Activity::onSaveInstanceState(ANativeActivity* activity, size_t* outLen)
-{
-  struct android_app* android_app = (struct android_app*)activity->instance;
-  void* savedState = NULL;
-
-  log_v("SaveInstanceState: %p\n", activity);
-  pthread_mutex_lock(&pMutex);
-  pStateSaved = 0;
-  write_cmd(APP_CMD_SAVE_STATE);
-  while (!pStateSaved) {
-    pthread_cond_wait(&pCond, &pMutex);
-  }
-
-  if (pSavedState != NULL) {
-    savedState = pSavedState;
-    *outLen = pSavedStateSize;
-    pSavedState = NULL;
-    pSavedStateSize = 0;
-  }
-
-  pthread_mutex_unlock(&pMutex);
-
-  return savedState;
-}
-
-/**
- NativeActivity has paused. See Java documentation for Activity.onPause() for more information.
- */
-void Fl_Android_Activity::onPause(ANativeActivity* activity)
-{
-  log_v("Pause: %p\n", activity);
-  set_activity_state(APP_CMD_PAUSE);
-}
-
-/**
- NativeActivity has stopped. See Java documentation for Activity.onStop() for more information.
- */
-void Fl_Android_Activity::onStop(ANativeActivity* activity)
-{
-  log_v("Stop: %p\n", activity);
-  set_activity_state(APP_CMD_STOP);
-}
-
-/**
- The current device AConfiguration has changed. The new configuration can be retrieved from assetManager.
- */
-void Fl_Android_Activity::onConfigurationChanged(ANativeActivity* activity)
-{
-  struct android_app* android_app = (struct android_app*)activity->instance;
-  log_v("ConfigurationChanged: %p\n", activity);
-  write_cmd(APP_CMD_CONFIG_CHANGED);
-}
-
-/**
- The system is running low on memory. Use this callback to release resources you do not need, to help the system avoid killing more important processes.
- */
-void Fl_Android_Activity::onLowMemory(ANativeActivity* activity)
-{
-  struct android_app* android_app = (struct android_app*)activity->instance;
-  log_v("LowMemory: %p\n", activity);
-  write_cmd(APP_CMD_LOW_MEMORY);
-}
-
-/**
- Focus has changed in this NativeActivity's window. This is often used, for example, to pause a game when it loses input focus.
- */
-void Fl_Android_Activity::onWindowFocusChanged(ANativeActivity* activity, int focused)
-{
-  log_v("WindowFocusChanged: %p -- %d\n", activity, focused);
-  write_cmd(focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS);
-}
-
-/**
- The drawing window for this native activity has been created. You can use the given native window object to start drawing.
- */
-void Fl_Android_Activity::onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window)
-{
-  log_v("NativeWindowCreated: %p -- %p\n", activity, window);
-  set_window(window);
-}
-
-/**
- The drawing window for this native activity is going to be destroyed. You MUST ensure that you do not touch the window object after returning from this function: in the common case of drawing to the window from another thread, that means the implementation of this callback must properly synchronize with the other thread to stop its drawing before returning from here.
- */
-void Fl_Android_Activity::onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window)
-{
-  log_v("NativeWindowDestroyed: %p -- %p\n", activity, window);
-  set_window(NULL);
-}
-
-/**
- The input queue for this native activity's window has been created. You can use the given input queue to start retrieving input events.
- */
-void Fl_Android_Activity::onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue)
-{
-  log_v("InputQueueCreated: %p -- %p\n", activity, queue);
-  set_input(queue);
-}
-
-/**
- The input queue for this native activity's window is being destroyed. You should no longer try to reference this object upon returning from this function.
- */
-void Fl_Android_Activity::onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue)
-{
-  log_v("InputQueueDestroyed: %p -- %p\n", activity, queue);
-  set_input(NULL);
-}
-
-/**
- Create a thread that will run our FLTK code and the required communications and locks.
- \param activity the interface to the Java end of Android
- \param savedState if this app is relaunched, this is a memory block with the state of the app when it was interrupted
- \param savedStateSize size of that block
- */
-void Fl_Android_Activity::create(ANativeActivity* activity, void* savedState,
-                                 size_t savedStateSize)
-{
-  static const char *FLTK = "FLTK";
-  activity->instance = (void*)FLTK;
-
-  set_activity(activity);
-  set_callbacks();
-
-  allocate_screen(); // TODO: we may need to change this to when the actual screen is allocated
-
-  pthread_mutex_init(&pMutex, NULL);
-  pthread_cond_init(&pCond, NULL);
-
-  if (savedState != NULL) {
-    pSavedState = malloc(savedStateSize);
-    pSavedStateSize = savedStateSize;
-    memcpy(pSavedState, savedState, savedStateSize);
-  }
-
-  int msgpipe[2];
-  if (pipe(msgpipe)) {
-    log_e("could not create pipe: %s", strerror(errno));
-    return;
-  }
-  pMsgReadPipe = msgpipe[0];
-  pMsgWritePipe = msgpipe[1];
-
-  pthread_attr_t attr;
-  pthread_attr_init(&attr);
-  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-  pthread_create(&pThread, &attr, thread_entry, 0L);
-
-  // Wait for thread to start.
-  pthread_mutex_lock(&pMutex);
-  while (!pRunning) {
-    pthread_cond_wait(&pCond, &pMutex);
-  }
-  pthread_mutex_unlock(&pMutex);
-}
-
-/**
- Set all callbacks from the Native Activity.
- */
-void Fl_Android_Activity::set_callbacks()
-{
-  ANativeActivityCallbacks *cb = pActivity->callbacks;
-  cb->onContentRectChanged = onContentRectChanged;
-  cb->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded;
-  cb->onNativeWindowResized = onNativeWindowResized;
-  cb->onDestroy = onDestroy;
-  cb->onStart = onStart;
-  cb->onResume = onResume;
-  cb->onSaveInstanceState = onSaveInstanceState;
-  cb->onPause = onPause;
-  cb->onStop = onStop;
-  cb->onConfigurationChanged = onConfigurationChanged;
-  cb->onLowMemory = onLowMemory;
-  cb->onWindowFocusChanged = onWindowFocusChanged;
-  cb->onNativeWindowCreated = onNativeWindowCreated;
-  cb->onNativeWindowDestroyed = onNativeWindowDestroyed;
-  cb->onInputQueueCreated = onInputQueueCreated;
-  cb->onInputQueueDestroyed = onInputQueueDestroyed;
-}
-
-/**
- This is the main entry point from the Android JavaVM into the native world.
- */
-JNIEXPORT void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize)
-{
-  // TODO: can we return an error message her is creation of the app failed?
-  Fl_Android_Activity::create(activity, savedState, savedStateSize);
-}
-
-
-// ---- Java Stuff -------------------------------------------------------------
-
-
-Fl_Android_Java::Fl_Android_Java()
-{
-  jint lResult;
-  jint lFlags = 0;
-
-  pJavaVM = Fl_Android_Application::get_activity()->vm;
-  pJNIEnv = Fl_Android_Application::get_activity()->env;
-
-  JavaVMAttachArgs lJavaVMAttachArgs = {
-          .version = JNI_VERSION_1_6,
-          .name = "NativeThread",
-          .group = nullptr
-  };
-
-  lResult = pJavaVM->AttachCurrentThread(&pJNIEnv, &lJavaVMAttachArgs);
-  if (lResult == JNI_ERR) return;
-
-  pNativeActivity = Fl_Android_Application::get_activity()->clazz;
-
-  pNativeActivityClass = env()->GetObjectClass(pNativeActivity);
-
-  pAttached = true;
-}
-
-
-Fl_Android_Java::~Fl_Android_Java()
-{
-  if (is_attached()) {
-    pJavaVM->DetachCurrentThread();
-  }
-}
diff --git src/drivers/Android/Fl_Android_Graphics_Clipping.H src/drivers/Android/Fl_Android_Graphics_Clipping.H
deleted file mode 100644
index dbec82f..0000000
--- src/drivers/Android/Fl_Android_Graphics_Clipping.H
+++ /dev/null
@@ -1,183 +0,0 @@
-//
-// Graphics regions and clipping for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_Android_Graphics_Clipping.H
- \brief Graphics regions and clipping for the Fast Light Tool Kit (FLTK).
- */
-
-#ifndef FL_ANDROID_GRAPHICS_CLIPPING_H
-#define FL_ANDROID_GRAPHICS_CLIPPING_H
-
-#include <FL/Fl_Graphics_Driver.H>
-#include <limits.h>
-
-
-class Fl_Android_Window_Driver;
-
-
-/**
- The Fl_Rect_Region describes a rectangular clipping region.
-
- Contrary to common FLTK convention, rectangles are stored with coordinates
- instead of their width and height to accelerate calculations. The discreet
- constructor however uses the old convention for convenience.
- */
-class Fl_Rect_Region
-{
-public:
-  enum Type {
-    EMPTY = 0, SAME, LESS, MORE, INFINITE
-  };
-
-  Fl_Rect_Region();
-  Fl_Rect_Region(int x, int y, int w, int h);
-  Fl_Rect_Region(const Fl_Rect_Region&);
-  Fl_Rect_Region(enum Type what);
-  virtual ~Fl_Rect_Region() { }
-
-  int x() const { return pLeft; }
-  int y() const { return pTop; }
-  int w() const { return pRight - pLeft; }
-  int h() const { return pBottom - pTop; }
-
-  int left() const { return pLeft; }
-  int top() const { return pTop; }
-  int right() const { return pRight; }
-  int bottom() const { return pBottom; }
-
-  bool is_empty() const;
-  bool is_infinite() const;
-
-  virtual void set_empty();
-  void set(int x, int y, int w, int h);
-  void set_ltrb(int l, int t, int r, int b);
-  virtual void set(const Fl_Rect_Region &r);
-  virtual int intersect_with(const Fl_Rect_Region &r);
-  void add_to_bbox(const Fl_Rect_Region &r);
-
-  virtual void print(const char*) const;
-
-protected:
-  int pLeft, pTop, pRight, pBottom;
-
-private:
-  Fl_Rect_Region&  operator = (const Fl_Rect_Region& other);
-};
-
-
-/**
- The Fl_Complex_Region represents a clipping region of any shape.
-
- This class is organized in a tree-like structure. If the region is
- rectangular, is_simple() returns 1 and the rectangle can be used just
- as in Fl_Rect_Region.
-
- If a more complex representation is needed, subregions are created which are
- guaranteed to lie within the bounding box of the current region. Subregions
- themselves can again contain sub-subregions to describe the entire clipping
- region, effectively creating a tree where the leafs contain the rectangles
- that together describe the clipping area.
-
- To make life easier, Fl_Complex_Region provides two types of iterator to
- travers the entire tree.
-
- 1. Fl_Complex_Region itself is compatible to C++11 range-based loops and
-    can bewalked simply by writing ``for (auto &&it: rgn) { ... }``.
-
- 2. Fl_Complex_Region provides an alternative iterator that loop only through
-    leafs that intersects with a given rectangle. The returned object
-    provides access to the readily clipped rectangle.
-
- \code
- Fl_Complex_Region rgn(something);
- for (auto &&it: rgn.iterate(Fl_Rect_Region(0, 0, 100, 100)) {
-    draw_something(it->rect());
- }
- \endcode
-
- */
-class Fl_Complex_Region : public Fl_Rect_Region
-{
-  class Iterator {
-  public:
-    Iterator(Fl_Complex_Region *r);
-    bool operator!= (const Iterator& other) const;
-    const Iterator& operator++ ();
-    Fl_Complex_Region *operator* () const;
-    Fl_Complex_Region *pRegion;
-  };
-
-  class Overlapping {
-    class OverlappingIterator {
-    public:
-      OverlappingIterator(Overlapping *ov);
-      bool operator!= (const OverlappingIterator& other) const;
-      const OverlappingIterator& operator++ ();
-      Overlapping *operator* () const;
-      Overlapping *pOv;
-    };
-  public:
-    Overlapping(Fl_Complex_Region *rgn, const Fl_Rect_Region &rect);
-    OverlappingIterator begin();
-    OverlappingIterator end();
-    Fl_Rect_Region &clipped_rect();
-    bool intersects();
-    bool find_intersecting();
-    bool find_next();
-    Fl_Complex_Region *pRegion;
-    Fl_Rect_Region pOriginalRect;
-    Fl_Rect_Region pClippedRect;
-  };
-
-public:
-  Fl_Complex_Region();
-  Fl_Complex_Region(const Fl_Rect_Region&);
-  virtual ~Fl_Complex_Region() override;
-  void delete_all_subregions();
-
-  virtual void set(const Fl_Rect_Region &r) override;
-  void set(const Fl_Complex_Region &r);
-  virtual void set_empty() override { delete pSubregion; pSubregion=0L; Fl_Rect_Region::set_empty(); }
-  Fl_Complex_Region *subregion() const { return pSubregion; }
-  Fl_Complex_Region *next() const { return pNext; }
-  Fl_Complex_Region *parent() const { return pParent; }
-  char is_simple() const { return pSubregion==0; }
-  char is_complex() const { return pSubregion!=0; }
-
-  virtual int intersect_with(const Fl_Rect_Region &r) override;
-  int subtract(const Fl_Rect_Region &r);
-
-  virtual void print(const char*) const override;
-
-  Iterator begin();
-  Iterator end();
-
-  Overlapping overlapping(const Fl_Rect_Region &r);
-
-protected:
-  void print_data(int indent) const;
-  int subtract_smaller_region(const Fl_Rect_Region &r);
-  Fl_Complex_Region *add_subregion();
-  void compress();
-
-  Fl_Complex_Region *pSubregion = 0L;
-  Fl_Complex_Region *pParent = 0L;
-  Fl_Complex_Region *pNext = 0L;
-};
-
-
-#endif // FL_ANDROID_GRAPHICS_CLIPPING_H
diff --git src/drivers/Android/Fl_Android_Graphics_Clipping.cxx src/drivers/Android/Fl_Android_Graphics_Clipping.cxx
deleted file mode 100644
index 3f14319..0000000
--- src/drivers/Android/Fl_Android_Graphics_Clipping.cxx
+++ /dev/null
@@ -1,808 +0,0 @@
-//
-// Clipping region routines for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-
-#include <config.h>
-#include "Fl_Android_Graphics_Driver.H"
-#include "Fl_Android_Application.H"
-#include <FL/platform.H>
-
-
-/**
- Create an empty clipping region.
- */
-Fl_Rect_Region::Fl_Rect_Region() :
-        pLeft(0), pTop(0), pRight(0), pBottom(0)
-{
-}
-
-/**
- Create a clipping region based on position and size.
- \param x, y position
- \param w, h size
- */
-Fl_Rect_Region::Fl_Rect_Region(int x, int y, int w, int h) :
-        pLeft(x), pTop(y), pRight(x+w), pBottom(y+h)
-{
-}
-
-/**
- Clone a clipping rectangle.
- */
-Fl_Rect_Region::Fl_Rect_Region(const Fl_Rect_Region &r) :
-        pLeft(r.pLeft), pTop(r.pTop),
-        pRight(r.pRight), pBottom(r.pBottom)
-{
-}
-
-/**
- Clone a clipping rectangle.
- The pointer can be NULL if an empty rectangle is needed.
- */
-Fl_Rect_Region::Fl_Rect_Region(enum Type what)
-{
-  if (what==INFINITE) {
-    pLeft = pTop = INT_MIN;
-    pRight = pBottom = INT_MAX;
-  } else {
-    pLeft = pTop = pRight = pBottom = 0;
-  }
-}
-
-/**
- If the rectangle has no width or height, it's considered empty.
- \return true, if everything will be clipped and there is nothing to draw
- */
-bool Fl_Rect_Region::is_empty() const
-{
-  return (pRight<=pLeft || pBottom<=pTop);
-}
-
-/**
- Return true, if the rectangle is of unlimited size and nothing should be clipped.
- \return treu, if there is no clipping
- */
-bool Fl_Rect_Region::is_infinite() const
-{
-  return (pLeft==INT_MIN);
-}
-
-/**
- Set an empty clipping rect.
- */
-void Fl_Rect_Region::set_empty()
-{
-  pLeft = pTop = pRight = pBottom = 0;
-}
-
-/**
- Set a clipping rect using position and size
- \param x, y position
- \param w, h size
- */
-void Fl_Rect_Region::set(int x, int y, int w, int h)
-{
-  pLeft = x;
-  pTop = y;
-  pRight = x+w;
-  pBottom = y+h;
-}
-
-/**
- Set a rectangle using the coordinates of two points, top left and bottom right.
- \param l, t left and top coordinate
- \param r, b right and bottom coordinate
- */
-void Fl_Rect_Region::set_ltrb(int l, int t, int r, int b)
-{
-  pLeft = l;
-  pTop = t;
-  pRight = r;
-  pBottom = b;
-}
-
-/**
- Copy the corrdinates from another rect.
- \param r source rectangle
- */
-void Fl_Rect_Region::set(const Fl_Rect_Region &r)
-{
-  pLeft = r.pLeft;
-  pTop = r.pTop;
-  pRight = r.pRight;
-  pBottom = r.pBottom;
-}
-
-/**
- Set this rect to be the intersecting area between the original rect and another rect.
- \param r another rectangular region
- \return EMPTY, if rectangles are not intersecting, SAME if this and rect are
-      equal, LESS if the new rect is smaller than the original rect
- */
-int Fl_Rect_Region::intersect_with(const Fl_Rect_Region &r)
-{
-  if (is_empty()) {
-    return EMPTY;
-  }
-  if (r.is_empty()) {
-    set_empty();
-    return EMPTY;
-  }
-  bool same = true;
-  if ( pLeft != r.pLeft ) {
-    same = false;
-    if ( r.pLeft > pLeft ) pLeft = r.pLeft;
-  }
-  if ( pTop != r.pTop ) {
-    same = false;
-    if ( r.pTop > pTop ) pTop = r.pTop;
-  }
-  if ( pRight != r.pRight ) {
-    same = false;
-    if ( r.pRight < pRight ) pRight = r.pRight;
-  }
-  if ( pBottom != r.pBottom ) {
-    same = false;
-    if ( r.pBottom < pBottom ) pBottom = r.pBottom;
-  }
-  if (same)
-    return SAME;
-  if (is_empty())
-    return EMPTY;
-  return LESS;
-}
-
-/**
- Use rectangle as a bounding box and add the outline of another rect.
- */
-void Fl_Rect_Region::add_to_bbox(const Fl_Rect_Region &r)
-{
-  if (is_empty()) return;
-  if (r.pLeft<pLeft) pLeft = r.pLeft;
-  if (r.pTop<pTop) pTop = r.pTop;
-  if (r.pRight>pRight) pRight = r.pRight;
-  if (r.pBottom>pBottom) pBottom = r.pBottom;
-}
-
-/**
- Print the coordinates of the rect to the log.
- \param label some text that is logged with this message.
- */
-void Fl_Rect_Region::print(const char *label) const
-{
-  Fl_Android_Application::log_i("---> Fl_Rect_Region: %s", label);
-  Fl_Android_Application::log_i("Rect l:%d t:%d r:%d b:%d", left(), top(), right(), bottom());
-}
-
-// =============================================================================
-
-/**
- Create an empty complex region.
- */
-Fl_Complex_Region::Fl_Complex_Region() :
-        Fl_Rect_Region()
-{
-}
-
-/**
- Create a complex region with the same bounds as the give rect.
- \param r region size
- */
-Fl_Complex_Region::Fl_Complex_Region(const Fl_Rect_Region &r) :
-        Fl_Rect_Region(r)
-{
-}
-
-/**
- Delete this region, all subregions recursively, and all following regions.
- */
-Fl_Complex_Region::~Fl_Complex_Region()
-{
-  delete_all_subregions();
-}
-
-/**
- Delete all subregions of this region.
- The pSubregion pointer should always be seen as a list of subregions, rather
- than a single region and some pNext pointer. So everything we do, we should
- probably do for every object in that list.
-
- Also note, that the top level region never has pNext pointing to anything.
- */
-void Fl_Complex_Region::delete_all_subregions()
-{
-  // Do NOT delete the chain in pNext! The caller has to that job.
-  // A top-level coplex region has pNext always set to NULL, and it does
-  // delete all subregions chained via the subregion pNext.
-  while (pSubregion) {
-    Fl_Complex_Region *rgn = pSubregion;
-    pSubregion = rgn->pNext;
-    delete rgn; rgn = 0;
-  }
-}
-
-/**
- Print the entire content of this region recursively.
- */
-void Fl_Complex_Region::print(const char *label) const
-{
-  Fl_Android_Application::log_i("---> Fl_Complex_Region: %s", label);
-  print_data(0);
-}
-
-/*
- Print the rectangular data only.
- */
-void Fl_Complex_Region::print_data(int indent) const
-{
-  static const char *space = "                ";
-  if (pSubregion) {
-    Fl_Android_Application::log_i("%sBBox l:%d t:%d r:%d b:%d", space+16-indent, left(), top(), right(), bottom());
-    pSubregion->print_data(indent+1);
-  } else {
-    Fl_Android_Application::log_i("%sRect l:%d t:%d r:%d b:%d", space+16-indent, left(), top(), right(), bottom());
-  }
-  if (pNext) {
-    pNext->print_data(indent);
-  }
-}
-
-/**
- Replace this region with a rectangle.
- \param r the source rectangle
- */
-void Fl_Complex_Region::set(const Fl_Rect_Region &r)
-{
-  Fl_Rect_Region::set(r);
-  delete_all_subregions();
-}
-
-/**
- Replace this region with a copy of another region.
- This operation can be expensive for very complex regions.
- \param r the source region
- */
-void Fl_Complex_Region::set(const Fl_Complex_Region &r)
-{
-  Fl_Rect_Region::set((const Fl_Rect_Region&)r);
-  delete_all_subregions();
-
-  Fl_Complex_Region *srcRgn = r.pSubregion;
-  if (srcRgn) {
-    // copy first subregion
-    Fl_Complex_Region *dstRgn = pSubregion = new Fl_Complex_Region();
-    pSubregion->set(*srcRgn);
-    // copy rest of list
-    while (srcRgn) {
-      dstRgn->pNext = new Fl_Complex_Region();
-      dstRgn = dstRgn->next();
-      dstRgn->set(*srcRgn);
-      srcRgn = srcRgn->next();
-    }
-  }
-}
-
-/**
- Set this region to the intersection of the original region and some rect.
- \param r intersect with this rectangle
- \return EMPTY, SAME, LESS
- */
-int Fl_Complex_Region::intersect_with(const Fl_Rect_Region &r)
-{
-  if (pSubregion) {
-    Fl_Complex_Region *rgn = pSubregion;
-    while (rgn) {
-      rgn->intersect_with(r);
-      rgn = rgn->next();
-    }
-    compress();
-  } else {
-    Fl_Rect_Region::intersect_with(r);
-  }
-  return 0;
-}
-
-/**
- Subtract a rectangular region from this region.
- \param r the rect that we want removed
- \return currently 0, but could return something meaningful
- */
-int Fl_Complex_Region::subtract(const Fl_Rect_Region &r)
-{
-  if (pSubregion) {
-    Fl_Complex_Region *rgn = pSubregion;
-    while (rgn) {
-      rgn->subtract(r);
-      rgn = rgn->next();
-    }
-    compress();
-  } else {
-    // Check if we overlap at all
-    Fl_Rect_Region s(r);
-    int intersects = s.intersect_with(*this);
-    switch (intersects) {
-      case EMPTY:
-        // nothing to do
-        break;
-      case SAME:
-        set_empty(); // Will be deleted by compress()
-        break;
-      case LESS:
-        // split this rect into 1, 2, 3, or 4 new ones
-        subtract_smaller_region(s);
-        break;
-      default:
-        Fl_Android_Application::log_e("Invalid case in %s:%d", __FUNCTION__, __LINE__);
-        break;
-    }
-    if (pSubregion) compress(); // because intersecting this may have created subregions
-  }
-  return 0;
-}
-
-/**
- Compress the subregion of this region if possible and update the bounding
- box of this region.
-
- Does not recurse down the tree!
- */
-void Fl_Complex_Region::compress()
-{
-  // Can't compress anything that does not have a subregion
-  if (!pSubregion) return;
-
-  // remove all empty regions, because the really don't add anything (literally)
-  //  print("Compress");
-  Fl_Complex_Region *rgn = pSubregion;
-  while (rgn && rgn->is_empty()) {
-    pSubregion = rgn->next();
-    delete rgn; rgn = pSubregion;
-  }
-  if (!pSubregion) return;
-
-  rgn = pSubregion;
-  while (rgn) {
-    while (rgn->pNext && rgn->pNext->is_empty()) {
-      Fl_Complex_Region *nextNext = rgn->pNext->pNext;
-      delete rgn->pNext; rgn->pNext = nextNext;
-    }
-    rgn = rgn->next();
-  }
-
-  // find rectangles that can be merged into a single new rectangle
-  // (Too much work for much too little benefit)
-
-  // if there is only a single subregion left, merge it into this region
-  if (pSubregion->pNext==nullptr) {
-    set((Fl_Rect_Region&)*pSubregion); // deletes subregion for us
-  }
-  if (!pSubregion) return;
-
-  // finally, update the boudning box
-  Fl_Rect_Region::set((Fl_Rect_Region&)*pSubregion);
-  for (rgn=pSubregion->pNext; rgn; rgn=rgn->pNext) {
-    add_to_bbox(*rgn);
-  }
-}
-
-/**
- Subtract a smaller rect from a larger rect, potentially creating four new rectangles.
- This assumes that the calling region is NOT complex.
- \param r subtract the area of this rectangle; r must fit within ``this``.
- \return currently 0, but this may change
- */
-int Fl_Complex_Region::subtract_smaller_region(const Fl_Rect_Region &r)
-{
-  // subtract a smaller rect from a larger rect and create subrects as needed
-  // if there is only one single coordinate different, we can reuse this container
-  if (left()==r.left() && top()==r.top() && right()==r.right() && bottom()==r.bottom()) {
-    // this should not happen
-    set_empty();
-  } else if (left()!=r.left() && top()==r.top() && right()==r.right() && bottom()==r.bottom()) {
-    pRight = r.left();
-  } else if (left()==r.left() && top()!=r.top() && right()==r.right() && bottom()==r.bottom()) {
-    pBottom = r.top();
-  } else if (left()==r.left() && top()==r.top() && right()!=r.right() && bottom()==r.bottom()) {
-    pLeft = r.right();
-  } else if (left()==r.left() && top()==r.top() && right()==r.right() && bottom()!=r.bottom()) {
-    pTop = r.bottom();
-  } else {
-    // create multiple regions
-    if (pTop!=r.top()) {
-      Fl_Complex_Region *s = add_subregion();
-      s->set_ltrb(pLeft, pTop, pRight, r.top());
-    }
-    if (pBottom!=r.bottom()) {
-      Fl_Complex_Region *s = add_subregion();
-      s->set_ltrb(pLeft, r.bottom(), pRight, pBottom);
-    }
-    if (pLeft!=r.left()) {
-      Fl_Complex_Region *s = add_subregion();
-      s->set_ltrb(pLeft, r.top(), r.left(), r.bottom());
-    }
-    if (pRight!=r.right()) {
-      Fl_Complex_Region *s = add_subregion();
-      s->set_ltrb(r.right(), r.top(), pRight, r.bottom());
-    }
-  }
-  return 0;
-}
-
-/**
- Add an empty subregion to the current region.
- \return a pointer to the newly created region.
- */
-Fl_Complex_Region *Fl_Complex_Region::add_subregion()
-{
-  Fl_Complex_Region *r = new Fl_Complex_Region();
-  r->pParent = this;
-  r->pNext = pSubregion;
-  pSubregion = r;
-  return r;
-}
-
-
-// -----------------------------------------------------------------------------
-
-/**
- Returns an iterator object for loops that traverse the entire region tree.
- C++11 interface to range-based loops.
- \return Iterator pointing to the first element.
- */
-Fl_Complex_Region::Iterator Fl_Complex_Region::begin()
-{
-  return Iterator(this);
-}
-
-/**
- Returns an interator object to mark the end of travesing the tree.
- C++11 interface to range-based loops.
- \return
- */
-Fl_Complex_Region::Iterator Fl_Complex_Region::end()
-{
-  return Iterator(nullptr);
-}
-
-/**
- Create an iterator to walk the entire tree.
- \param r Iterate through this region, r must not have a parent().
- */
-Fl_Complex_Region::Iterator::Iterator(Fl_Complex_Region *r) :
-        pRegion(r)
-{
-}
-
-/**
- Compare two iterators.
- C++11 needs this to find the end of a for loop.
- \param other
- \return
- */
-bool Fl_Complex_Region::Iterator::operator!=(const Iterator &other) const
-{
-  return pRegion != other.pRegion;
-}
-
-/**
- Set the iterator to the next object in the tree, down first.
- C++11 needs this to iterate in a for loop.
- \return
- */
-const Fl_Complex_Region::Iterator &Fl_Complex_Region::Iterator::operator++()
-{
-  if (pRegion->subregion()) {
-    pRegion = pRegion->subregion();
-  } else if (pRegion->next()) {
-    pRegion = pRegion->next();
-  } else {
-    pRegion = pRegion->parent();
-  }
-  return *this;
-}
-
-/**
- Return the current object while iterating through the tree.
- \return
- */
-Fl_Complex_Region *Fl_Complex_Region::Iterator::operator*() const
-{
-  return pRegion;
-}
-
-// -----------------------------------------------------------------------------
-
-/**
- Use this to iterate through a region, hitting only nodes that intersect with this rect.
- \param r find all parts of the region that intersect with this rect.
- \return an object that can be used in range-based for loops in C++11.
- */
-Fl_Complex_Region::Overlapping Fl_Complex_Region::overlapping(const Fl_Rect_Region &r)
-{
-  return Overlapping(this, r);
-}
-
-/**
- A helper object for iterating through a region, finding only overlapping rects.
- \param rgn
- \param rect
- */
-Fl_Complex_Region::Overlapping::Overlapping(Fl_Complex_Region *rgn,
-                                            const Fl_Rect_Region &rect) :
-        pRegion(rgn),
-        pOriginalRect(rect),
-        pClippedRect(rect)
-{
-}
-
-/**
- Return an itertor for the first clipping rectangle inside the region.
- \return
- */
-Fl_Complex_Region::Overlapping::OverlappingIterator Fl_Complex_Region::Overlapping::begin()
-{
-  find_intersecting();
-  return OverlappingIterator(this);
-}
-
-/**
- Return an iterator for the end of forward iteration.
- \return
- */
-Fl_Complex_Region::Overlapping::OverlappingIterator Fl_Complex_Region::Overlapping::end()
-{
-  return OverlappingIterator(nullptr);
-}
-
-/**
- Return the result of intersecting the original rect with this iterator.
- \return
- */
-Fl_Rect_Region &Fl_Complex_Region::Overlapping::clipped_rect()
-{
-  return pClippedRect;
-}
-
-/**
- Store the intersection in pClippedRect and return true if there was an intersection.
- \return
- */
-bool Fl_Complex_Region::Overlapping::intersects()
-{
-  return (pClippedRect.intersect_with(*pRegion) != EMPTY);
-}
-
-/**
- Find the next element in the tree that actually intersects with the initial rect.
- Starting the search at the current object, NOT the next object.
- \return
- */
-bool Fl_Complex_Region::Overlapping::find_intersecting()
-{
-  for (;;) {
-    if (!pRegion) return false;
-    pClippedRect.set(pOriginalRect);
-    if (intersects()) {
-      if (!pRegion->subregion()) {
-        return true;
-      } else {
-        pRegion = pRegion->subregion();
-      }
-    } else {
-      find_next();
-    }
-  }
-}
-
-/**
- Find the next object in the tree, complex, simple, intersecting or not.
- \return
- */
-bool Fl_Complex_Region::Overlapping::find_next()
-{
-  if (pRegion->subregion()) {
-    pRegion = pRegion->subregion();
-  } else if (pRegion->next()) {
-    pRegion = pRegion->next();
-  } else {
-    pRegion = pRegion->parent(); // can be NULL
-  }
-  return (pRegion != nullptr);
-}
-
-// -----------------------------------------------------------------------------
-
-/**
- Create the actual iterator for finding true clipping rects.
- \see Fl_Complex_Region::Overlapping
- \param ov
- */
-Fl_Complex_Region::Overlapping::OverlappingIterator::OverlappingIterator(
-        Overlapping *ov) :
-        pOv(ov)
-{
-}
-
-/**
- Compare two iterator.
- This is used by C++11 range-based for loops to find the end of the range.
- \param other
- \return
- */
-bool Fl_Complex_Region::Overlapping::OverlappingIterator::operator!=(
-        const OverlappingIterator &other) const
-{
-  auto thisRegion = pOv ? pOv->pRegion : nullptr;
-  auto otherRegion = other.pOv ? other.pOv->pRegion : nullptr;
-  return thisRegion != otherRegion;
-}
-
-/**
- Wrapper to find and set the next intersecting rectangle.
- \see Fl_Complex_Region::Overlapping::find_intersecting
- \see Fl_Complex_Region::Overlapping::find_next
- \return
- */
-const Fl_Complex_Region::Overlapping::OverlappingIterator &
-Fl_Complex_Region::Overlapping::OverlappingIterator::operator++()
-{
-  pOv->find_next();
-  if (pOv->pRegion)
-    pOv->find_intersecting();
-  return *this;
-}
-
-/**
- Return the Fl_Complex_Region::Overlapping state for this iterator.
- This gives the user access to the current rectangular fragment of
- the clipping region.
- \return
- */
-Fl_Complex_Region::Overlapping *
-Fl_Complex_Region::Overlapping::OverlappingIterator::operator*() const
-{
-  return pOv;
-}
-
-// =============================================================================
-
-
-void Fl_Android_Graphics_Driver::restore_clip()
-{
-  fl_clip_state_number++;
-
-  // find the current user clipping rectangle
-  Fl_Region b = rstack[rstackptr]; // Fl_Region is a pointer to Fl_Rect_Region
-  if (b) {
-    if (b->is_empty()) {
-      // if this is an empty region, the intersection is always empty as well
-      pClippingRegion.set_empty();
-    } else {
-      // if there is a region, copy the full window region
-      pClippingRegion.set(pDesktopWindowRegion);
-      if (!b->is_infinite()) {
-        // if the rect has dimensions, calculate the intersection
-        pClippingRegion.intersect_with(*b);
-      }
-    }
-  } else {
-    // no rect? Just copy the window region
-    pClippingRegion.set(pDesktopWindowRegion);
-  }
-}
-
-
-void Fl_Android_Graphics_Driver::clip_region(Fl_Region r)
-{
-  Fl_Region oldr = rstack[rstackptr];
-  if (oldr)
-    ::free(oldr);
-  rstack[rstackptr] = r;
-  restore_clip();
-}
-
-
-Fl_Region Fl_Android_Graphics_Driver::clip_region()
-{
-  return rstack[rstackptr];
-}
-
-
-void Fl_Android_Graphics_Driver::push_clip(int x, int y, int w, int h)
-{
-  Fl_Region r;
-  if (w > 0 && h > 0) {
-    r = new Fl_Rect_Region(x, y, w, h);
-    Fl_Region current = rstack[rstackptr];
-    if (current) {
-      r->intersect_with(*current);
-    }
-  } else { // make empty clip region:
-    r = new Fl_Rect_Region();
-  }
-  if (rstackptr < region_stack_max) rstack[++rstackptr] = r;
-  else Fl::warning("Fl_Android_Graphics_Driver::push_clip: clip stack overflow!\n");
-  restore_clip();
-}
-
-
-void Fl_Android_Graphics_Driver::push_no_clip()
-{
-  if (rstackptr < region_stack_max) rstack[++rstackptr] = 0;
-  else Fl::warning("Fl_Android_Graphics_Driver::push_no_clip: clip stack overflow!\n");
-  restore_clip();
-}
-
-
-void Fl_Android_Graphics_Driver::pop_clip()
-{
-  if (rstackptr > 0) {
-    Fl_Region oldr = rstack[rstackptr--];
-    if (oldr)
-      ::free(oldr);
-  } else Fl::warning("Fl_Android_Graphics_Driver::pop_clip: clip stack underflow!\n");
-  restore_clip();
-}
-
-/*
- Intersects the rectangle with the current clip region and returns the
- bounding box of the result.
-
- Returns non-zero if the resulting rectangle is different to the original.
- This can be used to limit the necessary drawing to a rectangle.
- \p W and \p H are set to zero if the rectangle is completely outside the region.
- \param[in] x,y,w,h position and size of rectangle
- \param[out] X,Y,W,H position and size of resulting bounding box.
- \returns Non-zero if the resulting rectangle is different to the original.
- */
-int Fl_Android_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H)
-{
-  Fl_Region r = rstack[rstackptr];
-  if (r) {
-    Fl_Rect_Region a(x, y, w, h);
-    int ret = a.intersect_with(*r);
-    X = a.x();
-    Y = a.y();
-    W = a.w();
-    H = a.h();
-    return (ret!=Fl_Rect_Region::SAME);
-  } else {
-    X = x; Y = y; W = w; H = h;
-    return 0;
-  }
-}
-
-/*
- Does the rectangle intersect the current clip region?
- \param[in] x,y,w,h position and size of rectangle
- \returns non-zero if any of the rectangle intersects the current clip
- region. If this returns 0 you don't have to draw the object.
-
- \note
- Under X this returns 2 if the rectangle is partially clipped,
- and 1 if it is entirely inside the clip region.
- */
-int Fl_Android_Graphics_Driver::not_clipped(int x, int y, int w, int h)
-{
-  if (w <= 0 || h <= 0) return 0;
-  Fl_Region r = rstack[rstackptr];
-  if (r) {
-    Fl_Rect_Region a(x, y, w, h); // return 0 for empty, 1 for same, 2 if intersecting
-    return a.intersect_with(*r);
-  } else {
-    return 1;
-  }
-}
diff --git src/drivers/Android/Fl_Android_Graphics_Driver.H src/drivers/Android/Fl_Android_Graphics_Driver.H
deleted file mode 100644
index 1c54a0f..0000000
--- src/drivers/Android/Fl_Android_Graphics_Driver.H
+++ /dev/null
@@ -1,352 +0,0 @@
-//
-// Definition of classes Fl_Graphics_Driver, Fl_Surface_Device, Fl_Display_Device
-// for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_Android_Graphics_Driver.H
- \brief Definition of Android graphics driver.
- */
-
-#ifndef FL_ANDROID_GRAPHICS_DRIVER_H
-#define FL_ANDROID_GRAPHICS_DRIVER_H
-
-#include <FL/Fl_Graphics_Driver.H>
-#include "Fl_Android_Graphics_Clipping.H"
-#include "Fl_Android_Graphics_Font.H"
-#include <limits.h>
-
-
-class Fl_Android_Window_Driver;
-class Fl_Android_Bytemap;
-class Fl_Android_565A_Map;
-
-/**
-  \brief The Windows-specific graphics driver class.
-
-  This class is implemented only on the Windows platform.
-*/
-class FL_EXPORT Fl_Android_Graphics_Driver : public Fl_Graphics_Driver
-{
-  // easy access to the super class
-  typedef Fl_Graphics_Driver super;
-
-protected:
-  class Vertex; // see below
-
-  // --- this is a copy of Fl_Graphics_Driver ----------------------------------
-  // - use this to find unimplementet calls in the derived driver
-  // - excluded by #if/#endif means that we have not implemneted this yet
-  // - methods marked with // super: use the implemnetation of the super class
-  // - virtual ... override functions are implemented for Android
-private:
-  virtual void draw_fixed(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy) override;
-  virtual void draw_fixed(Fl_Pixmap * pxm,int XP, int YP, int WP, int HP, int cx, int cy) override;
-  virtual void draw_fixed(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) override;
-  // some platforms may need to reimplement this
-  // This is called from the surface device, see: end_current()
-  // super: virtual void set_current_();
-protected:
-  /** Sets the current value of the scaling factor */
-  // super: virtual void scale(float f) { scale_ = f; } // we do not support any scaling at this point
-protected:
-  // set fl_gc, which we do not use in the Android port at this point
-  // super: virtual void global_gc();
-  /** Support function for Fl_Pixmap drawing */
-  virtual void cache(Fl_Pixmap *img) override;
-  /** Support function for Fl_Bitmap drawing */
-  virtual void cache(Fl_Bitmap *img) override;
-  virtual void cache(Fl_RGB_Image *img) override;
-  /** Support function for Fl_RGB_Image drawing */
-  virtual void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_) override;
-  // --- implementation is in src/drivers/xxx/Fl_xxx_Graphics_Driver_image.cxx
-  /** see fl_draw_image(const uchar* buf, int X,int Y,int W,int H, int D, int L) */
-  virtual void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0) override;
-  /** see fl_draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D, int L) */
-  virtual void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0) override;
-  /** see fl_draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D) */
-  virtual void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3) override;
-  /** see fl_draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D) */
-  virtual void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1) override;
-#if 0
-  // TODO: where are begine_, end_, create_, and delete_offscreen? Answer: Fl_Image_Surface - you know what to do!
-  virtual void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
-  /** Support function for image drawing */
-  // TODO: these seem to be only needed if FL_Image and Fl_Pixmap store alpha values seperatley.
-  virtual Fl_Bitmask create_bitmask(int w, int h, const uchar *array) {return 0; }
-#endif
-  // Support function for image drawing
-  virtual void uncache_pixmap(fl_uintptr_t p) override;
-  // Support function for image drawing
-  virtual void delete_bitmask(Fl_Bitmask bm) override;
-public:
-  /** Constructor, C++11 initialises member variables in-line */
-  Fl_Android_Graphics_Driver();
-  /** destructor */
-  virtual ~Fl_Android_Graphics_Driver() override;
-  /** Return whether the graphics driver can do alpha blending */
-  virtual char can_do_alpha_blending() override { return 0; }
-  // --- implementation is in src/fl_rect.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_rect.cxx
-  /** see fl_point() */
-  virtual void point(int x, int y) override;
-  /** see fl_rect() */
-  virtual void rect(int x, int y, int w, int h) override;
-  // super: virtual void focus_rect(int x, int y, int w, int h);
-  /** see fl_rectf() */
-  virtual void rectf(int x, int y, int w, int h) override;
-  /** see fl_line(int, int, int, int) */
-  virtual void line(int x, int y, int x1, int y1) override;
-  /** see fl_line(int, int, int, int, int, int) */
-  virtual void line(int x, int y, int x1, int y1, int x2, int y2) override;
-  /** see fl_xyline(int, int, int) */
-  virtual void xyline(int x, int y, int x1) override;
-  /** see fl_xyline(int, int, int, int) */
-  virtual void xyline(int x, int y, int x1, int y2) override;
-  /** see fl_xyline(int, int, int, int, int) */
-  virtual void xyline(int x, int y, int x1, int y2, int x3) override;
-  /** see fl_yxline(int, int, int) */
-  virtual void yxline(int x, int y, int y1) override;
-  /** see fl_yxline(int, int, int, int) */
-  virtual void yxline(int x, int y, int y1, int x2) override;
-  /** see fl_yxline(int, int, int, int, int) */
-  virtual void yxline(int x, int y, int y1, int x2, int y3) override;
-  /** see fl_loop(int, int, int, int, int, int) */
-  virtual void loop(int x0, int y0, int x1, int y1, int x2, int y2) override;
-  /** see fl_loop(int, int, int, int, int, int, int, int) */
-  virtual void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) override;
-  /** see fl_polygon(int, int, int, int, int, int) */
-  virtual void polygon(int x0, int y0, int x1, int y1, int x2, int y2) override;
-  /** see fl_polygon(int, int, int, int, int, int, int, int) */
-  virtual void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) override;
-  // --- clipping
-  /** see fl_push_clip() */
-  virtual void push_clip(int x, int y, int w, int h) override;
-  /** see fl_clip_box() */
-  virtual int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) override;
-  /** see fl_not_clipped() */
-  virtual int not_clipped(int x, int y, int w, int h) override;
-  /** see fl_push_no_clip() */
-  virtual void push_no_clip() override;
-  /** see fl_pop_clip() */
-  virtual void pop_clip() override;
-  virtual Fl_Region clip_region() override;
-  virtual void clip_region(Fl_Region r) override;
-  virtual void restore_clip() override;
-  // --- implementation is in src/fl_vertex.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_vertex.cxx
-  // super: virtual void push_matrix();
-  // super: virtual void pop_matrix();
-  // super: virtual void mult_matrix(double a, double b, double c, double d, double x, double y);
-  // super: virtual void rotate(double d);
-  // super: virtual void translate(double x,double y);
-  virtual void begin_points() override;
-  virtual void begin_line() override;
-  virtual void begin_loop() override;
-  virtual void begin_polygon() override;
-  virtual void begin_complex_polygon() override;
-  // super: virtual double transform_x(double x, double y);
-  // super: virtual double transform_y(double x, double y);
-  // super: virtual double transform_dx(double x, double y);
-  // super: virtual double transform_dy(double x, double y);
-  /** see fl_transformed_vertex() */
-  virtual void transformed_vertex(double xf, double yf) override;
-  /** see fl_vertex() */
-  virtual void vertex(double x, double y) override;
-  /** see fl_end_points() */
-  virtual void end_points() override;
-  /** see fl_end_line() */
-  virtual void end_line() override;
-  /** see fl_end_loop() */
-  virtual void end_loop() override;
-  /** see fl_end_polygon() */
-  virtual void end_polygon() override;
-  /** see fl_end_complex_polygon() */
-  virtual void end_complex_polygon() override;
-  /** see fl_gap() */
-  virtual void gap() override;
-  /** see fl_circle() */
-  virtual void circle(double x, double y, double r) override;
-  // --- implementation is in src/fl_arc.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_arc.cxx if needed
-  virtual void arc(double x, double y, double r, double start, double end) override { super::arc(x, y, r, start, end); }
-  // --- implementation is in src/fl_arci.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_arci.cxx
-  /** see fl_arc(int x, int y, int w, int h, double a1, double a2) */
-  virtual void arc(int x, int y, int w, int h, double a1, double a2) override;
-  /** see fl_pie() */
-  virtual void pie(int x, int y, int w, int h, double a1, double a2) override;
-  // --- implementation is in src/fl_curve.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_curve.cxx if needed
-  // super: virtual void curve(double X0, double Y0, double X1, double Y1, double X2, double Y2, double X3, double Y3);
-  // --- implementation is in src/fl_line_style.cxx which includes src/cfg_gfx/xxx_line_style.cxx
-  // TODO: line_style()
-  /** see fl_line_style() */
-  virtual void line_style(int style, int width=0, char* dashes=0) override;
-  // --- implementation is in src/fl_color.cxx which includes src/cfg_gfx/xxx_color.cxx
-  /** see fl_color(Fl_Color) */
-  virtual void color(Fl_Color c) override { super::color(c); }
-  virtual void set_color(Fl_Color i, unsigned int c) override;
-  // super: virtual void free_color(Fl_Color i, int overlay);
-  /** see fl_color(void) */
-  virtual Fl_Color color() override { return super::color(); }
-  /** see fl_color(uchar, uchar, uchar) */
-  virtual void color(uchar r, uchar g, uchar b) override;
-  /** see fl_draw(const char *str, int n, int x, int y) */
-  virtual void draw(const char *str, int n, int x, int y) override;
-  /** Draw the first \p n bytes of the string \p str starting at position \p x , \p y */
-  // super: virtual void draw(const char *str, int n, float x, float y);
-  /** see fl_draw(int angle, const char *str, int n, int x, int y) */
-  // TODO: drawing text at an angle is not supported
-  virtual void draw(int angle, const char *str, int n, int x, int y) override { draw(str, n, x, y); }
-  /** see fl_rtl_draw(const char *str, int n, int x, int y) */
-  // TODO: drawing text right-to-left is not supported
-  virtual void rtl_draw(const char *str, int n, int x, int y) override { draw(str, n, x, y); }
-  /** Returns non-zero if the graphics driver possesses the \p feature */
-  // super: virtual int has_feature(driver_feature feature)
-  /** see fl_font(Fl_Font, Fl_Fontsize) */
-  virtual void font(Fl_Font face, Fl_Fontsize fsize) override;
-  /** see fl_font(void) */
-  virtual Fl_Font font() override { return super::font(); }
-  /** Return the current font size */
-  virtual Fl_Fontsize size() override;
-  /** Compute the width of the first \p n bytes of the string \p str if drawn with current font */
-  virtual double width(const char *str, int n) override;
-  /** Compute the width of Unicode character \p c if drawn with current font */
-  virtual double width(unsigned int c) override;
-  virtual void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h) override;
-  /** Return the current line height */
-  virtual int height() override;
-  /** Return the current line descent */
-  virtual int descent() override;
-  /** Return the current Fl_Font_Descriptor */
-  // super: inline Fl_Font_Descriptor *font_descriptor() { return font_descriptor_;}
-  /** Set the current Fl_Font_Descriptor */
-  // super: virtual void font_descriptor(Fl_Font_Descriptor *d) { font_descriptor_ = d;}
-#if 0
-  // FIXME: do we need to implement any of the functions below?
-  /** Sets the value of the driver-specific graphics context. */
-  virtual void gc(void*) {}
-  /** Returns the driver-specific graphics context, of NULL if there's none. */
-  virtual void *gc(void) {return NULL;}
-  /** Support for pixmap drawing */
-  virtual uchar **mask_bitmap() { return 0; }
-  /** Support for pixmap drawing */
-  virtual void mask_bitmap(uchar **) {}
-#endif
-  // default implementation may be enough
-  /** Support for PostScript drawing */
-  virtual float scale_font_for_PostScript(Fl_Font_Descriptor *desc, int s) override { return float(s); }
-  // default implementation may be enough
-  /** Support for PostScript drawing - no documentation found on this call*/
-  // super: virtual float scale_bitmap_for_PostScript() { return 2; }
-  // super: virtual void set_spot(int font, int size, int X, int Y, int W, int H, Fl_Window *win);
-  // super: virtual void reset_spot();
-  // each platform implements these 3 functions its own way
-  /* TODO: Android: we can implement this to have a redraw region based on Fl::damage
-   * calls. Currently, we do not implement damage regions, but we can probably
-   * implement this using our clipping regions. This may become neccesary when
-   * we allow desktop-style window movement.
-   */
-  // super: virtual void add_rectangle_to_region(Fl_Region r, int x, int y, int w, int h);
-  // super: virtual Fl_Region XRectangleRegion(int x, int y, int w, int h);
-  // super: virtual void XDestroyRegion(Fl_Region r);
-  /** Support for Fl::get_font_name() */
-  virtual const char* get_font_name(Fl_Font fnum, int* ap) override;
-  /** Support for Fl::get_font_sizes() */
-  virtual int get_font_sizes(Fl_Font fnum, int*& sizep) override;
-  /** Support for Fl::set_fonts() */
-  virtual Fl_Font set_fonts(const char *name) override;
-  /** Some platforms may need to implement this to support fonts */
-  // super: virtual Fl_Fontdesc* calc_fl_fonts(void) {return NULL;}
-  /** Support for Fl::set_font() */
-  // super: virtual unsigned font_desc_size();
-  /** Support for Fl::get_font() */
-  virtual const char *font_name(int num) override;
-  /** Support for Fl::set_font() */
-  virtual void font_name(int num, const char *name) override;
-  /** Support function for fl_overlay_rect() and scaled GUI.
-   Defaut implementation may be enough */
-  // super: virtual void overlay_rect(int x, int y, int w , int h) { loop(x, y, x+w-1, y, x+w-1, y+h-1, x, y+h-1); }
-  // --- end of original Fl_Graphics_Driver header -----------------------------
-
-  // --- start of Android additions --------------------------------------------
-  // start drawing with this driver into the given window
-  // The virtual call `set_current_()` changes surface, not windows
-  void make_current(Fl_Window*);
-
-protected:
-  static uint16_t make565(uchar r, uchar g, uchar b);
-  static uint16_t make565(Fl_Color crgba);
-  void rectf_unclipped(int x, int y, int w, int h);
-  void xyline_unclipped(int x, int y, int x1);
-  void yxline_unclipped(int x, int y, int y1);
-  void end_polygon(int begin, int end);
-  void ellipse(double xt, double yt, double rx, double ry);
-  void draw(int xx, int yy, Fl_Android_565A_Map *bm, Fl_Rect_Region &r);
-  void draw(int x, int y, Fl_Android_Bytemap *bm, Fl_Rect_Region &r);
-  int render_letter(int xx, int yy, uint32_t c, Fl_Rect_Region &r);
-
-  // pointer into the screen buffer at the top left corner of the current window
-  uint16_t *pBits = nullptr;
-
-  // advance to next line in screen buffer
-  int32_t pStride = 0;
-
-  // TODO: current line style, temp kludge to make focus rect work.
-  int pLineStyle = 0;
-
-  // Clipping region of the current window in window coordinates (see: pStride and pBits)
-  Fl_Rect_Region pWindowRegion;
-
-  // clipping region of the window minus overlapping other windows
-  Fl_Complex_Region pDesktopWindowRegion;
-
-  // Final clipping region for all graphics calls to this class.
-  Fl_Complex_Region pClippingRegion;
-
-  // store vertices for begin_.../end_... drawing
-  class Vertex {
-  public:
-    void set(float x, float y, bool gap = false) { pX = x; pY = y; pIsGap = gap; }
-    float pX, pY;
-    bool pIsGap;
-  };
-
-  void begin_vertices();
-  void add_vertex(float x, float y, bool gap=false);
-  int pnVertex = 0, pNVertex = 0, pVertexGapStart = 0;
-  Vertex *pVertex = nullptr;
-};
-
-
-#if 0
-/**
-  The graphics driver used when printing on Android.
-*/
-class FL_EXPORT Fl_Android_Printer_Graphics_Driver : public Fl_Android_Graphics_Driver {
-
-#if 0
-
-private:
-  typedef BOOL (WINAPI* transparent_f_type) (HDC,int,int,int,int,HDC,int,int,int,int,UINT);
-  transparent_f_type TransparentBlt();
-public:
-  virtual int has_feature(driver_feature mask) { return mask & (NATIVE | PRINTER); }
-  void draw_unscaled(Fl_Pixmap *pxm, float s, int XP, int YP, int WP, int HP, int cx, int cy);
-  void draw_unscaled(Fl_Bitmap *bm, float s, int XP, int YP, int WP, int HP, int cx, int cy);
-
-#endif
-
-};
-#endif
-
-
-#endif // FL_ANDROID_GRAPHICS_DRIVER_H
diff --git src/drivers/Android/Fl_Android_Graphics_Driver.cxx src/drivers/Android/Fl_Android_Graphics_Driver.cxx
deleted file mode 100644
index 75c4e08..0000000
--- src/drivers/Android/Fl_Android_Graphics_Driver.cxx
+++ /dev/null
@@ -1,1257 +0,0 @@
-//
-// Graphics routines for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-
-#include <config.h>
-#include "Fl_Android_Application.H"
-#include "Fl_Android_Graphics_Driver.H"
-#include "Fl_Android_Screen_Driver.H"
-#include <FL/Fl.H>
-#include <FL/platform.H>
-#include <errno.h>
-#include <math.h>
-
-
-extern int fl_convert_pixmap(const char*const* cdata, uchar* out, Fl_Color bg);
-
-static int sign(int v) { return (v<0) ? -1 : 1; }
-
-/*
- By linking this module, the following static method will instantiate the
- Windows GDI Graphics driver as the main display driver.
- */
-Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver()
-{
-  return new Fl_Android_Graphics_Driver();
-}
-
-
-/**
- Private default constructor.
- */
-Fl_Android_Graphics_Driver::Fl_Android_Graphics_Driver() :
-        super()
-{
-}
-
-
-Fl_Android_Graphics_Driver::~Fl_Android_Graphics_Driver()
-{
-}
-
-
-void Fl_Android_Graphics_Driver::make_current(Fl_Window *win)
-{
-  // In the special case of win==0, we activate the desktop (the screen
-  // background) for drawing and clip out all visible windows
-
-  // The Stride is the offset between lines in the graphics buffer
-  pStride = Fl_Android_Application::graphics_buffer().stride;
-  // Bits is the memory address of the top left corner of the window
-  pBits = ((uint16_t*)(Fl_Android_Application::graphics_buffer().bits));
-  if (win) pBits += win->x_root() + pStride * win->y_root();
-
-  // TODO: set the clipping area
-  // set the clipping area to the physical screen size in window coordinates
-  if (win) {
-    pWindowRegion.set(-win->x(), -win->y(), 600, 800);
-    pWindowRegion.intersect_with(Fl_Rect_Region(0, 0, win->w(), win->h()));
-  } else {
-    pWindowRegion.set(0, 0, 600, 800);
-  }
-
-  pDesktopWindowRegion.set(pWindowRegion);
-
-  // remove all window rectangles that are positioned on top of this window
-  // TODO: this region is expensive to calculate. Cache it for each window and recalculate when windows move, show, hide, or change order
-  // TODO: this is where we also need to subtract any possible window decoration, like the window title and drag bar, resizing edges, etc.
-  Fl_Window *wTop = Fl::first_window();
-  int wx = win ? win->x() : 0;
-  int wy = win ? win->y() : 0;
-  while (wTop) {
-    if (wTop==win) break;
-    Fl_Rect_Region r(wTop->x()-wx, wTop->y()-wy, wTop->w(), wTop->h());
-    pDesktopWindowRegion.subtract(r);
-    wTop = Fl::next_window(wTop);
-  }
-  pClippingRegion.set(pDesktopWindowRegion);
-}
-
-
-uint16_t Fl_Android_Graphics_Driver::make565(uchar red,  uchar green, uchar blue)
-{
-    return (uint16_t)( ((((uint16_t)(red))   << 8) & 0xf800) |
-                       ((((uint16_t)(green)) << 3) & 0x07e0) |
-                       ((((uint16_t)(blue))  >> 3) & 0x001f) );
-}
-
-extern unsigned fl_cmap[256];
-
-
-uint16_t Fl_Android_Graphics_Driver::make565(Fl_Color crgba)
-{
-  if (crgba<0x00000100) crgba = fl_cmap[crgba];
-    return (uint16_t)( ((crgba >> 16) & 0xf800) |
-                       ((crgba >> 13) & 0x07e0) |
-                       ((crgba >> 11) & 0x001f) );
-}
-
-
-void Fl_Android_Graphics_Driver::rectf(int x, int y, int w, int h)
-{
-  for (const auto &it: pClippingRegion.overlapping(Fl_Rect_Region(x, y, w, h))) {
-    Fl_Rect_Region &s = it->clipped_rect();
-    rectf_unclipped(s.x(), s.y(), s.w(), s.h());
-  }
-}
-
-
-void Fl_Android_Graphics_Driver::rectf_unclipped(int x, int y, int w, int h)
-{
-  if (w<=0 || h<=0) return;
-
-  uint16_t cc = make565(color());
-  int32_t ss = pStride;
-  uint16_t *bits = pBits;
-  uint32_t xx = (uint32_t)x;
-  uint32_t yy = (uint32_t)y;
-  uint32_t ww = (uint32_t)w;
-  uint32_t hh = (uint32_t)h;
-  for (uint32_t iy = 0; iy<hh; ++iy) {
-    uint16_t *d = bits + (iy+yy)*ss + xx;
-    for (uint32_t ix = ww; ix>0; --ix) {
-      *d++ = cc;
-    }
-  }
-}
-
-
-void Fl_Android_Graphics_Driver::xyline(int x, int y, int x1)
-{
-  float w;
-  if (x1>x) {
-    w = x1-x;
-  } else {
-    w = x-x1;
-    x = x1;
-  }
-  for (const auto &it: pClippingRegion.overlapping(Fl_Rect_Region(x, y, w, 1))) {
-    Fl_Rect_Region &s = it->clipped_rect();
-    xyline_unclipped(s.x(), s.y(), s.right());
-  }
-}
-
-
-void Fl_Android_Graphics_Driver::xyline(int x, int y, int x1, int y2)
-{
-  xyline(x, y, x1);
-  yxline(x1, y, y2);
-}
-
-
-void Fl_Android_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3)
-{
-  xyline(x, y, x1);
-  yxline(x1, y, y2);
-  xyline(x1, y2, x3);
-}
-
-
-void Fl_Android_Graphics_Driver::xyline_unclipped(int x, int y, int x1)
-{
-  uint16_t cc = make565(color());
-  float w;
-  if (x1>x) {
-    w = x1-x+1;
-  } else {
-    w = x-x1+1;
-    x = x1;
-  }
-  int32_t sx = 1;
-  int32_t ss = pStride;
-  uint16_t *bits = pBits;
-  uint32_t xx = (uint32_t)x;
-  uint32_t yy = (uint32_t)y;
-  uint32_t ww = (uint32_t)w;
-  uint16_t *d = bits + yy*ss + xx;
-  if ((pLineStyle&0xff)==FL_DOT) { ww = ww/2; sx = sx*2; }
-  for (uint32_t ix = ww; ix>0; --ix) {
-    *d = cc;
-    d+=sx;
-  }
-}
-
-
-void Fl_Android_Graphics_Driver::yxline(int x, int y, int y1)
-{
-  float h;
-  if (y1>y) {
-    h = y1-y+1;
-  } else {
-    h = y-y1+1;
-    y = y1;
-  }
-  for (const auto &it: pClippingRegion.overlapping(Fl_Rect_Region(x, y, 1, h))) {
-    Fl_Rect_Region &s = it->clipped_rect();
-    yxline_unclipped(s.x(), s.y(), s.bottom());
-  }
-}
-
-
-void Fl_Android_Graphics_Driver::yxline(int x, int y, int y1, int x2)
-{
-  yxline(x, y, y1);
-  xyline(x, y1, x2);
-}
-
-
-void Fl_Android_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3)
-{
-  yxline(x, y, y1);
-  xyline(x, y1, x2);
-  yxline(x2, y1, y3);
-}
-
-
-void Fl_Android_Graphics_Driver::yxline_unclipped(int x, int y, int y1)
-{
-  uint16_t cc = make565(color());
-  float h = y1-y;
-  int32_t ss = pStride;
-  uint16_t *bits = pBits;
-  uint32_t xx = (uint32_t)x;
-  uint32_t yy = (uint32_t)y;
-  uint32_t hh = (uint32_t)h;
-  uint16_t *d = bits + yy*ss + xx;
-  if ((pLineStyle&0xff)==FL_DOT) { hh = hh/2; ss = ss*2; }
-  for (uint32_t iy = hh; iy>0; --iy) {
-    *d = cc;
-    d += ss;
-  }
-}
-
-
-void Fl_Android_Graphics_Driver::rect(int x, int y, int w, int h)
-{
-  xyline(x, y, x+w-1);
-  yxline(x, y, y+h-1);
-  yxline(x+w-1, y, y+h-1);
-  xyline(x, y+h-1, x+w-1);
-}
-
-
-void Fl_Android_Graphics_Driver::line_style(int style, int width, char* dashes)
-{
-  pLineStyle = style;
-  // TODO: finish this!
-}
-
-/**
- Draw a single dot in the current color.
- \param x, y position relative to window.
- */
-void Fl_Android_Graphics_Driver::point(int x, int y)
-{
-  // drawing a single point is insanely inefficient because we need to walk the
-  // entire clipping region every time to see if the point needs to be drawn.
-  for (const auto &it: pClippingRegion.overlapping(Fl_Rect_Region(x, y, 1, 1))) {
-    Fl_Rect_Region &s = it->clipped_rect();
-    uint16_t cc = make565(color());
-    int32_t ss = pStride;
-    uint16_t *bits = pBits;
-    uint32_t xx = (uint32_t)x;
-    uint32_t yy = (uint32_t)y;
-    uint16_t *d = bits + yy*ss + xx;
-    *d = cc;
-  }
-
-}
-
-/**
- Draw a line.
- FIXME: it is incredibly inefficient to call 'point', especially for long lines
- FIXME: clipping maust be moved into this call and drawing to the screen should happen right here
- FIXME: line width is not considered
- */
-void Fl_Android_Graphics_Driver::line(int x, int y, int x1, int y1)
-{
-  if (x==x1) {
-    return yxline(x, y, y1);
-  }
-  if (y==y1) {
-    return xyline(x, y, x1);
-  }
-  // Bresenham
-  int w = x1 - x, dx = abs(w);
-  int h = y1 - y, dy = abs(h);
-  int dx1 = sign(w), dy1 = sign(h), dx2, dy2;
-  int min, max;
-  if (dx < dy) {
-    min = dx; max = dy;
-    dx2 = 0;
-    dy2 = dy1;
-  } else {
-    min = dy; max = dx;
-    dx2 = dx1;
-    dy2 = 0;
-  }
-  int num = max/2;
-  for (int i=max+1; i>0; i--) {
-    point(x, y);
-    num += min;
-    if (num>=max) {
-      num -= max;
-      x += dx1;
-      y += dy1;
-    } else {
-      x += dx2;
-      y += dy2;
-    }
-  }
-}
-
-
-void Fl_Android_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2)
-{
-  begin_line();
-  transformed_vertex(x, y);
-  transformed_vertex(x1, y1);
-  transformed_vertex(x2, y2);
-  end_line();
-}
-
-
-void Fl_Android_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2)
-{
-  begin_loop();
-  transformed_vertex(x0, y0);
-  transformed_vertex(x1, y1);
-  transformed_vertex(x2, y2);
-  end_loop();
-}
-
-
-void Fl_Android_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3)
-{
-  begin_loop();
-  transformed_vertex(x0, y0);
-  transformed_vertex(x1, y1);
-  transformed_vertex(x2, y2);
-  transformed_vertex(x3, y3);
-  end_loop();
-}
-
-
-void Fl_Android_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2)
-{
-  begin_polygon();
-  transformed_vertex(x0, y0);
-  transformed_vertex(x1, y1);
-  transformed_vertex(x2, y2);
-  end_polygon();
-}
-
-
-void Fl_Android_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3)
-{
-  begin_polygon();
-  transformed_vertex(x0, y0);
-  transformed_vertex(x1, y1);
-  transformed_vertex(x2, y2);
-  transformed_vertex(x3, y3);
-  end_polygon();
-}
-
-
-/**
- Reset the vertex counter to zero.
- */
-void Fl_Android_Graphics_Driver::begin_vertices()
-{
-  pnVertex = n = 0;
-  pVertexGapStart = 0;
-}
-
-/**
- Add a vertex to the vertex list. Dynamically allocates memory.
- \param x, y position of the vertex after matrix transformation
- \param gap line and loop call offer to leave a gap in the drawing
- */
-void Fl_Android_Graphics_Driver::add_vertex(float x, float y, bool gap)
-{
-  if (pnVertex == pNVertex) {
-    pNVertex += 16;
-    pVertex = (Vertex*)::realloc(pVertex, pNVertex*sizeof(Vertex));
-  }
-  pVertex[pnVertex].set(x, y);
-  pVertex[pnVertex].pIsGap = gap;
-  pnVertex++; n = pnVertex;
-}
-
-/**
- Start a list of vertices to draw multiple points.
- */
-void Fl_Android_Graphics_Driver::begin_points()
-{
-  begin_vertices();
-  super::begin_points();
-}
-
-/**
- Start a list of vertices to draw a polyline.
- */
-void Fl_Android_Graphics_Driver::begin_line()
-{
-  begin_vertices();
-  super::begin_line();
-}
-
-/**
- Start a list of vertices to draw a line loop.
- */
-void Fl_Android_Graphics_Driver::begin_loop()
-{
-  begin_vertices();
-  super::begin_loop();
-}
-
-/**
- Start a list of vertices to draw a polygon.
- */
-void Fl_Android_Graphics_Driver::begin_polygon()
-{
-  begin_vertices();
-  super::begin_polygon();
-}
-
-/**
- Start a list of vertices to draw a complex polygon.
- */
-void Fl_Android_Graphics_Driver::begin_complex_polygon()
-{
-  begin_vertices();
-  super::begin_complex_polygon();
-}
-
-/**
- Draw all stored vertices as points.
- */
-void Fl_Android_Graphics_Driver::end_points()
-{
-  for (int i=0; i<pnVertex; ++i) {
-    Vertex &v = pVertex[i];
-    if (!v.pIsGap)
-      point(v.pX, v.pY);
-  }
-}
-
-/**
- Draw all stored vertices as a polyline.
- */
-void Fl_Android_Graphics_Driver::end_line()
-{
-  Vertex &v1 = pVertex[0];
-  for (int i=1; i<pnVertex; ++i) {
-    Vertex &v2 = pVertex[i];
-    if (!v1.pIsGap && !v2.pIsGap)
-      line(v1.pX, v1.pY, v2.pX, v2.pY);
-    v1 = v2;
-  }
-}
-
-/**
- Draw all stored vertices as a polyline loop.
- */
-void Fl_Android_Graphics_Driver::end_loop()
-{
-  gap();
-  Vertex &v1 = pVertex[0];
-  for (int i=1; i<pnVertex; ++i) {
-    Vertex &v2 = pVertex[i];
-    if (!v1.pIsGap)
-      line(v1.pX, v1.pY, v2.pX, v2.pY);
-    v1 = v2;
-  }
-}
-
-/**
- Draw all stored vertices as a polygon.
- FIXME: these calls are very ineffiecient. Avoid pointer lookup.
- FIXME: use the current clipping rect to accelerate rendering
- FIXME: unmix float and int
- */
-void Fl_Android_Graphics_Driver::end_polygon(int begin, int end)
-{
-  if (end - begin < 2) return;
-
-  Vertex *v = pVertex+0;
-  int xMin = v->pX, xMax = xMin, yMin = v->pY, yMax = yMin;
-  for (int i = begin+1; i < end; i++) {
-    v = pVertex+i;
-    if (v->pX < xMin) xMin = v->pX;
-    if (v->pX > xMax) xMax = v->pX;
-    if (v->pY < yMin) yMin = v->pY;
-    if (v->pY > yMax) yMax = v->pY;
-  }
-  xMax++; yMax++;
-
-  int nodes, nodeX[end - begin], pixelX, pixelY, i, j, swap;
-
-  //  Loop through the rows of the image.
-  for (pixelY = yMin; pixelY < yMax; pixelY++) {
-    //  Build a list of nodes.
-    nodes = 0;
-    j = begin;
-    for (i = begin+1; i < end; i++) {
-      if (   (pVertex[i].pY < pixelY && pVertex[j].pY >= pixelY)
-          || (pVertex[j].pY < pixelY && pVertex[i].pY >= pixelY))
-      {
-        float dy = pVertex[j].pY - pVertex[i].pY;
-        if (fabsf(dy)>.0001) {
-          nodeX[nodes++] = (int)(pVertex[i].pX +
-                                 (pixelY - pVertex[i].pY) / dy
-                                 * (pVertex[j].pX - pVertex[i].pX));
-        } else {
-          nodeX[nodes++] = pVertex[i].pX;
-        }
-      }
-      j = i;
-    }
-
-    //  Sort the nodes, via a simple â??Bubbleâ?? sort.
-    i = 0;
-    while (i < nodes - 1) {
-      if (nodeX[i] > nodeX[i + 1]) {
-        swap = nodeX[i];
-        nodeX[i] = nodeX[i + 1];
-        nodeX[i + 1] = swap;
-        if (i) i--;
-      } else {
-        i++;
-      }
-    }
-
-    //  Fill the pixels between node pairs.
-    for (i = 0; i < nodes; i += 2) {
-      if (nodeX[i] >= xMax) break;
-      if (nodeX[i + 1] > xMin) {
-        if (nodeX[i] < xMin) nodeX[i] = xMin;
-        if (nodeX[i + 1] > xMax) nodeX[i + 1] = xMax;
-        xyline(nodeX[i], pixelY, nodeX[i + 1]);
-      }
-    }
-  }
-
-}
-
-/**
- Draw all stored vertices as a polygon.
- Mind the gap!
- */
-void Fl_Android_Graphics_Driver::end_polygon()
-{
-  if (pnVertex==0) return;
-  gap();
-  int start = 0, end = 0;
-  for (int i=0; i<pnVertex; i++) {
-    if (pVertex[i].pIsGap) {
-      end = i+1;
-      end_polygon(start, end);
-      start = end;
-      i++;
-    }
-  }
-}
-
-/**
- Draw all stored vertices as a possibly self-intersecting polygon.
- FIXME: these calls are very ineffiecient. Avoid pointer lookup.
- FIXME: use the current clipping rect to accelerate rendering
- FIXME: unmix float and int
- */
-void Fl_Android_Graphics_Driver::end_complex_polygon()
-{
-  if (pnVertex < 2) return;
-
-  gap(); // adds the first coordinate of this loop and marks it as a gap
-  int begin = 0, end = pnVertex;
-
-  Vertex *v = pVertex+0;
-  int xMin = v->pX, xMax = xMin, yMin = v->pY, yMax = yMin;
-  for (int i = begin+1; i < end; i++) {
-    v = pVertex+i;
-    if (v->pX < xMin) xMin = v->pX;
-    if (v->pX > xMax) xMax = v->pX;
-    if (v->pY < yMin) yMin = v->pY;
-    if (v->pY > yMax) yMax = v->pY;
-  }
-  xMax++; yMax++;
-
-  int nodes, nodeX[end - begin], pixelX, pixelY, i, j, swap;
-
-  //  Loop through the rows of the image.
-  for (pixelY = yMin; pixelY < yMax; pixelY++) {
-    //  Build a list of nodes.
-    nodes = 0;
-    for (i = begin+1; i < end; i++) {
-      j = i-1;
-      if (pVertex[j].pIsGap)
-        continue;
-      if (   (pVertex[i].pY < pixelY && pVertex[j].pY >= pixelY)
-          || (pVertex[j].pY < pixelY && pVertex[i].pY >= pixelY) )
-      {
-        float dy = pVertex[j].pY - pVertex[i].pY;
-        if (fabsf(dy)>.0001) {
-          nodeX[nodes++] = (int)(pVertex[i].pX +
-                                 (pixelY - pVertex[i].pY) / dy
-                                 * (pVertex[j].pX - pVertex[i].pX));
-        } else {
-          nodeX[nodes++] = pVertex[i].pX;
-        }
-      }
-    }
-    //Fl_Android_Application::log_e("%d nodes (must be even!)", nodes);
-
-    //  Sort the nodes, via a simple â??Bubbleâ?? sort.
-    i = 0;
-    while (i < nodes - 1) {
-      if (nodeX[i] > nodeX[i + 1]) {
-        swap = nodeX[i];
-        nodeX[i] = nodeX[i + 1];
-        nodeX[i + 1] = swap;
-        if (i) i--;
-      } else {
-        i++;
-      }
-    }
-
-    //  Fill the pixels between node pairs.
-    for (i = 0; i < nodes; i += 2) {
-      if (nodeX[i] >= xMax) break;
-      if (nodeX[i + 1] > xMin) {
-        if (nodeX[i] < xMin) nodeX[i] = xMin;
-        if (nodeX[i + 1] > xMax) nodeX[i + 1] = xMax;
-        xyline(nodeX[i], pixelY, nodeX[i + 1]);
-      }
-    }
-  }
-}
-
-/**
- Add a gap to a polyline drawing
- */
-void Fl_Android_Graphics_Driver::gap()
-{
-  // drop gaps at the start or gap after gap
-  if (pnVertex==0 || pnVertex==pVertexGapStart)
-    return;
-
-  // create a loop
-  Vertex &v = pVertex[pVertexGapStart];
-  add_vertex(v.pX, v.pY, true);
-  pVertexGapStart = pnVertex;
-}
-
-/**
- Add a vertex to the list.
- TODO: we should maintain a bounding box for faster clipping.
- */
-void Fl_Android_Graphics_Driver::transformed_vertex(double x, double y)
-{
-  add_vertex(x, y);
-}
-
-
-void Fl_Android_Graphics_Driver::vertex(double x,double y)
-{
-  transformed_vertex(x*m.a + y*m.c + m.x, x*m.b + y*m.d + m.y);
-}
-
-
-/**
- Draw an arc.
- \param xi
- \param yi
- \param w
- \param h
- \param a1
- \param a2
- FIXME: float-to-int interpolation is horrible!
- */
-void Fl_Android_Graphics_Driver::arc(int xi, int yi, int w, int h, double a1, double a2)
-{
-  if (a2<=a1) return;
-
-  double rx = w/2.0;
-  double ry = h/2.0;
-  double x = xi + rx;
-  double y = yi + ry;
-  double circ = M_PI*0.5*(rx+ry);
-  int i, segs = circ * (a2-a1) / 1000;  // every line is about three pixels long
-  if (segs<3) segs = 3;
-
-  int px, py;
-  a1 = a1/180*M_PI;
-  a2 = a2/180*M_PI;
-  double step = (a2-a1)/segs;
-
-  int nx = x + cos(a1)*rx;
-  int ny = y - sin(a1)*ry;
-  for (i=segs; i>0; i--) {
-    a1+=step;
-    px = nx; py = ny;
-    nx = x + cos(a1)*rx;
-    ny = y - sin(a1)*ry;
-    line(px, py, nx, ny);
-  }
-}
-
-/**
- Draw a piece of a pie.
- FIXME: this is not working very well at all.
- \param xi
- \param yi
- \param w
- \param h
- \param b1
- \param b2
- */
-void Fl_Android_Graphics_Driver::pie(int xi, int yi, int w, int h, double b1, double b2)
-{
-  // quick access to bounding box size
-  double rx = w / 2.0;
-  double ry = h / 2.0;
-  double x = xi + rx;
-  double y = yi + ry;
-
-
-  double a1 = b1 / 180 * M_PI;
-  double a2 = b2 / 180 * M_PI;
-
-  // invert to make b1 always the smaller value
-  if (b1 > b2) {
-    b1 -= 360.0;
-  }
-  if (b1 == b2) return;
-
-  // make the top the zero degree origin, turning CCW
-  b1 -= 90.0;
-  b2 -= 90.0;
-
-  // find the delta between angles
-  double delta = b2 - b1;
-  if (delta >= 360.0) {
-    b1 = 0.0;
-    b2 = 360.0;
-    delta = 360.0;
-  }
-
-  // make sure that b2 is always in the range [0.0..360.0]
-  if (b2 > 360.0) b2 -= 360.0; // FIXME: fmod(...)
-  if (b2 < 0.0) b2 += 360.0;
-  b1 = b2 - delta;
-  // now b1 is [-360...360] and b2 is [0..360] and b1<b2;
-
-  a1 = b1 / 180 * M_PI;
-  a2 = b2 / 180 * M_PI;
-  double b1o = b1;
-  bool flipped = false;
-  if (a1<0.0) { a1 += 2*M_PI; b1 += 360.0; flipped = true; }
-
-//  Fl_Android_Application::log_e(" %g %g %d", b1, b2, flipped);
-
-  double a1Slope = tan(a1);
-  double a2Slope = tan(a2);
-
-  // draw the pie line by line
-  for (double iy = y - ry; iy <= y + ry; iy++) {
-    double a = acos((iy - y) / ry);
-    double aL = M_PI - a; // 0..PI
-    double aR = a + M_PI; // 2PI..PI
-    double sinALrx = sin(aL)*rx;
-
-//    fl_color(FL_RED);
-
-    if (aL<0.5*M_PI) {
-      // rasterize top left quadrant
-      bool loInside = false, hiInside = false;
-      double loLeft = 0.0, loRight = 0.0;
-      double hiLeft = 0.0, hiRight = 0.0;
-      if (b1 >= 0 && b1 < 90) {
-        loInside = true;
-        loLeft = -sinALrx;
-        loRight = a1Slope * (iy - y);
-      }
-      if (b2 >= 0 && b2 < 90) {
-        hiInside = true;
-        if (aL < a2)
-          hiLeft = -sinALrx;
-        else
-          hiLeft = a2Slope * (iy - y);
-      }
-      if (loInside && hiInside && !flipped) {
-//        fl_color(FL_GREEN);
-        if (a1 < aL)
-          xyline(x + hiLeft, iy, x + loRight);
-      } else {
-        if ((!loInside) && (!hiInside)) {
-//          fl_color(FL_MAGENTA);
-          if ( (b1o<=0.0 && b2>=90.0) || (b1o<=(0.0-360.0) && b2>=(90.0-360.0)) )
-            xyline(x - sinALrx, iy, x);
-        } else {
-          if (loInside) {
-//            fl_color(FL_BLUE);
-            if (a1 < aL)
-              xyline(x + loLeft, iy, x + loRight);
-          }
-          if (hiInside) {
-//            fl_color(FL_YELLOW);
-            xyline(x + hiLeft, iy, x);
-          }
-        }
-      }
-    } else {
-      // rasterize bottom left quadrant
-      bool loInside = false, hiInside = false;
-      double loLeft = 0.0, loRight = 0.0;
-      double hiLeft = 0.0, hiRight = 0.0;
-      if (b1 >= 90 && b1 < 180) {
-        loInside = true;
-        if (aL>=a1)
-          loLeft = -sinALrx;
-        else
-          loLeft = a1Slope * (iy - y);
-      }
-      if (b2 >= 90 && b2 < 180) {
-        hiInside = true;
-        hiLeft = -sinALrx;
-        hiRight = a2Slope * (iy - y);
-      }
-      if (loInside && hiInside && !flipped) {
-//        fl_color(FL_GREEN);
-        if (a2 > aL)
-          xyline(x + loLeft, iy, x + hiRight);
-      } else {
-        if ((!loInside) && (!hiInside)) {
-//          fl_color(FL_MAGENTA);
-          if ( (b1o<=90.0 && b2>=180.0) || (b1o<=(90.0-360.0) && b2>=(180.0-360.0)) )
-            xyline(x - sinALrx, iy, x);
-        } else {
-          if (loInside) {
-//            fl_color(FL_BLUE);
-            xyline(x + loLeft, iy, x);
-          }
-          if (hiInside) {
-//            fl_color(FL_YELLOW);
-            if (a2 > aL)
-              xyline(x + hiLeft, iy, x + hiRight);
-          }
-        }
-      }
-    }
-    if (aR<1.5*M_PI) {
-      // rasterize bottom right quadrant
-      bool loInside = false, hiInside = false;
-      double loLeft = 0.0, loRight = 0.0;
-      double hiLeft = 0.0, hiRight = 0.0;
-      if (b1 >= 180 && b1 < 270) {
-        loInside = true;
-        loLeft = sinALrx;
-        loRight = a1Slope * (iy - y);
-      }
-      if (b2 >= 180 && b2 < 270) {
-        hiInside = true;
-        if (aR < a2)
-          hiLeft = sinALrx;
-        else
-          hiLeft = a2Slope * (iy - y);
-      }
-      if (loInside && hiInside && !flipped) {
-//        fl_color(FL_GREEN);
-        if (a1 < aR)
-          xyline(x + hiLeft, iy, x + loRight);
-      } else {
-        if ((!loInside) && (!hiInside)) {
-//          fl_color(FL_MAGENTA);
-          if ( (b1o<=180.0 && b2>=270.0) || (b1o<=(180.0-360.0) && b2>=(270.0-360.0)) )
-            xyline(x + sinALrx, iy, x);
-        } else {
-          if (loInside) {
-//            fl_color(FL_BLUE);
-            if (a1 < aR)
-              xyline(x + loLeft, iy, x + loRight);
-          }
-          if (hiInside) {
-//            fl_color(FL_YELLOW);
-            xyline(x + hiLeft, iy, x);
-          }
-        }
-      }
-    } else {
-      // rasterize top right quadrant
-      bool loInside = false, hiInside = false;
-      double loLeft = 0.0, loRight = 0.0;
-      double hiLeft = 0.0, hiRight = 0.0;
-      if (b1 >= 270 && b1 < 360) {
-        loInside = true;
-        if (aR>=a1)
-          loLeft = sinALrx;
-        else
-          loLeft = a1Slope * (iy - y);
-      }
-      if (b2 >= 270 && b2 < 360) {
-        hiInside = true;
-        hiLeft = sinALrx;
-        hiRight = a2Slope * (iy - y);
-      }
-      if (loInside && hiInside && !flipped) {
-//        fl_color(FL_GREEN);
-        if (a2 > aR)
-          xyline(x + loLeft, iy, x + hiRight);
-      } else {
-        if ((!loInside) && (!hiInside)) {
-//          fl_color(FL_MAGENTA);
-          if ( (b1o<=270.0 && b2>=360.0) || (b1o<=(270.0-360.0) && b2>=(360.0-360.0)) )
-            xyline(x + sinALrx, iy, x);
-        } else {
-          if (loInside) {
-//            fl_color(FL_BLUE);
-            xyline(x + loLeft, iy, x);
-          }
-          if (hiInside) {
-//            fl_color(FL_YELLOW);
-            if (a2 > aR)
-              xyline(x + hiLeft, iy, x + hiRight);
-          }
-        }
-      }
-    }
-  }
-}
-
-/**
- FIXME: these do not draw rotated ellipses correctly!
- FIXME: use floating point version of arc and pie?!
- */
-void Fl_Android_Graphics_Driver::ellipse(double xt, double yt, double rx, double ry)
-{
-  int llx = xt-rx;
-  int w = xt+rx-llx;
-  int lly = yt-ry;
-  int h = yt+ry-lly;
-
-  if (what==POLYGON)
-    pie(llx, lly, w, h, 0.0, 360.0);
-  else
-    arc(llx, lly, w, h, 0.0, 360.0);
-}
-
-
-void Fl_Android_Graphics_Driver::circle(double x, double y, double r)
-{
-  double xt = transform_x(x,y);
-  double yt = transform_y(x,y);
-  double rx = r * (m.c ? sqrt(m.a*m.a+m.c*m.c) : fabs(m.a));
-  double ry = r * (m.b ? sqrt(m.b*m.b+m.d*m.d) : fabs(m.d));
-  ellipse(xt, yt, rx, ry);
-}
-
-
-void Fl_Android_Graphics_Driver::draw_fixed(Fl_Pixmap * pxm, int X, int Y, int W, int H, int cx, int cy)
-{
-  if (*Fl_Graphics_Driver::id(pxm)) {
-    Fl_Android_565A_Map *cache = (Fl_Android_565A_Map*)*Fl_Graphics_Driver::id(pxm);
-    for (const auto &it: pClippingRegion.overlapping(Fl_Rect_Region(X, Y, W, H))) {
-      draw(X-cx, Y-cy, cache, it->clipped_rect());
-    }
-  }
-}
-
-
-void Fl_Android_Graphics_Driver::draw_fixed(Fl_Bitmap *bm, int X, int Y, int W, int H, int cx, int cy)
-{
-  if (*Fl_Graphics_Driver::id(bm)) {
-    Fl_Android_Bytemap *cache = (Fl_Android_Bytemap*)*Fl_Graphics_Driver::id(bm);
-    for (const auto &it: pClippingRegion.overlapping(Fl_Rect_Region(X, Y, W, H))) {
-      draw(X-cx, Y-cy, cache, it->clipped_rect());
-    }
-  }
-}
-
-
-void Fl_Android_Graphics_Driver::cache(Fl_Bitmap *bm)
-{
-  int w = bm->w(), h = bm->h();
-  int rowBytes = (w+7)>>3;
-
-  Fl_Android_Bytemap *cache = new Fl_Android_Bytemap(w, h);
-  for (int yy=0; yy<w; yy++) {
-    const uchar *src = bm->array + yy*rowBytes;
-    uchar *dst = cache->pBytes + yy*cache->pStride;
-    uchar d = 0;
-    for (int xx=0; xx<w; xx++) {
-      if ((xx&7)==0) d = *src++;
-      if (d&1) *dst = 0xff; else *dst = 0;
-      dst++;
-      d >>= 1;
-    }
-  }
-
-  *Fl_Graphics_Driver::id(bm) = (fl_uintptr_t)cache;
-  int *pw, *ph;
-  cache_w_h(bm, pw, ph);
-  *pw = bm->data_w();
-  *ph = bm->data_h();
-}
-
-void Fl_Android_Graphics_Driver::delete_bitmask(Fl_Bitmask bm)
-{
-  delete (Fl_Android_Bytemap*)bm;
-}
-
-void Fl_Android_Graphics_Driver::cache(Fl_Pixmap *img)
-{
-  int w = img->w(), h = img->h();
-  int rowBytes = 4*w;
-  uchar *rgba = (uchar*)calloc(w*h, 4);
-  int ret = fl_convert_pixmap(img->data(), rgba, 0);
-  if (ret==0) {
-    ::free(rgba);
-    *Fl_Graphics_Driver::id(img) = 0;
-    return;
-  }
-
-  Fl_Android_565A_Map *cache = new Fl_Android_565A_Map(w, h);
-  for (int yy=0; yy<w; yy++) {
-    const uchar *src = rgba + yy*rowBytes;
-    uint32_t *dst = cache->pWords + yy*cache->pStride;
-    for (int xx=0; xx<w; xx++) {
-//      uint32_t c = ((((src[0] << 8) & 0xf800) |
-//                     ((src[1] << 3) & 0x07e0) |
-//                     ((src[2] >> 3) & 0x001f) ) << 16) | src[3]; // FIXME: alpha
-      *dst++ = Fl_Android_565A_Map::toRGBA(src[0],src[1], src[2], src[3]);
-      src+=4;
-    }
-  }
-
-  ::free(rgba);
-  *Fl_Graphics_Driver::id(img) = (fl_uintptr_t)cache;
-  int *pw, *ph;
-  cache_w_h(img, pw, ph);
-  *pw = img->data_w();
-  *ph = img->data_h();
-}
-
-
-void Fl_Android_Graphics_Driver::uncache_pixmap(fl_uintptr_t p)
-{
-  Fl_Android_565A_Map *img = (Fl_Android_565A_Map*)p;
-  delete img;
-}
-
-void Fl_Android_Graphics_Driver::cache(Fl_RGB_Image *img)
-{
-  int w = img->data_w(), h = img->data_h(), d = img->d(), stride = w*d + img->ld();
-  Fl_Android_565A_Map *cgimg = new Fl_Android_565A_Map(w, h);
-  *Fl_Graphics_Driver::id(img) = (fl_uintptr_t)cgimg;
-  int *pw, *ph;
-  cache_w_h(img, pw, ph);
-  *pw = img->data_w();
-  *ph = img->data_h();
-  if (d==1) { // grayscale
-    for (int iy=0; iy<h; iy++) {
-      const uchar *src = img->array + iy*stride;
-      uint32_t *dst = cgimg->pWords + iy*cgimg->pStride;
-      for (int ix=0; ix<w; ix++) {
-        uchar l = *src++;
-        uint32_t rgba = Fl_Android_565A_Map::toRGBA(l, l, l, 255);
-        *dst++ = rgba;
-      }
-    }
-  } else if (d==2) { // gray + alpha
-    for (int iy=0; iy<h; iy++) {
-      const uchar *src = img->array + iy*stride;
-      uint32_t *dst = cgimg->pWords + iy*cgimg->pStride;
-      for (int ix=0; ix<w; ix++) {
-        uchar l = *src++, a = *src++;
-        uint32_t rgba = Fl_Android_565A_Map::toRGBA(l, l, l, a);
-        *dst++ = rgba;
-      }
-    }
-  } else if (d==3) { // rgb
-    for (int iy=0; iy<h; iy++) {
-      const uchar *src = img->array + iy*stride;
-      uint32_t *dst = cgimg->pWords + iy*cgimg->pStride;
-      for (int ix=0; ix<w; ix++) {
-        uchar r = *src++, g = *src++, b = *src++;
-        uint32_t rgba = Fl_Android_565A_Map::toRGBA(r, g, b, 255);
-        *dst++ = rgba;
-      }
-    }
-  } else if (d==4) { // rgb + alpha
-    for (int iy=0; iy<h; iy++) {
-      const uchar *src = img->array + iy*stride;
-      uint32_t *dst = cgimg->pWords + iy*cgimg->pStride;
-      for (int ix=0; ix<w; ix++) {
-        uchar r = *src++, g = *src++, b = *src++, a = *src++;
-        uint32_t rgba = Fl_Android_565A_Map::toRGBA(r, g, b, a);
-        *dst++ = rgba;
-      }
-    }
-  }
-}
-
-void Fl_Android_Graphics_Driver::draw_fixed(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, int cy)
-{
-  Fl_Android_565A_Map *cgimg = (Fl_Android_565A_Map*)*Fl_Graphics_Driver::id(img);
-  if (cgimg) {
-    for (const auto &it: pClippingRegion.overlapping(Fl_Rect_Region(X, Y, W, H))) {
-      draw(X-cx, Y-cy, cgimg, it->clipped_rect());
-    }
-  }
-}
-
-
-/**
- Copy RGB (or RGBA?) image data directly onto the surface.
- TODO: I did not find documentation on the possible values of D. If D is four, does that
- mean that the fourth value must be an alpha value, and should that be applied here?
- What does a negative D indicate?
- */
-void Fl_Android_Graphics_Driver::draw_image(const uchar* buf, int X,int Y,int W,int H, int D, int L)
-{
-  int srcDelta = abs(D);
-  int srcStride = L ? L : W*srcDelta;
-  for (const auto &it: pClippingRegion.overlapping(Fl_Rect_Region(X, Y, W, H))) {
-    Fl_Rect_Region *r = &it->clipped_rect();
-    int rBottom = r->bottom();
-    int rRight = r->right();
-    for (int iy=r->top(); iy<rBottom;iy++) {
-      const uchar *src = buf + (iy-Y)*srcStride + (r->left()-X)*srcDelta;
-      uint16_t *dst = pBits + iy*pStride + r->left();
-      for (int ix=r->left();ix<rRight;ix++) {
-        uint16_t c = make565(src[0], src[1], src[2]);
-        src += srcDelta;
-        *dst++ = c;
-      }
-    }
-  }
-}
-
-/**
- Copy RGB (or RGBA?) image data directly onto the surface.
- TODO: I did not find documentation on the possible values of D. If D is four, does that
- mean that the fourth value must be an alpha value, and should that be applied here?
- What does a negative D indicate?
- */
-void Fl_Android_Graphics_Driver::draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D, int L)
-{
-  int srcDelta = abs(D);
-  int srcStride = W*srcDelta+L;
-  for (const auto &it: pClippingRegion.overlapping(Fl_Rect_Region(X, Y, W, H))) {
-    Fl_Rect_Region *r = &it->clipped_rect();
-    int rBottom = r->bottom();
-    int rRight = r->right();
-    for (int iy=r->top(); iy<rBottom;iy++) {
-      const uchar *src = buf + iy*srcStride;
-      uint16_t *dst = pBits + iy*pStride + r->left();
-      for (int ix=r->left();ix<rRight;ix++) {
-        uchar l = src[0];
-        uint16_t c = make565(l, l, l);
-        src += srcDelta;
-        *dst++ = c;
-      }
-    }
-  }
-}
-
-/*
- Draw some graphics line-by-line directly onto this surface
- TODO: I did not find documentation on the possible values of D. If D is four, does that
- mean that the fourth value must be an alpha value, and should that be applied here?
- */
-void Fl_Android_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D)
-{
-  int srcDelta = abs(D);
-  for (const auto &it: pClippingRegion.overlapping(Fl_Rect_Region(X, Y, W, H))) {
-    Fl_Rect_Region *r = &it->clipped_rect();
-    uchar *buf = (uchar*)malloc(size_t(srcDelta*r->w()));
-    int rBottom = r->bottom();
-    int rRight = r->right();
-    for (int iy=r->top(); iy<rBottom;iy++) {
-      cb(data, r->left()-X, iy-Y, r->w(), buf);
-      uchar *src = buf;
-      uint16_t *dst = pBits + iy*pStride + r->left();
-      for (int ix=r->left();ix<rRight;ix++) {
-        uint16_t c = make565(src[0], src[1], src[2]);
-        src += srcDelta;
-        *dst++ = c;
-      }
-    }
-    free(buf);
-  }
-}
-
-/*
- Draw some graphics line-by-line directly onto this surface
- TODO: I did not find documentation on the possible values of D. If D is two, does that
- mean that the fourth value must be an alpha value, and should that be applied here?
- If it is three, doe we need to convert RGB to grayscale?
- What exactly does a negative value mean? Where is this all documented? Sigh.
- */
-void Fl_Android_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D)
-{
-  int srcDelta = abs(D);
-  for (const auto &it: pClippingRegion.overlapping(Fl_Rect_Region(X, Y, W, H))) {
-    Fl_Rect_Region *r = &it->clipped_rect();
-    uchar *buf = (uchar*)malloc(size_t(srcDelta*r->w()));
-    int rBottom = r->bottom();
-    int rRight = r->right();
-    for (int iy=r->top(); iy<rBottom;iy++) {
-      cb(data, r->left()-X, iy-Y, r->w(), buf);
-      uchar *src = buf;
-      uint16_t *dst = pBits + iy*pStride + r->left();
-      for (int ix=r->left();ix<rRight;ix++) {
-        uchar l = src[0];
-        uint16_t c = make565(l, l, l);
-        src += srcDelta;
-        *dst++ = c;
-      }
-    }
-    free(buf);
-  }
-}
-
-
-void Fl_Android_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintptr_t&)
-{
-  Fl_Android_565A_Map *cgimg = (Fl_Android_565A_Map*)id_;
-  delete cgimg;
-  id_ = 0;
-}
-
-
-void Fl_Android_Graphics_Driver::set_color(Fl_Color i, unsigned int c)
-{
-  if (i>255) return;
-  fl_cmap[i] = c;
-}
-
-
-void Fl_Android_Graphics_Driver::color(uchar r, uchar g, uchar b)
-{
-  color( (((Fl_Color)r)<<24)|(((Fl_Color)g)<<16)|(((Fl_Color)b)<<8) );
-}
diff --git src/drivers/Android/Fl_Android_Graphics_Font.H src/drivers/Android/Fl_Android_Graphics_Font.H
deleted file mode 100644
index b07ba7d..0000000
--- src/drivers/Android/Fl_Android_Graphics_Font.H
+++ /dev/null
@@ -1,132 +0,0 @@
-//
-// Font definitions for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-#ifndef FL_ANDROID_GRAPHICS_FONT_H
-#define FL_ANDROID_GRAPHICS_FONT_H
-
-
-#include "Fl_Android_Graphics_Driver.H"
-
-// We violate FLTKs avoidance of STL because we live in a defined driver space
-#define FL_ALLOW_STL 1
-#ifdef FL_ALLOW_STL
-#include <map>
-#endif
-
-#include "stb_truetype.h"
-
-
-/**
- A bytemap is an array of bytes, used as an alpha channel when redering glyphs
- in a given color.
- TODO: reate a class for RGB only and for grayscale and grayscale with alpha
- TODO: derive all this from a baseclass, so we can create the correct class for the required image
- */
-class Fl_Android_Bytemap
-{
-public:
-  Fl_Android_Bytemap();
-  Fl_Android_Bytemap(int w, int h);
-  ~Fl_Android_Bytemap();
-
-public:
-  int pWidth = 0, pHeight = 0, pStride = 0;
-  int pXOffset = 0, pYOffset = 0, pAdvance = 0;
-  unsigned char *pBytes = nullptr;
-};
-
-
-/**
- A 565a map is an array of words for interleaved RGB and Alpha data.
- 565 is the number of bit per component, compatible with our screen memory
- scheme. The second word is actually a byt containing the alpha value for
- the previous pixel: rrrrrggg.gggbbbbb.aaaaaaaa.00000000
- */
-class Fl_Android_565A_Map
-{
-public:
-  Fl_Android_565A_Map();
-  Fl_Android_565A_Map(int w, int h);
-  ~Fl_Android_565A_Map();
-  static inline uint32_t toRGBA(uchar r, uchar g, uchar b, uchar a)
-  {
-    return ((((r << 8) & 0xf800) |
-             ((g << 3) & 0x07e0) |
-             ((b >> 3) & 0x001f)) << 16) | a;
-  }
-
-public:
-  int pWidth = 0, pHeight = 0, pStride = 0;
-  int pXOffset = 0, pYOffset = 0;
-  uint32_t *pWords = nullptr;
-};
-
-
-/**
- This class reads True Type Font files and creates Bytemaps for glyphs at the
- requested height.
- */
-class Fl_Android_Font_Source
-{
-private:
-  stbtt_fontinfo pFont;
-  uint8_t *pFileBuffer;
-  const char *pName;
-  Fl_Font pFontIndex;
-  bool pError;
-
-  bool load_font(const char *name);
-  bool load_font_file(const char *name);
-  bool load_font_asset(const char *name);
-
-public:
-  Fl_Android_Font_Source(const char *fname, Fl_Font fnum);
-  ~Fl_Android_Font_Source();
-  void load_font();
-  Fl_Android_Bytemap *get_bytemap(uint32_t c, int size);
-  float get_advance(uint32_t c, Fl_Fontsize size);
-  int get_descent(Fl_Fontsize size);
-};
-
-
-/**
- This class caches glyphs of a font for a specified height.
- */
-class Fl_Android_Font_Descriptor : public Fl_Font_Descriptor
-{
-#ifdef FL_ALLOW_STL
-  typedef std::map<uint32_t, Fl_Android_Bytemap*> BytemapTable;
-#else
-  typedef Fl_Android_Bytemap* BytemapTable[256];
-#endif
-private:
-  Fl_Android_Font_Source *pFontSource;
-  Fl_Font pFontIndex;
-  BytemapTable pBytemapTable;
-
-public:
-  Fl_Android_Font_Descriptor(const char *fname, Fl_Android_Font_Source *fsrc, Fl_Font fnum, Fl_Fontsize size);
-  ~Fl_Android_Font_Descriptor();
-  float get_advance(uint32_t c);
-  Fl_Android_Bytemap *get_bytemap(uint32_t c);
-  Fl_Android_Font_Source *get_font_source() { return pFontSource; }
-  int get_descent();
-
-  static Fl_Android_Font_Descriptor* find(Fl_Font fnum, Fl_Fontsize size);
-};
-
-
-#endif // FL_ANDROID_GRAPHICS_FONT_H
diff --git src/drivers/Android/Fl_Android_Graphics_Font.cxx src/drivers/Android/Fl_Android_Graphics_Font.cxx
deleted file mode 100644
index 48e6152..0000000
--- src/drivers/Android/Fl_Android_Graphics_Font.cxx
+++ /dev/null
@@ -1,797 +0,0 @@
-//
-// Graphics routines for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-
-#include "Fl_Android_Graphics_Font.H"
-#include "Fl_Android_Application.H"
-#include <FL/fl_draw.H>
-#include <errno.h>
-#include <FL/filename.H>
-
-#define STB_TRUETYPE_IMPLEMENTATION  // force following include to generate implementation
-#include "stb_truetype.h"
-
-
-//struct Fl_Fontdesc {
-//  const char *name;
-//  char fontname[128];  // "Pretty" font name
-//  Fl_Font_Descriptor *first;  // linked list of sizes of this style
-//};
-
-
-/**
- - font names starting with a $ will have the system font path inserted
- - font names starting with an @ will be loaded via the Asset Manager
- - all other names will be used verbatim
- */
-static Fl_Fontdesc built_in_table[] = {
-        {"$Roboto-Regular.ttf"},
-        {"$Roboto-Bold.ttf"},
-        {"$Roboto-Italic.ttf"},
-        {"$Roboto-BoldItalic.ttf"},
-        {"$CutiveMono.ttf"},
-        {"$CutiveMono.ttf"}, // sorry no bold
-        {"$CutiveMono.ttf"}, // sorry no italic
-        {"$CutiveMono.ttf"}, // sorry no bold-italic
-        {"$NotoSerif-Regular.ttf"},
-        {"$NotoSerif-Bold.ttf"},
-        {"$NotoSerif-Italic.ttf"},
-        {"$NotoSerif-BoldItalic.ttf"},
-        {"$Roboto-Regular.ttf"},
-        {"$DroidSansMono.ttf"},
-        {"$DroidSansMono.ttf"}, // sorry no bold
-        {"$Roboto-Regular.ttf"},
-};
-
-Fl_Fontdesc* fl_fonts = built_in_table;
-
-static const char *old_font_names[] = {
-        "$DroidSans.ttf", "$DroidSerif-Regular.ttf",
-        "$DroidSansMono.ttf", "$DroidSansMono.ttf"
-};
-
-// -----------------------------------------------------------------------------
-
-/**
- Create an empty Bytemap.
- */
-Fl_Android_Bytemap::Fl_Android_Bytemap()
-{
-}
-
-/**
- Create an empty Bytemap.
- */
-Fl_Android_Bytemap::Fl_Android_Bytemap(int w, int h)
-{
-  pWidth = w; pStride = w; pHeight = h;
-  pBytes = (unsigned char *)calloc(w, h);
-}
-
-/**
- Destroy the Bytemap and its allocated resources.
- */
-Fl_Android_Bytemap::~Fl_Android_Bytemap()
-{
-  if (pBytes) ::free(pBytes);
-}
-
-/**
- Render a bytemap to the screen using the current fl_color.
-
- Bytes are seen as alpha values for the RGB color set by fl_color. For better
- performance, alpha is only rendered in 5 steps. All rendering is offset as
- described in the bytemap, and clipped to the clipping region.
- \param xx, yy bottom left position of the bytemap (baseline for text)
- \param bm bytemap including offsets and size
- \param r clipping rectangle
- */
-void Fl_Android_Graphics_Driver::draw(int xx, int yy, Fl_Android_Bytemap *bm,
-                                      Fl_Rect_Region &r)
-{
-  xx += bm->pXOffset; yy += bm->pYOffset;
-
-  if (xx>r.right()) return;
-  if (yy>r.bottom()) return;
-  if (xx+bm->pWidth < r.left()) return;
-  if (yy+bm->pHeight < r.top()) return;
-
-  uint16_t cc = make565(fl_color()), cc12 = (cc&0xf7de)>>1, cc14 = (cc12&0xf7de)>>1, cc34 = cc12+cc14;
-  int32_t ss = pStride;
-  uint16_t *bits = pBits;
-  uint32_t ww = bm->pWidth;
-  uint32_t hh = bm->pHeight;
-  unsigned char *srcBytes = bm->pBytes;
-
-  int dx = r.left()-xx;
-  int dy = r.top()-yy;
-  int dr = (xx+ww)-r.right();
-  int db = (yy+hh)-r.bottom();
-  if (dx>0) { xx+=dx; ww-=dx; srcBytes+=dx; }
-  if (dy>0) { yy+=dy; hh-=dy; srcBytes+=dy*bm->pStride; }
-  if (dr>0) { ww-=dr; }
-  if (db>0) { hh-=db; }
-
-  for (uint32_t iy = 0; iy<hh; ++iy) {
-    uint16_t *d = bits + (yy+iy)*ss + xx;
-    unsigned char *s = srcBytes + iy*bm->pStride;
-    for (uint32_t ix = 0; ix<ww; ++ix) {
-#if 1
-      // 5 step antialiasing
-      unsigned char v = *s++;
-      if (v>200) { // 100% black
-        *d = cc;
-      } else if (v<50) { // 0%
-      } else if (v>150) { // 75%
-        uint16_t nn = *d, nn14 = (nn&(uint16_t(0xe79c)))>>2;
-        *d = nn14 + cc34;
-      } else if (v<100) { // 25%
-        uint16_t nn = *d, nn12 = (nn&(uint16_t(0xf7de)))>>1, nn14 = (nn12&(uint16_t(0xf7de)))>>1, nn34 = nn12+nn14;
-        *d = nn34 + cc14;
-      } else { // 50%
-        uint16_t nn = *d, nn12 = (nn&(uint16_t(0xf7de)))>>1;
-        *d = nn12 + cc12;
-      }
-#else
-      // pure black and white
-      if (*s++ > 128)
-        *d = cc;
-#endif
-      d++;
-    }
-  }
-}
-
-// -----------------------------------------------------------------------------
-
-/**
- Create an empty image.
- All initialisation of members is done in-lin (C++11)
- */
-Fl_Android_565A_Map::Fl_Android_565A_Map()
-{
-}
-
-Fl_Android_565A_Map::Fl_Android_565A_Map(int w, int h)
-{
-  pWidth = w; pStride = w; pHeight = h;
-  pWords = (uint32_t*)calloc(4, w*h);
-}
-
-Fl_Android_565A_Map::~Fl_Android_565A_Map()
-{
-  if (pWords) ::free(pWords);
-}
-
-/**
- Render a bytemap to the screen using the current fl_color.
-
- Bytes are seen as alpha values for the RGB color set by fl_color. For better
- performance, alpha is only rendered in 5 steps. All rendering is offset as
- described in the bytemap, and clipped to the clipping region.
- \param xx, yy bottom left position of the bytemap (baseline for text)
- \param bm bytemap including offsets and size
- \param r clipping rectangle
- */
-void Fl_Android_Graphics_Driver::draw(int xx, int yy, Fl_Android_565A_Map *bm,
-                                      Fl_Rect_Region &r)
-{
-  xx += bm->pXOffset; yy += bm->pYOffset;
-
-  if (xx>r.right()) return;
-  if (yy>r.bottom()) return;
-  if (xx+bm->pWidth < r.left()) return;
-  if (yy+bm->pHeight < r.top()) return;
-
-  uint16_t cc = make565(fl_color()); // TODO: alpha: , cc12 = (cc&0xf7de)>>1, cc14 = (cc12&0xf7de)>>1, cc34 = cc12+cc14;
-  int32_t ss = pStride;
-  uint16_t *bits = pBits;
-  uint32_t ww = bm->pWidth;
-  uint32_t hh = bm->pHeight;
-  uint32_t *srcWords = bm->pWords;
-
-  int dx = r.left()-xx;
-  int dy = r.top()-yy;
-  int dr = (xx+ww)-r.right();
-  int db = (yy+hh)-r.bottom();
-  if (dx>0) { xx+=dx; ww-=dx; srcWords+=dx; }
-  if (dy>0) { yy+=dy; hh-=dy; srcWords+=dy*bm->pStride; }
-  if (dr>0) { ww-=dr; }
-  if (db>0) { hh-=db; }
-
-  for (uint32_t iy = 0; iy<hh; ++iy) {
-    uint16_t *d = bits + (yy+iy)*ss + xx;
-    uint32_t *s = srcWords + iy*bm->pStride;
-    for (uint32_t ix = 0; ix<ww; ++ix) {
-      uint32_t c = *s++;
-      uint8_t alpha = c;
-      if (alpha>0) {
-        uint16_t rgb = c >> 16;
-        // TODO: alpha blending: *d = rgb*a + (*d)*(1-a);
-        *d = rgb;
-      }
-      d++;
-    }
-  }
-}
-
-// -----------------------------------------------------------------------------
-
-/**
- Create a True Type font manager.
- \param fname the name of the font as it appears in the fl_fonts table.
- \param fnum the index into the fl_fonts table
- */
-Fl_Android_Font_Source::Fl_Android_Font_Source(const char *fname, Fl_Font fnum) :
-        pFileBuffer(nullptr),
-        pName(fname),
-        pFontIndex(fnum),
-        pError(false)
-{
-}
-
-/**
- Release all resources.
- */
-Fl_Android_Font_Source::~Fl_Android_Font_Source()
-{
-  if (pFileBuffer) ::free(pFileBuffer);
-  // pFont does not allocate any buffers and needs no destructor
-}
-
-/**
- Attempt to find an load a font file.
- \param name file or asset name
- \return
- */
-bool Fl_Android_Font_Source::load_font(const char *name)
-{
-  if (pFileBuffer) return true;
-  if (!name) return false;
-  bool ret = false;
-  if (name[0]=='@')
-    ret = load_font_asset(name+1);
-  else
-    ret = load_font_file(name);
-  return ret;
-}
-
-/**
- Attempt to load a font through the asset manager.
- \param name file or asset name
- \return
- */
-bool Fl_Android_Font_Source::load_font_asset(const char *name)
-{
-  errno = 0;
-  AAssetManager *aMgr = Fl_Android_Application::get_asset_manager();
-  AAsset *aFile = AAssetManager_open(aMgr, name, AASSET_MODE_STREAMING);
-  if (aFile == nullptr) {
-    Fl_Android_Application::log_w("Can't open font asset at '%s': ",
-                                  name, strerror(errno));
-    return false;
-  }
-  size_t fsize = (size_t)AAsset_getLength(aFile);
-  if (fsize == 0) {
-    Fl_Android_Application::log_w("Can't read font asset at '%s': file is empty",
-                                  name);
-    AAsset_close(aFile);
-    return false;
-  }
-  pFileBuffer = (uint8_t *)malloc(fsize);
-  if (AAsset_read(aFile, pFileBuffer, fsize)<=0) {
-    Fl_Android_Application::log_w("Can't read font asset at '%s': ",
-                                  name, strerror(errno));
-    free(pFileBuffer);
-    pFileBuffer = 0;
-    AAsset_close(aFile);
-    return false;
-  }
-  AAsset_close(aFile);
-  return true;
-}
-
-/**
- Attempt to load a font through the asset manager.
- \param name file or asset name
- \return
- */
-bool Fl_Android_Font_Source::load_font_file(const char *name)
-{
-  char buf[2048];
-  if (name[0] == '$') {
-    // use the system path for fonts
-    snprintf(buf, 2048, "/system/fonts/%s", name + 1);
-  } else {
-    strcpy(buf, name);
-  }
-  FILE *f = fopen(buf, "rb");
-  if (f == nullptr) {
-    Fl_Android_Application::log_w("Can't open font file at '%s': ",
-                                  name, strerror(errno));
-    return false;
-  }
-  fseek(f, 0, SEEK_END);
-  size_t fsize = (size_t)ftell(f);
-  fseek(f, 0, SEEK_SET);
-  if (fsize == 0) {
-    Fl_Android_Application::log_w(
-            "Can't read font file at '%s': file is empty",
-            name);
-    fclose(f);
-    return false;
-  }
-  pFileBuffer = (uint8_t *)malloc(fsize);
-  if (fread(pFileBuffer, 1, fsize, f)<=0) {
-    Fl_Android_Application::log_w("Can't read font file at '%s': ",
-                                  name, strerror(errno));
-    free(pFileBuffer);
-    pFileBuffer = 0;
-    fclose(f);
-    return false;
-  }
-  fclose(f);
-  return true;
-}
-
-
-/**
- Load a True Type font file and initialize the TTF interpreter.
- A copy of the font file must remain in memory for the interpreter to work.
- */
-void Fl_Android_Font_Source::load_font()
-{
-  if (pError) return;
-  if (pFileBuffer==0) {
-    const char *name = fl_fonts[pFontIndex].name;
-
-    // first attempt, try to read a font from wherever the user wishes
-    bool ret = load_font(name);
-
-    // if that did not work, read the old style Android fonts
-    if (!ret && pFontIndex<16)
-      ret = load_font(old_font_names[pFontIndex/4]);
-
-    // if that still didn't work, see if we have the default font asset
-    if (!ret)
-      ret = load_font("@fonts/Roboto-Regular.ttf");
-
-    // still no luck? Well, I guess we can't render anything in this font.
-    if (!ret) {
-      Fl_Android_Application::log_e("Giving up. Can't load font '%s'", name);
-      pError = true;
-      return;
-    }
-    stbtt_InitFont(&pFont, pFileBuffer, stbtt_GetFontOffsetForIndex(pFileBuffer,0));
-  }
-}
-
-/**
- Return a bytemap for the give unicode character.
- \param c unicode character
- \param size height in pixels
- \return a bytemap
- */
-Fl_Android_Bytemap *Fl_Android_Font_Source::get_bytemap(uint32_t c, int size)
-{
-  if (pFileBuffer==0) load_font();
-  if (pError) return nullptr;
-
-  Fl_Android_Bytemap *bm = new Fl_Android_Bytemap();
-
-  float hgt = stbtt_ScaleForPixelHeight(&pFont, size);
-  bm->pBytes = stbtt_GetCodepointBitmap(&pFont, 0, hgt, c,
-                                             &bm->pWidth, &bm->pHeight,
-                                             &bm->pXOffset, &bm->pYOffset);
-  bm->pStride = bm->pWidth;
-
-  int advance, lsb;
-  stbtt_GetCodepointHMetrics(&pFont, c, &advance, &lsb);
-  float scale = stbtt_ScaleForPixelHeight(&pFont, size);
-  bm->pAdvance = (int)((scale * advance)+0.5f);
-
-  return bm;
-}
-
-/**
- Get the width of the character in pixels.
- This is not a good function because character advance also depends on kerning
- which takes the next character in a text line into account. Also, FLTK is
- limited to integer character positions, and so is the Android driver.
- \param c unicode character
- \param size height in pixels
- \return width in pixels to the start of the next character
- */
-float Fl_Android_Font_Source::get_advance(uint32_t c, Fl_Fontsize size)
-{
-  int advance, lsb;
-
-  if (pFileBuffer==0) load_font();
-  if (pError) return 0.0f;
-
-  stbtt_GetCodepointHMetrics(&pFont, c, &advance, &lsb);
-  float scale = stbtt_ScaleForPixelHeight(&pFont, size);
-  return scale * advance;
-}
-
-
-int Fl_Android_Font_Source::get_descent(Fl_Fontsize size)
-{
-  if (pFileBuffer==0) load_font();
-  if (pError) return 0.0f;
-
-  int ascent, descent, lineGap;
-  stbtt_GetFontVMetrics(&pFont, &ascent, &descent, &lineGap);
-  float scale = stbtt_ScaleForPixelHeight(&pFont, size);
-
-  return -(descent*scale-0.5f);
-}
-
-
-// -----------------------------------------------------------------------------
-
-/**
- Create a new font descriptor.
- \param fname name of this font as in fl_fonts
- \param fsrc the font source for this font; there is one single font source
-        for all hights of a single font
- \param fnum index into the fl_fonts array
- \param fsize height of font in pixels
- */
-Fl_Android_Font_Descriptor::Fl_Android_Font_Descriptor(const char *fname, Fl_Android_Font_Source *fsrc, Fl_Font fnum, Fl_Fontsize fsize) :
-        Fl_Font_Descriptor(fname, fsize),
-        pFontSource(fsrc),
-        pFontIndex(fnum)
-{
-  descent = -1;
-  if (!pFontSource) {
-    pFontSource = new Fl_Android_Font_Source(fname, fnum);
-  }
-  // --- We probably must fill these values in:
-  //  Fl_Font_Descriptor *next;
-  //  Fl_Fontsize size; /**< font size */
-  //  Fl_Font_Descriptor(const char* fontname, Fl_Fontsize size);
-  //          FL_EXPORT ~Fl_Font_Descriptor() {}
-  //  short ascent, descent, q_width;
-  //  unsigned int listbase; // base of display list, 0 = none
-}
-
-/**
- Release resources, including all cached unicode character shapes.
- */
-Fl_Android_Font_Descriptor::~Fl_Android_Font_Descriptor()
-{
-#ifdef FL_ALLOW_STL
-  // Life is easy in C++11.
-  for (auto &i: pBytemapTable) {
-    delete i.second; i.second = nullptr;
-  }
-#else
-  for (int i=0; i<256; i++) {
-    if (pBytemapTable[i]) delete pBytemapTable[i];
-  }
-#endif
-}
-
-/*
- Get the width of the character in pixels.
- \param c unicode character
- \return width in pixels to the start of the next character
- */
-float Fl_Android_Font_Descriptor::get_advance(uint32_t c)
-{
-  // TODO: should we use the cached value in the Bytemap?
-  // Yes, we should, because if FLTK requests the width of a character, it is
-  // more than likely to render that character soon after.
-  return pFontSource->get_advance(c, size);
-}
-
-/**
- Get the pixels for a given Unicode character.
-
- Calculating a bitmap is relatively expensive. This class will cache every
- bitmap ever generated. Currently, this is pretty much brute force because
- none of the bitmaps are ever released.
-
- \param c unicode character
- \return a bytemap
- */
-Fl_Android_Bytemap *Fl_Android_Font_Descriptor::get_bytemap(uint32_t c)
-{
-  Fl_Android_Bytemap *bm = 0;
-#ifdef FL_ALLOW_STL
-  auto it = pBytemapTable.find(c);
-  if (it==pBytemapTable.end()) {
-    bm = pFontSource->get_bytemap(c, size);
-    if (bm)
-      pBytemapTable[c] = bm;
-  } else {
-    bm = it->second;
-  }
-#else
-  if (c<256) {
-    if (pBytemapTable[c]) {
-      bm = pBytemapTable[c];
-    } else {
-      bm = pFontSource->get_bytemap(c, size);
-      if (bm)
-        pBytemapTable[c] = bm;
-    }
-  }
-#endif
-  return bm;
-}
-
-
-int Fl_Android_Font_Descriptor::get_descent()
-{
-  if (descent==-1)
-    descent = (short)pFontSource->get_descent(size);
-  return descent;
-}
-
-
-/**
- Find or create a font descriptor for a given font and height.
- \param fnum index into fl_fonts
- \param size height in pixels
- \return an existing oder newly created descriptor
- */
-Fl_Android_Font_Descriptor* Fl_Android_Font_Descriptor::find(Fl_Font fnum, Fl_Fontsize size)
-{
-  Fl_Fontdesc &s = fl_fonts[fnum];
-  if (!s.name) s = fl_fonts[0]; // use 0 if fnum undefined
-
-  Fl_Font_Descriptor *f;
-  for (f = s.first; f; f = f->next) {
-    if (f->size==size) return (Fl_Android_Font_Descriptor*)f;
-  }
-
-  Fl_Android_Font_Source *fsrc = nullptr;
-  if (s.first) fsrc = ((Fl_Android_Font_Descriptor*)s.first)->get_font_source();
-
-  Fl_Android_Font_Descriptor *af = new Fl_Android_Font_Descriptor(s.name, fsrc, fnum, size);
-  af->next = s.first;
-  s.first = af;
-  return af;
-}
-
-// =============================================================================
-
-/**
- Set a font for future use in text rendering calls.
- \param fnum index into fl_fonts
- \param size height in pixels
- */
-void Fl_Android_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
-  font_descriptor( Fl_Android_Font_Descriptor::find(fnum, size) );
-  size_ = size;
-  font_ = fnum;
-}
-
-/**
- Copy a single letter to the screen.
- \param xx, yy position of character on screen
- \param c unicode character
- \return x position of next character on screen
- */
-int Fl_Android_Graphics_Driver::render_letter(int xx, int yy, uint32_t c, Fl_Rect_Region &r)
-{
-  int oxx = xx;
-
-  // find the font descriptor
-  Fl_Android_Font_Descriptor *fd = (Fl_Android_Font_Descriptor*)font_descriptor();
-  if (!fd) return xx; // this should not happen
-
-  Fl_Android_Bytemap *bm = fd->get_bytemap(c);
-  if (!bm) return oxx;
-
-  draw(xx, yy, bm, r);
-
-  return oxx + bm->pAdvance;
-}
-
-/**
- Render a string to screen.
- \param str text in utf-8 encoding
- \param n number of bytes to render
- \param x, y position on screen
- */
-void Fl_Android_Graphics_Driver::draw(const char* str, int n, int x, int y)
-{
-  if (str) {
-    int dx, dy, w, h;
-    text_extents(str, n, dx, dy, w, h);
-    //pClippingRegion.print("<---- clip text to this");
-    //Fl_Rect_Region(x+dx, y+dy, w, h).print(str);
-    for (const auto &it: pClippingRegion.overlapping(Fl_Rect_Region(x+dx, y+dy, w, h))) {
-      Fl_Rect_Region &r = it->clipped_rect();
-      //r.print("Clip");
-      const char *e = str + n;
-      for (int i = 0; i < n;) {
-        int incr = 1;
-        unsigned uniChar = fl_utf8decode(str + i, e, &incr);
-        int x1 = x;
-        x = render_letter(x, y, uniChar, r);
-#if 0
-        // use this to make the character baseline visible
-        Fl_Color old = fl_color();
-        fl_color(FL_RED);
-        fl_xyline(x1, y, x);
-        fl_yxline(x1, y-5, y+5);
-        fl_color(old);
-#endif
-        i += incr;
-      }
-    }
-  }
-}
-
-
-double Fl_Android_Graphics_Driver::width(const char *str, int n)
-{
-  Fl_Android_Font_Descriptor *fd = (Fl_Android_Font_Descriptor*)font_descriptor();
-  if (!fd) return 0;
-
-  int width = 0;
-  const char *e = str+n;
-  for (int i=0; i<n; ) {
-    int incr = 1;
-    unsigned uniChar = fl_utf8decode(str + i, e, &incr);
-    width += ((int)(fd->get_advance(uniChar)+0.5f));
-    i += incr;
-  }
-  return width;
-}
-
-
-double Fl_Android_Graphics_Driver::width(unsigned int uniChar)
-{
-  Fl_Android_Font_Descriptor *fd = (Fl_Android_Font_Descriptor*)font_descriptor();
-  if (!fd) return 0;
-  return ((int)(fd->get_advance(uniChar)+0.5f));
-}
-
-
-Fl_Fontsize Fl_Android_Graphics_Driver::size()
-{
-  Fl_Android_Font_Descriptor *fd = (Fl_Android_Font_Descriptor*)font_descriptor();
-  if (!fd) return 0;
-  return fd->size;
-}
-
-/**
- FIXME: use the actual size of all glyphs, which is easily found in the Bytemap!
- */
-void Fl_Android_Graphics_Driver::text_extents(const char *str, int n, int &dx, int &dy, int &w, int &h)
-{
-  w = width(str, n);
-  h = height();
-  dx = 0;
-  dy = descent() - h;
-}
-
-
-int Fl_Android_Graphics_Driver::height()
-{
-  // This should really be "ascent - descent + lineGap"
-  Fl_Android_Font_Descriptor *fd = (Fl_Android_Font_Descriptor*)font_descriptor();
-  if (!fd) return 0;
-  return fd->size;
-}
-
-
-int Fl_Android_Graphics_Driver::descent()
-{
-  Fl_Android_Font_Descriptor *fd = (Fl_Android_Font_Descriptor*)font_descriptor();
-  if (!fd) return 0;
-  if (fd->descent==-1) fd->get_descent();
-  return fd->descent;
-}
-
-/**
- Get a human-readable string describing the family of this face.
- \param fnum index into font table
- \param ap[out] returns if the face is bold or italic or both.
- \return pointer to a string; don't free, don't write
- */
-const char *Fl_Android_Graphics_Driver::get_font_name(Fl_Font fnum, int* ap)
-{
-  const char *name = fl_fonts[fnum].name;
-  if (ap) {
-    *ap = 0;
-    if (strstr(name, "BoldItalic")) *ap = FL_BOLD_ITALIC;
-    else if (strstr(name, "Bold")) *ap = FL_BOLD;
-    else if (strstr(name, "Italic")) *ap = FL_ITALIC;
-  }
-  return name;
-}
-
-/**
- Gets the string for this face.
- \param num index into font table
- \return pointer to a string; don't free, don't write
- */
-const char *Fl_Android_Graphics_Driver::font_name(int num)
-{
-  // TODO: we should probably beatify the font name, remove file path and
-  // extension, and save the result in fl_fonts[num].fontname ...
-  return fl_fonts[num].name;
-}
-
-/**
- Return an array of sizes in sizep.
- \param fnum index into font table
- \param sizep[out] a static array that contains the single value 0, indicating
-        that all fonts are arbitrarily resizable.
- \return 1, because our array has a size of 1
- */
-int Fl_Android_Graphics_Driver::get_font_sizes(Fl_Font fnum, int*& sizep)
-{
-  static int sSizes[] = { 0 };
-  sizep = sSizes;
-  return 1;
-}
-
-/**
- FLTK will open the display, and add every fonts on the server to the face table.
- TODO: This is not supported under Android.
- \param name basically a wildcard for finding fonts
- \return number of fonts found
- */
-Fl_Font Fl_Android_Graphics_Driver::set_fonts(const char *name)
-{
-  return 16;
-}
-
-/**
- Changes a face.
- \param num index of the font
- \param name Path to font file, prepend $ for system fonts, @ for font assets.
-        The string pointer is simply stored, the string is not copied, so the
-        string must be in static memory.
- */
-void Fl_Android_Graphics_Driver::font_name(int num, const char *name)
-{
-  Fl_Fontdesc *s = fl_fonts + num;
-
-  // if the same font is requested, do nothing
-  if (s && s->name && name && strcmp(s->name, name)==0) {
-    s->name = name;
-    return;
-  }
-
-  // if a font is loaded, delete the all descriptors, caches, and the source
-  Fl_Android_Font_Descriptor *desc = (Fl_Android_Font_Descriptor*)s->first;
-  if (desc) {
-    Fl_Android_Font_Source *src = desc->get_font_source();
-    while (desc) {
-      auto nDesc = (Fl_Android_Font_Descriptor*)desc->next;
-      delete desc; desc = nDesc;
-    }
-    delete src; src = nullptr;
-  }
-  s->name = nullptr;
-  s->fontname[0] = 0;
-  s->first = nullptr;
-
-  // set the new font name
-  if (name) {
-    // the next time the font is used, it will be loaded and initialized
-    s->name = name;
-    s->fontname[0] = 0;
-  }
-}
diff --git src/drivers/Android/Fl_Android_Image_Surface_Driver.cxx src/drivers/Android/Fl_Android_Image_Surface_Driver.cxx
deleted file mode 100644
index 03872fb..0000000
--- src/drivers/Android/Fl_Android_Image_Surface_Driver.cxx
+++ /dev/null
@@ -1,115 +0,0 @@
-//
-// Draw-to-image code for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-
-#include <config.h>
-
-#include "Fl_Android_Graphics_Driver.H"
-//#include "../WinAPI/Fl_WinAPI_Screen_Driver.H"
-#include <FL/Fl_Image_Surface.H>
-#include <FL/fl_draw.H>
-#include <FL/platform.H>
-//#include <windows.h>
-
-
-class Fl_Android_Image_Surface_Driver : public Fl_Image_Surface_Driver {
-#if 0
-  virtual void end_current_(Fl_Surface_Device*);
-public:
-  Window pre_window;
-  int _savedc;
-#endif
-public:
-  Fl_Android_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off)
-  : Fl_Image_Surface_Driver(w, h, high_res, off) {}
-#if 0
-  ~Fl_GDI_Image_Surface_Driver();
-  POINT origin;
-#endif
-  void set_current() override { } // TODO: write me
-  void translate(int x, int y) override { } // TODO: write me
-  void untranslate() override { } // TODO: write me
-  Fl_RGB_Image *image() override { return nullptr; } // TODO: write me
-};
-
-Fl_Image_Surface_Driver *Fl_Image_Surface_Driver::newImageSurfaceDriver(int w, int h, int high_res, Fl_Offscreen off)
-{
-  return new Fl_Android_Image_Surface_Driver(w, h, high_res, off);
-}
-
-
-#if 0
-
-
-Fl_GDI_Image_Surface_Driver::Fl_GDI_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off) : Fl_Image_Surface_Driver(w, h, high_res, 0) {
-  float d =  fl_graphics_driver->scale();
-  if (!off && d != 1 && high_res) {
-    w = int(w*d);
-    h = int(h*d);
-  }
-  HDC gc = (HDC)Fl_Graphics_Driver::default_driver().gc();
-  offscreen = off ? off : CreateCompatibleBitmap( (gc ? gc : fl_GetDC(0) ) , w, h);
-  if (!offscreen) offscreen = CreateCompatibleBitmap(fl_GetDC(0), w, h);
-  driver(new Fl_GDI_Graphics_Driver);
-  if (d != 1 && high_res) ((Fl_GDI_Graphics_Driver*)driver())->scale(d);
-  origin.x = origin.y = 0;
-}
-
-
-Fl_GDI_Image_Surface_Driver::~Fl_GDI_Image_Surface_Driver() {
-  if (offscreen) DeleteObject(offscreen);
-  delete driver();
-}
-
-
-void Fl_GDI_Image_Surface_Driver::set_current() {
-  HDC gc = fl_makeDC(offscreen);
-  driver()->gc(gc);
-  SetWindowOrgEx(gc, origin.x, origin.y, NULL);
-  Fl_Surface_Device::set_current();
-  pre_window = fl_window;
-  _savedc = SaveDC(gc);
-  fl_window=(HWND)offscreen;
-}
-
-
-void Fl_GDI_Image_Surface_Driver::translate(int x, int y) {
-  ((Fl_GDI_Graphics_Driver*)driver())->translate_all(x, y);
-}
-
-
-void Fl_GDI_Image_Surface_Driver::untranslate() {
-  ((Fl_GDI_Graphics_Driver*)driver())->untranslate_all();
-}
-
-
-Fl_RGB_Image* Fl_GDI_Image_Surface_Driver::image()
-{
-  Fl_RGB_Image *image = Fl::screen_driver()->read_win_rectangle( 0, 0, width, height);
-  return image;
-}
-
-
-void Fl_GDI_Image_Surface_Driver::end_current_(Fl_Surface_Device*)
-{
-  HDC gc = (HDC)driver()->gc();
-  GetWindowOrgEx(gc, &origin);
-  RestoreDC(gc, _savedc);
-  DeleteDC(gc);
-  fl_window = pre_window;
-}
-
-#endif
diff --git src/drivers/Android/Fl_Android_Screen_Driver.H src/drivers/Android/Fl_Android_Screen_Driver.H
deleted file mode 100644
index f5fab67..0000000
--- src/drivers/Android/Fl_Android_Screen_Driver.H
+++ /dev/null
@@ -1,176 +0,0 @@
-//
-// Definition of Android screen interface
-// for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_Android_Screen_Driver.H
- \brief Definition of Android screen interface.
- */
-
-#ifndef FL_ANDROID_SCREEN_DRIVER_H
-#define FL_ANDROID_SCREEN_DRIVER_H
-
-#include "../../Fl_Screen_Driver.H"
-#include <FL/Fl_Rect.H>
-#include <android/input.h>
-//#include <windows.h>
-
-extern void (*fl_unlock_function)();
-extern void (*fl_lock_function)();
-
-
-class Fl_Window;
-
-
-class FL_EXPORT Fl_Android_Screen_Driver : public Fl_Screen_Driver
-{
-  // easy access to the super class
-  typedef Fl_Screen_Driver super;
-
-#if 0
-  // No, this is not how we will implement this.
-  enum {
-    /// request attribute for a specific screen; default to screen 0
-    INDEX = 0x0001,     // add an integer in the vararg list
-    /// allow or lock screen rotation
-    ROTATION_MASK = 0x0006, ROTATION_KEEP = 0x0000,
-    MAY_ROTATE = 0x0006, LOCK_TO_PORTRAIT = 0x0002, LOCK_TO_LANDSCAPE = 0x0004,
-    /// screen size
-    SIZE_MASK = 0x0038, SIZE_KEEP = 0x0000,
-    NATIVE_SIZE = 0x0008, // keep the full native screen size
-    FIRST_WINDOW = 0x0010, // adapt the screen to the size of the first window
-    ALL_WINDOWS = 0x0018, // adapt the screen to show all windows
-    FIXED_DIAGONAL = 0x0020, // keep aspect ration at 1:1, add an int for the length of the diagonal
-    // fixed size override the previous flags for portrait and/or landscape
-    FIXED_PORTRAIT_SIZE = 0x0040, // add two int width and height
-    NO_FIXED_PORTRAIT_SIZE = 0x80000040, // release fixed portrait size
-    FIXED_LANDSCAPE_SIZE = 0x0080, // add two int width and height
-    NO_FIXED_LANDSCAPE_SIZE = 0x80000080, // release fixed landscape size
-    // show or hide mobile device screen items
-    SHOW_STATUS_BAR = 0x0080, // top of the screen
-    HIDE_STATUS_BAR = 0x80000080, // top of the screen
-    SHOW_NAVIGATION_BAR = 0x0100, // bottom of the screen
-    HIDE_NAVIGATION_BAR = 0x0100, // bottom of the screen
-  };
-  /// request some attributes from a screen that may or may not be met
-  virtual hint(unsigned int flags, ...);
-#endif
-
-
-private:
-  int handle_queued_events(double time_to_wait);
-  int handle_app_command();
-  int handle_input_event();
-  int handle_keyboard_event(AInputQueue*, AInputEvent*);
-  int handle_mouse_event(AInputQueue*, AInputEvent*);
-
-public:
-  Fl_Android_Screen_Driver();
-
-  virtual void add_timeout(double time, Fl_Timeout_Handler cb, void *argp) override;
-  virtual void repeat_timeout(double time, Fl_Timeout_Handler cb, void *argp) override;
-  virtual int has_timeout(Fl_Timeout_Handler cb, void *argp) override;
-  virtual void remove_timeout(Fl_Timeout_Handler cb, void *argp) override;
-
-  virtual int compose(int &del) override;
-
-  virtual void request_keyboard() override;
-  virtual void release_keyboard() override;
-  int pKeyboardCount = 0;
-
-#if 0
-  Fl_WinAPI_Screen_Driver() : Fl_Screen_Driver() {
-    for (int i = 0; i < MAX_SCREENS; i++) scale_of_screen[i] = 1;
-  }
-  // --- display management
-  virtual int visual(int flags);
-  // --- screen configuration
-  virtual void init();
-#endif
-  virtual int x() override { return 0; } // FIXME:
-  virtual int y() override { return 0; } // FIXME:
-  virtual int w() override { return 600; } // FIXME:
-  virtual int h() override { return 800; } // FIXME:
-  virtual void screen_xywh(int &X, int &Y, int &W, int &H, int n) override
-  { X = 0; Y = 0; W = 600; H = 800; }  // FIXME:
-#if 0
-  virtual void screen_dpi(float &h, float &v, int n=0);
-  int screen_num_unscaled(int x, int y);
-#endif
-  virtual void screen_work_area(int &X, int &Y, int &W, int &H, int n) override
-  { X = 0; Y = 0; W = 600; H = 800; }  // FIXME:
-  // --- audible output
-  virtual void beep(int type) override;
-  // --- global events
-  virtual void flush() override;
-  virtual double wait(double time_to_wait) override;
-#if 0
-  virtual int ready();
-#endif
-  virtual void grab(Fl_Window* win) override;
-#if 0
-  // --- global colors
-  virtual void get_system_colors();
-  virtual const char *get_system_scheme();
-  // --- global timers
-  virtual int dnd(int unused);
-  virtual int compose(int &del);
-  virtual Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h);
-  Fl_RGB_Image *read_win_rectangle_unscaled(int X, int Y, int w, int h);
-#endif
-  virtual int get_mouse(int &x, int &y) override;
-#if 0
-  virtual void enable_im();
-  virtual void disable_im();
-  virtual void open_display_platform();
-  virtual void offscreen_size(Fl_Offscreen off, int &width, int &height);
-#if defined(FLTK_HIDPI_SUPPORT)
-  virtual APP_SCALING_CAPABILITY rescalable() {
-    return PER_SCREEN_APP_SCALING;
-  }
-  virtual float scale(int n) {
-    return scale_of_screen[n];
-  }
-  virtual void scale(int n, float f) {
-    scale_of_screen[n] = f;
-  }
-#else
-  float DWM_scaling_factor();
-#endif
-  virtual float desktop_scale_factor();
-
-#endif
-#if 0
-
-  protected:
-  RECT screens[MAX_SCREENS];
-  RECT work_area[MAX_SCREENS];
-  float dpi[MAX_SCREENS][2];
-  float scale_of_screen[MAX_SCREENS];
-
-  static BOOL CALLBACK screen_cb(HMONITOR mon, HDC, LPRECT r, LPARAM);
-  BOOL screen_cb(HMONITOR mon, HDC, LPRECT r);
-  int get_mouse_unscaled(int &mx, int &my);
-#ifdef FLTK_HIDPI_SUPPORT
-  void init_screen_scale_factors();
-#endif
-
-#endif
-  bool pContentChanged;
-  bool pClearDesktop;
-};
-
-#endif // FL_ANDROID_SCREEN_DRIVER_H
diff --git src/drivers/Android/Fl_Android_Screen_Driver.cxx src/drivers/Android/Fl_Android_Screen_Driver.cxx
deleted file mode 100644
index 2d75eb2..0000000
--- src/drivers/Android/Fl_Android_Screen_Driver.cxx
+++ /dev/null
@@ -1,568 +0,0 @@
-//
-// Android screen interface for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-
-/**
- @cond AndroidDev
- \defgroup AndroidDeveloper Android Developer Documentation
- \{
- */
-
-
-#include <config.h>
-#include "Fl_Android_Screen_Driver.H"
-#include "Fl_Android_Application.H"
-#include "Fl_Android_Graphics_Font.H"
-#include <FL/Fl.H>
-#include <FL/platform.H>
-#include <FL/Fl_Graphics_Driver.H>
-#include <FL/Fl_RGB_Image.H>
-#include <FL/fl_ask.H>
-#include <stdio.h>
-#include <errno.h>
-#include <math.h>
-
-
-/**
- \class Fl_Android_Screen_Driver
-
- Handle Android screen devices.
-
- \todo This class is in an early development stage
- */
-
-
-static void nothing() {}
-void (*fl_unlock_function)() = nothing;
-void (*fl_lock_function)() = nothing;
-
-static void timer_do_callback(int timerIndex);
-
-
-/**
- Creates a driver that manages all Android screen and display related calls.
- */
-Fl_Screen_Driver *Fl_Screen_Driver::newScreenDriver()
-{
-  return new Fl_Android_Screen_Driver();
-}
-
-
-extern int fl_send_system_handlers(void *e);
-
-
-/**
- Create the screen driver.
- */
-Fl_Android_Screen_Driver::Fl_Android_Screen_Driver() :
-  super(),
-  pContentChanged(false),
-  pClearDesktop(false)
-{
-}
-
-
-/**
- Call the FLTK System handler with Android specific events.
-
- \return always 1, assuming the event was handled
-
- \see Fl_Android_Platform_Event
- */
-int Fl_Android_Screen_Driver::handle_app_command()
-{
-  // get the command
-  int8_t cmd = Fl_Android_Application::read_cmd();
-
-  // setup the Android glue and prepare all settings for calling into FLTK
-  Fl_Android_Application::pre_exec_cmd(cmd);
-
-  // call all registered FLTK system handlers
-  Fl::e_number = ((uint32_t)(cmd-Fl_Android_Application::APP_CMD_INPUT_CHANGED)) + FL_ANDROID_EVENT_INPUT_CHANGED;
-  fl_send_system_handlers(nullptr);
-
-  // fixup and finalize application wide command handling
-  Fl_Android_Application::post_exec_cmd(cmd);
-  return 1;
-}
-
-
-int Fl_Android_Screen_Driver::handle_input_event()
-{
-  AInputQueue *queue = Fl_Android_Application::input_event_queue();
-  AInputEvent *event = nullptr;
-
-  if (AInputQueue_getEvent(queue, &event) >= 0) {
-    if (AInputQueue_preDispatchEvent(queue, event)==0) {
-      int consumed = 0;
-      switch (AInputEvent_getType(event)) {
-        case  AINPUT_EVENT_TYPE_KEY:
-          consumed = handle_keyboard_event(queue, event);
-          break;
-        case AINPUT_EVENT_TYPE_MOTION:
-          consumed = handle_mouse_event(queue, event);
-          break;
-        default:
-          // don't do anything. There may be additional event types in the future
-          AInputQueue_finishEvent(queue, event, consumed);
-          break;
-      }
-      // TODO: handle all events here
-//      AInputQueue_finishEvent(queue, event, consumed);
-    }
-  }
-  return 0;
-}
-
-
-int Fl_Android_Screen_Driver::handle_mouse_event(AInputQueue *queue, AInputEvent *event)
-{
-  int ex = Fl::e_x_root = (int)(AMotionEvent_getX(event, 0) * 600 /
-                                 ANativeWindow_getWidth(Fl_Android_Application::native_window()));
-  int ey = Fl::e_y_root = (int)(AMotionEvent_getY(event, 0) * 800 /
-                                 ANativeWindow_getHeight(Fl_Android_Application::native_window()));
-
-  // FIXME: find the window in which the event happened
-  Fl_Window *win = Fl::grab();
-  if (!win) {
-    win = Fl::first_window();
-    if (win && !win->modal()) {
-      while (win) {
-        if (ex >= win->x() && ex < win->x() + win->w() && ey >= win->y() &&
-            ey < win->y() + win->h())
-          break;
-        win = Fl::next_window(win);
-      }
-    }
-  }
-  if (!win) {
-    AInputQueue_finishEvent(queue, event, 0);
-    return 0;
-  }
-
-  if (win) {
-    Fl::e_x = ex-win->x();
-    Fl::e_y = ey-win->y();
-  } else {
-    Fl::e_x = ex;
-    Fl::e_y = ey;
-  }
-
-  Fl::e_state = FL_BUTTON1;
-  Fl::e_keysym = FL_Button + 1;
-  if (AMotionEvent_getAction(event) == AMOTION_EVENT_ACTION_DOWN) {
-    AInputQueue_finishEvent(queue, event, 1);
-    Fl::e_is_click = 1;
-//    Fl_Android_Application::log_i("Mouse push %x %d at %d, %d", win, Fl::event_button(), Fl::event_x(), Fl::event_y());
-    if (win) Fl::handle(FL_PUSH, win); // do NOT send a push event into the "Desktop"
-  } else if (AMotionEvent_getAction(event) == AMOTION_EVENT_ACTION_MOVE) {
-    AInputQueue_finishEvent(queue, event, 1);
-//    Fl_Android_Application::log_i("Mouse drag %x %d at %d, %d", win, Fl::event_button(), Fl::event_x(), Fl::event_y());
-    if (win) Fl::handle(FL_DRAG, win);
-  } else if (AMotionEvent_getAction(event) == AMOTION_EVENT_ACTION_UP) {
-    AInputQueue_finishEvent(queue, event, 1);
-    Fl::e_state = 0;
-//    Fl_Android_Application::log_i("Mouse release %x %d at %d, %d", win, Fl::event_button(), Fl::event_x(), Fl::event_y());
-    if (win) Fl::handle(FL_RELEASE, win);
-  } else {
-    AInputQueue_finishEvent(queue, event, 0);
-  }
-  return 1;
-}
-
-
-/**
- Handle all events in the even queue.
-
- \todo what should this function return?
-
- \param time_to_wait
- \return we do not know
- */
-int Fl_Android_Screen_Driver::handle_queued_events(double time_to_wait)
-{
-  int ret = 0;
-  // Read all pending events.
-  int ident;
-  int events;
-  int delay_millis = time_to_wait*1000;
-  bool done = false;
-
-  int delay = Fl::damage() ? 0 : delay_millis;
-  while (!done) {
-    ident = ALooper_pollOnce(delay, nullptr, &events, nullptr);
-    switch (ident) {
-      case Fl_Android_Application::LOOPER_ID_MAIN:
-        ret = handle_app_command();
-        break;
-      case Fl_Android_Application::LOOPER_ID_INPUT:
-        ret = handle_input_event();
-        break;
-      case Fl_Android_Application::LOOPER_ID_TIMER:
-        timer_do_callback(Fl_Android_Application::receive_timer_index());
-        break;
-      case ALOOPER_POLL_WAKE:
-        Fl_Android_Application::log_e("Someone woke up ALooper_pollOnce.");
-        done = true;
-        break;
-      case ALOOPER_POLL_CALLBACK:
-        Fl_Android_Application::log_e(
-                "Someone added a callback to ALooper_pollOnce.");
-        done = true;
-        break;
-      case ALOOPER_POLL_TIMEOUT:
-        done = true; // timer expired, return to FLTK
-        break;
-      case ALOOPER_POLL_ERROR:
-        Fl_Android_Application::log_e(
-                "Something caused an ERROR in ALooper_pollOnce.");
-        done = true; // return to the app to find the error
-        break;
-      default:
-        Fl_Android_Application::log_e(
-                "Unknown return value from ALooper_pollOnce.");
-        done = true; // return to the app, just in case
-        break;
-    }
-    // we need to repeat this as long as there are messages in the queue, or any
-    // change in the graphical interface will trigger a redraw immediately. To
-    // save time and energy, we want to collect graphics changes and execute
-    // them as soon as no more events are pending.
-    // Setting delay to zero on the second round makes sure that all events
-    // are handled first, and the call returns only when no more
-    // events are pending.
-    delay = 0;
-  }
-  return ret;
-}
-
-
-/**
- Wait for a maximum of `time_to_wait` until something happens.
-
- \param time_to_wait in seconds
- \return We really do not know; check other platforms to see what is
-        consistent here.
-
- \todo return the remaining time to reach 'time_to_wait'
- */
-double Fl_Android_Screen_Driver::wait(double time_to_wait)
-{
-  Fl::run_checks();
-  static int in_idle = 0;
-  if (Fl::idle) {
-    if (!in_idle) {
-      in_idle = 1;
-      Fl::idle();
-      in_idle = 0;
-    }
-    // the idle function may turn off idle, we can then wait:
-    if (Fl::idle) time_to_wait = 0.0;
-  }
-
-  if (time_to_wait==0.0) {
-    // if there is no wait time, handle the event and show the results right away
-    fl_unlock_function();
-    handle_queued_events(time_to_wait);
-    fl_lock_function();
-    // FIXME: kludge to erase a window after it was hidden
-    if (pClearDesktop && fl_graphics_driver) {
-      ((Fl_Android_Graphics_Driver*)fl_graphics_driver)->make_current(nullptr);
-      fl_rectf(0, 0, 600, 800, FL_BLACK);
-      pClearDesktop = false;
-      pContentChanged = true;
-    }
-    Fl::flush();
-  } else {
-    // if there is wait time, show the pending changes and then handle the events
-    // FIXME: kludge to erase a window after it was hidden
-    if (pClearDesktop && fl_graphics_driver) {
-      ((Fl_Android_Graphics_Driver*)fl_graphics_driver)->make_current(nullptr);
-      fl_rectf(0, 0, 600, 800, FL_BLACK);
-      pClearDesktop = false;
-      pContentChanged = true;
-    }
-    Fl::flush();
-    if (Fl::idle && !in_idle) // 'idle' may have been set within flush()
-      time_to_wait = 0.0;
-    fl_unlock_function();
-    handle_queued_events(time_to_wait);
-    fl_lock_function();
-  }
-
-  return 0.0;
-}
-
-
-/**
- On Android, we currently write into a memory buffer and copy
- the content to the screen.
-
- \see fl_flush()
- */
-void Fl_Android_Screen_Driver::flush()
-{
-  Fl_Screen_Driver::flush();
-  // FIXME: do this only if anything actually changed on screen (need to optimize)!
-  if (pContentChanged) {
-    if (Fl_Android_Application::copy_screen())
-      pContentChanged = false;
-  }
-}
-
-
-// ---- timers -----------------------------------------------------------------
-
-
-struct TimerData
-{
-  timer_t handle;
-  struct sigevent sigevent;
-  Fl_Timeout_Handler callback;
-  void *data;
-  bool used;
-  bool triggered;
-  struct itimerspec timeout;
-};
-static TimerData* timerData = nullptr;
-static int NTimerData = 0;
-static int nTimerData = 0;
-
-
-static int allocate_more_timers()
-{
-  if (NTimerData == 0) {
-    NTimerData = 8;
-  }
-  if (NTimerData>256) { // out of timers
-    return -1;
-  }
-  NTimerData *= 2;
-  timerData = (TimerData*)realloc(timerData, sizeof(TimerData) * NTimerData);
-  return nTimerData;
-}
-
-
-static void timer_signal_handler(union sigval data)
-{
-  int timerIndex = data.sival_int;
-  Fl_Android_Application::send_timer_index(timerIndex);
-}
-
-
-static void timer_do_callback(int timerIndex)
-{
-  TimerData& t = timerData[timerIndex];
-  t.triggered = false;
-  if (t.callback) {
-    t.callback(t.data);
-    // TODO: should we release the timer at this point?
-  }
-}
-
-
-void Fl_Android_Screen_Driver::add_timeout(double time, Fl_Timeout_Handler cb, void *data)
-{
-  repeat_timeout(time, cb, data);
-}
-
-
-void Fl_Android_Screen_Driver::repeat_timeout(double time, Fl_Timeout_Handler cb, void *data)
-{
-  int ret = -1;
-  int timerIndex = -1;
-
-  // first, find the timer associated with this handler
-  for (int i = 0; i < nTimerData; ++i) {
-    TimerData& t = timerData[i];
-    if ( (t.used) && (t.callback==cb) && (t.data==data) ) {
-      timerIndex = i;
-      break;
-    }
-  }
-
-  // if we did not have a timer yet, find a free slot
-  if (timerIndex==-1) {
-    for (int i = 0; i < nTimerData; ++i) {
-      if (!timerData[i].used)
-        timerIndex = i;
-      break;
-    }
-  }
-
-  // if that didn't work, allocate more timers
-  if (timerIndex==-1) {
-    if (nTimerData==NTimerData)
-      allocate_more_timers();
-    timerIndex = nTimerData++;
-  }
-
-  // if that didn't work either, we ran out of timers
-  if (timerIndex==-1) {
-    Fl::error("FLTK ran out of timer slots.");
-    return;
-  }
-
-  TimerData& t = timerData[timerIndex];
-  if (!t.used) {
-    t.data = data;
-    t.callback = cb;
-    memset(&t.sigevent, 0, sizeof(struct sigevent));
-    t.sigevent.sigev_notify = SIGEV_THREAD;
-    t.sigevent.sigev_notify_function = timer_signal_handler;
-    t.sigevent.sigev_value.sival_int = timerIndex;
-    ret = timer_create(CLOCK_MONOTONIC, &t.sigevent, &t.handle);
-    if (ret==-1) {
-      Fl_Android_Application::log_e("Can't create timer: %s", strerror(errno));
-      return;
-    }
-    t.used = true;
-  }
-
-  double ff;
-  t.timeout = {
-          { 0, 0 },
-          { (time_t)floor(time), (long)(modf(time, &ff)*1000000000) }
-  };
-  ret = timer_settime(t.handle, 0, &t.timeout, nullptr);
-  if (ret==-1) {
-    Fl_Android_Application::log_e("Can't launch timer: %s", strerror(errno));
-    return;
-  }
-  t.triggered = true;
-}
-
-
-int Fl_Android_Screen_Driver::has_timeout(Fl_Timeout_Handler cb, void *data)
-{
-  for (int i = 0; i < nTimerData; ++i) {
-    TimerData& t = timerData[i];
-    if ( (t.used) && (t.callback==cb) && (t.data==data) ) {
-      return 1;
-    }
-  }
-  return 0;
-}
-
-
-void Fl_Android_Screen_Driver::remove_timeout(Fl_Timeout_Handler cb, void *data)
-{
-  for (int i = 0; i < nTimerData; ++i) {
-    TimerData& t = timerData[i];
-    if ( t.used && (t.callback==cb) && ( (t.data==data) || (data==nullptr) ) ) {
-      if (t.used)
-        timer_delete(t.handle);
-      t.triggered = t.used = false;
-    }
-  }
-}
-
-
-/**
- Play some system sound.
-
- This function plays some rather arbitrary system sounds.
-
- \param type
-
- \see Fl_Screen_Driver::beep(int)
- \see fl_beep(int)
- */
-void Fl_Android_Screen_Driver::beep(int type)
-{
-  int androidSoundID = 93;  // default to TONE_CDMA_ALERT_CALL_GUARD
-  switch (type) {
-    case FL_BEEP_DEFAULT:       androidSoundID = 92; break;
-    case FL_BEEP_MESSAGE:       androidSoundID = 86; break;
-    case FL_BEEP_ERROR:         androidSoundID = 87; break;
-    case FL_BEEP_QUESTION:      androidSoundID = 91; break;
-    case FL_BEEP_PASSWORD:      androidSoundID = 95; break;
-    case FL_BEEP_NOTIFICATION:  androidSoundID = 93; break;
-  }
-  Fl_Android_Java java;
-  if (java.is_attached()) {
-
-    jclass class_tone_generator = java.env()->FindClass("android/media/ToneGenerator");
-
-    jmethodID toneGeneratorConstructor = java.env()->GetMethodID(
-            class_tone_generator, "<init>",
-            "(II)V");
-
-    jobject toneGeneratorObj = java.env()->NewObject(
-            class_tone_generator, toneGeneratorConstructor,
-            4,  // STREAM_ALARM
-            100); // volume
-
-    jmethodID method_start_tone = java.env()->GetMethodID(
-            class_tone_generator,
-            "startTone",
-            "(II)Z");
-
-    java.env()->CallBooleanMethod(
-            toneGeneratorObj, method_start_tone,
-            androidSoundID,
-            1000);
-
-    java.env()->DeleteLocalRef(class_tone_generator);
-    java.env()->DeleteLocalRef(toneGeneratorObj);
-  }
-
-}
-
-
-/**
- Get the current mouse coordinates.
-
- This is used, among other things, to position the FLTK standard dialogs in
- a way that makes it easy to click the most common button. For an Android
- touch screen, this makes no sense at all, which is why we return the center
- of the screen for now.
-
- \todo rethink the dialog positioning scheme for touch devices.
-
- \todo this method assumes a fixed screen resolution
-
- \param [out] x
- \param [out] y
- \return
- */
-int Fl_Android_Screen_Driver::get_mouse(int &x, int &y)
-{
-  x = 600/2;
-  y = 800/2;
-  return 1;
-}
-
-
-void Fl_Android_Screen_Driver::grab(Fl_Window* win)
-{
-  if (win) {
-    if (!Fl::grab_) {
-      // TODO: will we need to fix any focus and/or direct the input stream to a window
-    }
-    Fl::grab_ = win;
-  } else {
-    if (Fl::grab_) {
-      Fl::grab_ = 0;
-    }
-  }
-}
-
-
-/**
- \}
- \endcond
- */
diff --git src/drivers/Android/Fl_Android_Screen_Keyboard.cxx src/drivers/Android/Fl_Android_Screen_Keyboard.cxx
deleted file mode 100644
index a719be1..0000000
--- src/drivers/Android/Fl_Android_Screen_Keyboard.cxx
+++ /dev/null
@@ -1,452 +0,0 @@
-//
-// Android screen interface for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-
-#include <config.h>
-#include "Fl_Android_Screen_Driver.H"
-#include "Fl_Android_Application.H"
-#include "Fl_Android_Graphics_Font.H"
-#include <FL/Fl.H>
-#include <FL/platform.H>
-#include <FL/Fl_Graphics_Driver.H>
-#include <FL/Fl_RGB_Image.H>
-#include <FL/fl_ask.H>
-#include <stdio.h>
-#include <errno.h>
-#include <math.h>
-
-
-// convert an FLTK (X) keysym to a MacOS symbol:
-// This table is in numeric order by FLTK symbol order for binary search.
-static const struct {unsigned short vk, fltk;} vktab[] = {
-        { AKEYCODE_SPACE, ' ' }, { AKEYCODE_APOSTROPHE, '\'' }, { AKEYCODE_COMMA, ',' }, { AKEYCODE_MINUS, '-' }, { AKEYCODE_PERIOD, '.' }, { AKEYCODE_SLASH, '/' },
-        { AKEYCODE_0, '0' }, { AKEYCODE_1, '1' }, { AKEYCODE_2, '2' }, { AKEYCODE_3, '3' },
-        { AKEYCODE_4, '4' }, { AKEYCODE_5, '5' }, { AKEYCODE_6, '6' }, { AKEYCODE_7, '7' },
-        { AKEYCODE_8, '8' }, { AKEYCODE_9, '9' }, { AKEYCODE_SEMICOLON, ';' }, { AKEYCODE_EQUALS, '=' },
-        { AKEYCODE_A, 'A' }, { AKEYCODE_B, 'B' }, { AKEYCODE_C, 'C' }, { AKEYCODE_D, 'D' },
-        { AKEYCODE_E, 'E' }, { AKEYCODE_F, 'F' }, { AKEYCODE_G, 'G' }, { AKEYCODE_H, 'H' },
-        { AKEYCODE_I, 'I' }, { AKEYCODE_J, 'J' }, { AKEYCODE_K, 'K' }, { AKEYCODE_L, 'L' },
-        { AKEYCODE_M, 'M' }, { AKEYCODE_N, 'N' }, { AKEYCODE_O, 'O' }, { AKEYCODE_P, 'P' },
-        { AKEYCODE_Q, 'Q' }, { AKEYCODE_R, 'R' }, { AKEYCODE_S, 'S' }, { AKEYCODE_T, 'T' },
-        { AKEYCODE_U, 'U' }, { AKEYCODE_V, 'V' }, { AKEYCODE_W, 'W' }, { AKEYCODE_X, 'X' },
-        { AKEYCODE_Y, 'Y' }, { AKEYCODE_Z, 'Z' },
-        { AKEYCODE_LEFT_BRACKET, '[' }, { AKEYCODE_BACKSLASH, '\\' }, { AKEYCODE_RIGHT_BRACKET, ']' }, { AKEYCODE_GRAVE, '`' },
-        { AKEYCODE_VOLUME_DOWN, FL_Volume_Down}, { AKEYCODE_MUTE, FL_Volume_Mute}, { AKEYCODE_VOLUME_UP, FL_Volume_Up},
-#if 0
-            #define FL_Volume_Down  0xEF11   /* Volume control down        */
-        513 #define FL_Volume_Mute  0xEF12   /* Mute sound from the system */
-        514 #define FL_Volume_Up    0xEF13   /* Volume control up          */
-        515 #define FL_Media_Play   0xEF14   /* Start playing of audio     */
-        516 #define FL_Media_Stop   0xEF15   /* Stop playing audio         */
-        517 #define FL_Media_Prev   0xEF16   /* Previous track             */
-        518 #define FL_Media_Next   0xEF17   /* Next track                 */
-        519 #define FL_Home_Page    0xEF18   /* Display user's home page   */
-        520 #define FL_Mail         0xEF19   /* Invoke user's mail program */
-        521 #define FL_Search       0xEF1B   /* Search                     */
-        522 #define FL_Back         0xEF26   /* Like back on a browser     */
-        523 #define FL_Forward      0xEF27   /* Like forward on a browser  */
-        524 #define FL_Stop         0xEF28   /* Stop current operation     */
-        525 #define FL_Refresh      0xEF29   /* Refresh the page           */
-        526 #define FL_Sleep        0xEF2F   /* Put system to sleep        */
-        527 #define FL_Favorites    0xEF30   /* Show favorite locations    */
-        528
-#endif
-        { AKEYCODE_DEL, FL_BackSpace }, { AKEYCODE_TAB, FL_Tab }, { AKEYCODE_POUND, FL_Iso_Key }, { AKEYCODE_ENTER, FL_Enter }, /*{ 0x7F, FL_Pause },
-  { 0x7F, FL_Scroll_Lock },*/ { AKEYCODE_ESCAPE, FL_Escape },
-        { AKEYCODE_KANA, FL_Kana}, { AKEYCODE_EISU, FL_Eisu}, { AKEYCODE_YEN, FL_Yen}, /*{ AKEYCODE_UND, FL_JIS_Underscore},*/
-        { AKEYCODE_MOVE_HOME, FL_Home }, { AKEYCODE_DPAD_LEFT, FL_Left },
-        { AKEYCODE_DPAD_UP, FL_Up }, { AKEYCODE_DPAD_RIGHT, FL_Right }, { AKEYCODE_DPAD_DOWN, FL_Down }, { AKEYCODE_PAGE_UP, FL_Page_Up },
-        { AKEYCODE_PAGE_DOWN, FL_Page_Down },  { AKEYCODE_MOVE_END, FL_End }, { AKEYCODE_SYSRQ, FL_Print }, { AKEYCODE_INSERT, FL_Insert },
-        { AKEYCODE_MENU, FL_Menu }, { AKEYCODE_HELP, FL_Help }, { AKEYCODE_NUM_LOCK, FL_Num_Lock },
-        { AKEYCODE_NUMPAD_ENTER, FL_KP_Enter }, { AKEYCODE_NUMPAD_MULTIPLY, FL_KP+'*' }, { AKEYCODE_NUMPAD_ADD, FL_KP+'+'},
-        { AKEYCODE_NUMPAD_COMMA, FL_KP+',' },
-        { AKEYCODE_NUMPAD_SUBTRACT, FL_KP+'-' }, { AKEYCODE_NUMPAD_DOT, FL_KP+'.' }, { AKEYCODE_NUMPAD_DIVIDE, FL_KP+'/' },
-        { AKEYCODE_NUMPAD_0, FL_KP+'0' }, { AKEYCODE_NUMPAD_1, FL_KP+'1' }, { AKEYCODE_NUMPAD_2, FL_KP+'2' }, { AKEYCODE_NUMPAD_3, FL_KP+'3' },
-        { AKEYCODE_NUMPAD_4, FL_KP+'4' }, { AKEYCODE_NUMPAD_5, FL_KP+'5' }, { AKEYCODE_NUMPAD_6, FL_KP+'6' }, { AKEYCODE_NUMPAD_7, FL_KP+'7' },
-        { AKEYCODE_NUMPAD_8, FL_KP+'8' }, { AKEYCODE_NUMPAD_9, FL_KP+'9' }, { AKEYCODE_NUMPAD_EQUALS, FL_KP+'=' },
-        { AKEYCODE_F1, FL_F+1 }, { AKEYCODE_F2, FL_F+2 }, { AKEYCODE_F3, FL_F+3 }, { AKEYCODE_F4, FL_F+4 },
-        { AKEYCODE_F5, FL_F+5 }, { AKEYCODE_F6, FL_F+6 }, { AKEYCODE_F7, FL_F+7 }, { AKEYCODE_F8, FL_F+8 },
-        { AKEYCODE_F9, FL_F+9 }, { AKEYCODE_F10, FL_F+10 }, { AKEYCODE_F11, FL_F+11 }, { AKEYCODE_F12, FL_F+12 },
-        //{ AKEYCODE_F13, FL_F+13 }, { AKEYCODE_F14, FL_F+14 }, { AKEYCODE_F15, FL_F+15 }, { AKEYCODE_F16, FL_F+16 },
-        //{ AKEYCODE_F17, FL_F+17 }, { AKEYCODE_F18, FL_F+18 }, { AKEYCODE_F19, FL_F+19 }, { AKEYCODE_F20, FL_F+20 },
-        { AKEYCODE_SHIFT_LEFT, FL_Shift_L }, { AKEYCODE_SHIFT_RIGHT, FL_Shift_R }, { AKEYCODE_CTRL_LEFT, FL_Control_L }, { AKEYCODE_CTRL_RIGHT, FL_Control_R },
-        { AKEYCODE_CAPS_LOCK, FL_Caps_Lock }, { AKEYCODE_META_LEFT, FL_Meta_L }, { AKEYCODE_META_RIGHT, FL_Meta_R },
-        { AKEYCODE_ALT_LEFT, FL_Alt_L }, { AKEYCODE_ALT_RIGHT, FL_Alt_R }, { AKEYCODE_FORWARD_DEL, FL_Delete }
-};
-
-#if 0
-
-
-//    public static final int KEYCODE_ALL_APPS = 284;
-//    private static final int LAST_KEYCODE = KEYCODE_ALL_APPS;
-
-// Computes the macKeyLookUp table that transforms a Mac OS virtual keycode into an FLTK keysym
-unsigned short *fl_compute_macKeyLookUp()
-{
-  static unsigned short macKeyLookUp[128];
-  memset(macKeyLookUp, 0, sizeof(macKeyLookUp));
-  for (unsigned i = 0; i < sizeof(vktab)/sizeof(*vktab); i++) {
-    macKeyLookUp[vktab[i].vk] = vktab[i].fltk;
-  }
-  return macKeyLookUp;
-}
-
-static int fltk2mac(int fltk) {
-  int a = 0;
-  int b = sizeof(vktab)/sizeof(*vktab);
-  while (a < b) {
-    int c = (a+b)/2;
-    if (vktab[c].fltk == fltk) return vktab[c].vk;
-    if (vktab[c].fltk < fltk) a = c+1; else b = c;
-  }
-  return vktab[a].vk;
-}
-
-//: returns true, if that key was pressed during the last event
-int Fl_Darwin_System_Driver::event_key(int k) {
-  return get_key(k);
-}
-
-//: returns true, if that key is pressed right now
-int Fl_Darwin_System_Driver::get_key(int k) {
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
-  if (&CGEventSourceKeyState != NULL) {
-    return (int)CGEventSourceKeyState(kCGEventSourceStateCombinedSessionState, fltk2mac(k) );
-  }
-  else
-#endif
-  {
-    typedef UInt32 fl_KeyMap[4];
-    fl_KeyMap foo;
-    // use the GetKeys Carbon function
-    typedef void (*keymap_f)(fl_KeyMap);
-    static keymap_f f = NULL;
-    if (!f) f = ( keymap_f )Fl_Darwin_System_Driver::get_carbon_function("GetKeys");
-    (*f)(foo);
-#ifdef MAC_TEST_FOR_KEYCODES
-    static int cnt = 0;
- if (cnt++>1024) {
-  cnt = 0;
-  printf("%08x %08x %08x %08x\n", (ulong*)(foo)[3], (ulong*)(foo)[2], (ulong*)(foo)[1], (ulong*)(foo)[0]);
- }
-#endif
-    unsigned char *b = (unsigned char*)foo;
-    // KP_Enter can be at different locations for Powerbooks vs. desktop Macs
-    if (k==FL_KP_Enter) {
-      return (((b[0x34>>3]>>(0x34&7))&1)||((b[0x4c>>3]>>(0x4c&7))&1));
-    }
-    int i = fltk2mac(k);
-    return (b[i>>3]>>(i&7))&1;
-  }
-}
-
-#endif
-
-
-
-int Fl_Android_Screen_Driver::compose(int &del)
-{
-  int condition;
-  unsigned char ascii = (unsigned char)Fl::e_text[0];
-  condition = (Fl::e_state & (FL_ALT | FL_META | FL_CTRL)) && !(ascii & 128) ;
-  if (condition) { del = 0; return 0;} // this stuff is to be treated as a function key
-  del = Fl::compose_state;
-  Fl::compose_state = 0;
-  // Only insert non-control characters:
-  if ( (!Fl::compose_state) && ! (ascii & ~31 && ascii!=127)) { return 0; }
-  return 1;
-}
-
-
-static unsigned short *key_lookup = nullptr;
-
-// Computes the macKeyLookUp table that transforms a Mac OS virtual keycode into an FLTK keysym
-static unsigned short *compute_key_lookup()
-{
-  static unsigned short AndroidKeyLookUp[AKEYCODE_ALL_APPS+1];
-  memset(AndroidKeyLookUp, 0, sizeof(AndroidKeyLookUp));
-  for (unsigned i = 0; i < sizeof(vktab)/sizeof(*vktab); i++) {
-    AndroidKeyLookUp[vktab[i].vk] = vktab[i].fltk;
-  }
-  return AndroidKeyLookUp;
-}
-
-
-static int android_to_fltk_modifiers(int a)
-{
-  int fl_mod = 0;
-  if (a == AMETA_NONE) return 0;
-  if (a & AMETA_ALT_ON) fl_mod |= FL_ALT;
-  if (a & AMETA_SHIFT_ON) fl_mod |= FL_SHIFT;
-  if (a & AMETA_CTRL_ON) fl_mod |= FL_CTRL;
-  if (a & AMETA_META_ON) fl_mod |= FL_META;
-  if (a & AMETA_NUM_LOCK_ON) fl_mod |= FL_NUM_LOCK;
-  if (a & AMETA_CAPS_LOCK_ON) fl_mod |= FL_CAPS_LOCK;
-  if (a & AMETA_SCROLL_LOCK_ON) fl_mod |= FL_SCROLL_LOCK;
-  // AMETA_SYM_ON
-  // AMETA_FUNCTION_ON
-  // FIXME: we need to add the status of the mouse button(s)
-  // FL_BUTTON1
-  // FL_BUTTON2
-  // FL_BUTTON3
-  return fl_mod;
-}
-
-
-
-int Fl_Android_Screen_Driver::handle_keyboard_event(AInputQueue *queue, AInputEvent *event)
-{
-/*
-int32_t         AKeyEvent_getAction (const AInputEvent *key_event)
- { AKEY_EVENT_ACTION_DOWN = 0, AKEY_EVENT_ACTION_UP = 1, AKEY_EVENT_ACTION_MULTIPLE = 2 }
-> Reading up on ACTION_MULTIPLE also explains how to deal with
-> special or sequences of characters:
-> "If the key code is not KEYCODE_UNKNOWN then the getRepeatCount()
-> method returns the number of times the given key code should be
-> executed. Otherwise, if the key code is KEYCODE_UNKNOWN, then this
-> is a sequence of characters as returned by getCharacters()."
-
-int32_t         AKeyEvent_getFlags (const AInputEvent *key_event)
- {
-  AKEY_EVENT_FLAG_WOKE_HERE = 0x1, AKEY_EVENT_FLAG_SOFT_KEYBOARD = 0x2, AKEY_EVENT_FLAG_KEEP_TOUCH_MODE = 0x4, AKEY_EVENT_FLAG_FROM_SYSTEM = 0x8,
-  AKEY_EVENT_FLAG_EDITOR_ACTION = 0x10, AKEY_EVENT_FLAG_CANCELED = 0x20, AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY = 0x40, AKEY_EVENT_FLAG_LONG_PRESS = 0x80,
-  AKEY_EVENT_FLAG_CANCELED_LONG_PRESS = 0x100, AKEY_EVENT_FLAG_TRACKING = 0x200, AKEY_EVENT_FLAG_FALLBACK = 0x400
-}
-
-int32_t         AKeyEvent_getKeyCode (const AInputEvent *key_event)
- {
-  AKEYCODE_UNKNOWN = 0, AKEYCODE_SOFT_LEFT = 1, AKEYCODE_SOFT_RIGHT = 2, AKEYCODE_HOME = 3,
-  AKEYCODE_BACK = 4, AKEYCODE_CALL = 5, AKEYCODE_ENDCALL = 6, AKEYCODE_0 = 7,
-  AKEYCODE_1 = 8, AKEYCODE_2 = 9, AKEYCODE_3 = 10, AKEYCODE_4 = 11,
-  AKEYCODE_5 = 12, AKEYCODE_6 = 13, AKEYCODE_7 = 14, AKEYCODE_8 = 15,
-  AKEYCODE_9 = 16, AKEYCODE_STAR = 17, AKEYCODE_POUND = 18, AKEYCODE_DPAD_UP = 19,
-  AKEYCODE_DPAD_DOWN = 20, AKEYCODE_DPAD_LEFT = 21, AKEYCODE_DPAD_RIGHT = 22, AKEYCODE_DPAD_CENTER = 23,
-  AKEYCODE_VOLUME_UP = 24, AKEYCODE_VOLUME_DOWN = 25, AKEYCODE_POWER = 26, AKEYCODE_CAMERA = 27,
-  AKEYCODE_CLEAR = 28, AKEYCODE_A = 29, AKEYCODE_B = 30, AKEYCODE_C = 31,
-  AKEYCODE_D = 32, AKEYCODE_E = 33, AKEYCODE_F = 34, AKEYCODE_G = 35, ...
-
-int32_t         AKeyEvent_getScanCode (const AInputEvent *key_event)
-  { AKEY_STATE_UNKNOWN = -1, AKEY_STATE_UP = 0, AKEY_STATE_DOWN = 1, AKEY_STATE_VIRTUAL = 2 }
-
-int32_t         AKeyEvent_getMetaState (const AInputEvent *key_event)
- {
-  AMETA_NONE = 0, AMETA_ALT_ON = 0x02, AMETA_ALT_LEFT_ON = 0x10, AMETA_ALT_RIGHT_ON = 0x20,
-  AMETA_SHIFT_ON = 0x01, AMETA_SHIFT_LEFT_ON = 0x40, AMETA_SHIFT_RIGHT_ON = 0x80, AMETA_SYM_ON = 0x04,
-  AMETA_FUNCTION_ON = 0x08, AMETA_CTRL_ON = 0x1000, AMETA_CTRL_LEFT_ON = 0x2000, AMETA_CTRL_RIGHT_ON = 0x4000,
-  AMETA_META_ON = 0x10000, AMETA_META_LEFT_ON = 0x20000, AMETA_META_RIGHT_ON = 0x40000, AMETA_CAPS_LOCK_ON = 0x100000,
-  AMETA_NUM_LOCK_ON = 0x200000, AMETA_SCROLL_LOCK_ON = 0x400000
-}
-
-int32_t         AKeyEvent_getRepeatCount (const AInputEvent *key_event)
-int64_t         AKeyEvent_getDownTime (const AInputEvent *key_event)
-int64_t         AKeyEvent_getEventTime (const AInputEvent *key_event)
-*/
-  Fl_Android_Application::log_i("Key event: action=%d keyCode=%d metaState=0x%x scanCode=%d",
-                                AKeyEvent_getAction(event),
-                                AKeyEvent_getKeyCode(event),
-                                AKeyEvent_getMetaState(event),
-                                AKeyEvent_getScanCode(event));
-
-  auto keyAction = AKeyEvent_getAction(event);
-  if (keyAction==AKEY_EVENT_ACTION_MULTIPLE) {
-    if (AKeyEvent_getKeyCode(event)==AKEYCODE_UNKNOWN) {
-      // characters are in getCharacters()
-      // String class KeyEvent::getCharacters() [Java]
-      // is there a way to get the true Java event somehow?
-      // override dispatchKeyEvent(android.view.KeyEvent event)
-      //   getDeadChar()
-      //
-      // This seems to work for hardware keys only:
-//      public static interface View.OnKeyListener
-//      boolean onKey (View v,
-//                     int keyCode,
-//                     KeyEvent event)
-      // public static interface KeyEvent.Callback
-      //   onKeyDown(int keyCode, KeyEvent event)
-      // public static interface Window.Callback
-      //   abstract boolean dispatchKeyEvent(KeyEvent event)
-      // view.setOnKeyListener(new OnKeyListener()
-      //
-      // NativeApplication.nativeApplication.addEventListener(KeyboardEvent.KEY_DOWN,checkKeypress);
-      // public function CheckKeypress(event:KeyboardEvent):void
-      //
-      // https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/view/KeyEvent.java
-    } else {
-      // send keycode as many times as getRepeatCount() / AKeyEvent_getRepeatCount(event)
-    }
-  }
-
-  int unicodeKey = 0;
-  auto aKeyCode = AKeyEvent_getKeyCode(event);
-  auto aMetaState = AKeyEvent_getMetaState(event);
-
-  Fl_Android_Java java;
-  if (java.is_attached()) {
-
-    jclass class_key_event = java.env()->FindClass("android/view/KeyEvent");
-
-    jmethodID eventConstructor = java.env()->GetMethodID(
-            class_key_event, "<init>",
-            "(JJIIIIIIII)V");
-
-    jobject eventObj = java.env()->NewObject(
-            class_key_event, eventConstructor,
-            AKeyEvent_getDownTime(event),
-            AKeyEvent_getEventTime(event),
-            AKeyEvent_getAction(event),
-            aKeyCode,
-            AKeyEvent_getRepeatCount(event),
-            aMetaState,
-            AInputEvent_getDeviceId(event),
-            AKeyEvent_getScanCode(event), // hardware keyboard only
-            AKeyEvent_getFlags(event),
-            AInputEvent_getSource(event));
-
-    jmethodID method_get_unicode_char = java.env()->GetMethodID(
-            class_key_event,
-            "getUnicodeChar",
-            "(I)I");
-
-    unicodeKey = java.env()->CallIntMethod(
-            eventObj, method_get_unicode_char,
-            AKeyEvent_getMetaState(event));
-
-    java.env()->DeleteLocalRef(class_key_event);
-    java.env()->DeleteLocalRef(eventObj);
-  }
-
-  // FIXME: do the following thing only on key-down or key-repeat
-  static char buf[8];
-  int len = fl_utf8encode(unicodeKey, buf);
-  if (len >= 0 && len < 8)
-    buf[len] = 0;
-  else
-    buf[0] = 0;
-  Fl_Android_Application::log_i("Unicode: %d Text: %s", unicodeKey, buf);
-
-  if (!key_lookup) key_lookup = compute_key_lookup();
-  Fl::e_keysym = (aKeyCode>AKEYCODE_ALL_APPS) ? 0 : key_lookup[aKeyCode];
-  Fl::e_state = android_to_fltk_modifiers(aMetaState);
-
-  AInputQueue_finishEvent(queue, event, 0);
-
-  Fl_Widget *w = Fl::focus();
-  if (w) {
-    Fl_Window *win = w->window();
-    if (keyAction==AKEY_EVENT_ACTION_DOWN) {
-      if (unicodeKey>0) {
-        Fl::e_text = buf;
-        Fl::e_length = len;
-      } else {
-        Fl::e_text = (char*)"";
-        Fl::e_length = 0;
-      }
-      Fl::handle(FL_KEYBOARD, win);
-    }
-  }
-
-  return 0;
-}
-
-// TODO: different inputs may be able to request different keyboards
-// TODO: knowing the position of the widget, we may be able to avoid
-// obstructing it with the on-screen keyboard
-void Fl_Android_Screen_Driver::request_keyboard( /*o->rect(), o->type()*/ )
-{
-  if (pKeyboardCount==0) {
-    /*
-     * The following line does not work as of March 2018. The pseudo-Java
-     * code that follows is needed to make the virtaul keyboard show.
-     *
-    ANativeActivity_showSoftInput(Fl_Android_Application::get_activity(),
-                                  ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT);
-     *
-     * This is the actual Java code that we recreate in C++
-     *
-    InputMethodManager imm = ( InputMethodManager )getSystemService( Context.INPUT_METHOD_SERVICE );
-    imm.showSoftInput( this.getWindow().getDecorView(), InputMethodManager.SHOW_FORCED );
-     */
-
-    Fl_Android_Java java;
-    if (java.is_attached()) {
-
-      jint lFlags = 0;
-
-      // Retrieves Context.INPUT_METHOD_SERVICE.
-      jclass ClassContext = java.env()->FindClass("android/content/Context");
-      jfieldID FieldINPUT_METHOD_SERVICE = java.env()->GetStaticFieldID(
-              ClassContext,
-              "INPUT_METHOD_SERVICE",
-              "Ljava/lang/String;");
-      jobject INPUT_METHOD_SERVICE = java.env()->GetStaticObjectField(
-              ClassContext,
-              FieldINPUT_METHOD_SERVICE);
-
-      // Runs getSystemService(Context.INPUT_METHOD_SERVICE).
-      jclass ClassInputMethodManager = java.env()->FindClass(
-              "android/view/inputmethod/InputMethodManager");
-      jmethodID MethodGetSystemService = java.env()->GetMethodID(
-              java.native_activity_class(), "getSystemService",
-              "(Ljava/lang/String;)Ljava/lang/Object;");
-      jobject lInputMethodManager = java.env()->CallObjectMethod(
-              java.native_ativity(), MethodGetSystemService,
-              INPUT_METHOD_SERVICE);
-
-      // Runs getWindow().getDecorView().
-      jmethodID MethodGetWindow = java.env()->GetMethodID(
-              java.native_activity_class(), "getWindow",
-              "()Landroid/view/Window;");
-      jobject lWindow = java.env()->CallObjectMethod(
-              java.native_ativity(),
-              MethodGetWindow);
-      jclass ClassWindow = java.env()->FindClass(
-              "android/view/Window");
-      jmethodID MethodGetDecorView = java.env()->GetMethodID(
-              ClassWindow, "getDecorView", "()Landroid/view/View;");
-      jobject lDecorView = java.env()->CallObjectMethod(
-              lWindow,
-              MethodGetDecorView);
-
-      // Runs lInputMethodManager.showSoftInput(...).
-      jmethodID MethodShowSoftInput = java.env()->GetMethodID(
-              ClassInputMethodManager, "showSoftInput",
-              "(Landroid/view/View;I)Z");
-      jboolean lResult = java.env()->CallBooleanMethod(
-              lInputMethodManager, MethodShowSoftInput,
-              lDecorView, lFlags);
-
-      java.env()->DeleteLocalRef(ClassContext);
-      java.env()->DeleteLocalRef(ClassInputMethodManager);
-      java.env()->DeleteLocalRef(ClassWindow);
-
-      java.env()->DeleteLocalRef(INPUT_METHOD_SERVICE);
-      java.env()->DeleteLocalRef(lInputMethodManager);
-      java.env()->DeleteLocalRef(lWindow);
-      java.env()->DeleteLocalRef(lDecorView);
-    }
-  }
-  pKeyboardCount++;
-}
-
-
-void Fl_Android_Screen_Driver::release_keyboard()
-{
-  pKeyboardCount--;
-  if (pKeyboardCount==0) {
-    ANativeActivity_hideSoftInput(Fl_Android_Application::get_activity(),
-                                  ANATIVEACTIVITY_HIDE_SOFT_INPUT_NOT_ALWAYS);
-  }
-}
diff --git src/drivers/Android/Fl_Android_System_Driver.H src/drivers/Android/Fl_Android_System_Driver.H
deleted file mode 100644
index 865b62a..0000000
--- src/drivers/Android/Fl_Android_System_Driver.H
+++ /dev/null
@@ -1,132 +0,0 @@
-//
-// Definition of Android system driver for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2020 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_Android_System_Driver.H
- \brief Definition of Android system driver.
- */
-
-#ifndef FL_ANDROID_SYSTEM_DRIVER_H
-#define FL_ANDROID_SYSTEM_DRIVER_H
-
-#include <string.h>
-#include <FL/fl_string_functions.h>
-#include "../../Fl_System_Driver.H"
-#include <stdarg.h>
-
-/*
- Move everything here that manages the system interface.
-
- There is exactly one system driver.
-
- - filename and pathname management
- - directory and file access
- - system time and system timer
- - multithreading
- */
-
-class Fl_Android_System_Driver : public Fl_System_Driver
-{
-#if 0
-public:
-  static unsigned win_pixmap_bg_color; // the RGB() of the pixmap background color
-  virtual void warning(const char *format, va_list args);
-  virtual void error(const char *format, va_list args);
-  virtual void fatal(const char *format, va_list args);
-  virtual char *utf2mbcs(const char *s);
-  virtual char *getenv(const char *var);
-  virtual int putenv(const char *var) { return ::putenv(fl_strdup(var)); }
-  virtual int open(const char *fnam, int oflags, int pmode);
-  virtual int open_ext(const char *fnam, int binary, int oflags, int pmode);
-  virtual FILE *fopen(const char *fnam, const char *mode);
-  virtual int system(const char *cmd);
-  virtual int execvp(const char *file, char *const *argv);
-  virtual int chmod(const char *fnam, int mode);
-  virtual int access(const char *fnam, int mode);
-  virtual int stat(const char *fnam, struct stat *b);
-  virtual char *getcwd(char *b, int l);
-  virtual int chdir(const char *path);
-  virtual int unlink(const char *fnam);
-  virtual int mkdir(const char *fnam, int mode);
-  virtual int rmdir(const char *fnam);
-  virtual int rename(const char *fnam, const char *newnam);
-  virtual unsigned utf8towc(const char *src, unsigned srclen, wchar_t* dst, unsigned dstlen);
-  virtual unsigned utf8fromwc(char *dst, unsigned dstlen, const wchar_t* src, unsigned srclen);
-  virtual int utf8locale();
-  virtual unsigned utf8to_mb(const char *src, unsigned srclen, char *dst, unsigned dstlen);
-  virtual unsigned utf8from_mb(char *dst, unsigned dstlen, const char *src, unsigned srclen);
-  virtual int clocale_printf(FILE *output, const char *format, va_list args);
-  virtual int clocale_snprintf(char *output, size_t output_size, const char *format, va_list args);
-  virtual int clocale_sscanf(const char *input, const char *format, va_list args);
-  // these 2 are in Fl_get_key_win32.cxx
-  virtual int event_key(int k);
-  virtual int get_key(int k);
-  virtual int filename_list(const char *d, dirent ***list,
-                            int (*sort)(struct dirent **, struct dirent **),
-                            char *errmsg, int errmsg_sz);
-  virtual int filename_expand(char *to,int tolen, const char *from);
-  virtual int filename_relative(char *to, int tolen, const char *from, const char *base);
-  virtual int filename_absolute(char *to, int tolen, const char *from);
-  virtual int filename_isdir(const char *n);
-  virtual int filename_isdir_quick(const char *n);
-  virtual const char *filename_ext(const char *buf);
-  virtual int open_uri(const char *uri, char *msg, int msglen);
-  virtual int use_recent_tooltip_fix() {return 1;}
-  virtual int file_browser_load_filesystem(Fl_File_Browser *browser, char *filename, int lname, Fl_File_Icon *icon);
-  virtual int file_browser_load_directory(const char *directory, char *filename, size_t name_size,
-                                          dirent ***pfiles, Fl_File_Sort_F *sort,
-                                          char *errmsg=NULL, int errmsg_sz=0);
-  virtual void newUUID(char *uuidBuffer);
-  virtual char *preference_rootnode(Fl_Preferences *prefs, Fl_Preferences::Root root, const char *vendor,
-                                    const char *application);
-  virtual void *dlopen(const char *filename);
-  virtual void png_extra_rgba_processing(unsigned char *array, int w, int h);
-  virtual const char *next_dir_sep(const char *start);
-  // these 3 are implemented in Fl_lock.cxx
-  virtual void awake(void*);
-  virtual int lock();
-  virtual void unlock();
-  // this one is implemented in Fl_win32.cxx
-  virtual void* thread_message();
-  virtual int file_type(const char *filename);
-  virtual int pixmap_extra_transparent_processing() {return 1;}
-  // this one is implemented in fl_draw_pixmap.cxx
-  virtual void make_unused_color(unsigned char &r, unsigned char &g, unsigned char &b);
-  virtual const char *home_directory_name();
-  virtual const char *filesystems_label() { return "My Computer"; }
-  virtual int backslash_as_slash() {return 1;}
-  virtual int colon_is_drive() {return 1;}
-  virtual int case_insensitive_filenames() {return 1;}
-  // this one is implemented in Fl_win32.cxx
-  virtual const char *filename_name(const char *buf);
-  // this one is implemented in Fl_win32.cxx
-  virtual void copy(const char *stuff, int len, int clipboard, const char *type);
-  // this one is implemented in Fl_win32.cxx
-  virtual void paste(Fl_Widget &receiver, int clipboard, const char *type);
-  // this one is implemented in Fl_win32.cxx
-  virtual int clipboard_contains(const char *type);
-  // this one is implemented in Fl_win32.cxx
-  virtual void clipboard_notify_change();
-  virtual void add_fd(int fd, int when, Fl_FD_Handler cb, void* = 0);
-  virtual void add_fd(int fd, Fl_FD_Handler cb, void* = 0);
-  virtual void remove_fd(int, int when);
-  virtual void remove_fd(int);
-  virtual void gettime(time_t *sec, int *usec);
-#endif
-  virtual char *strdup(const char *s) {return ::strdup(s);}
-};
-
-#endif // FL_ANDROID_SYSTEM_DRIVER_H
diff --git src/drivers/Android/Fl_Android_System_Driver.cxx src/drivers/Android/Fl_Android_System_Driver.cxx
deleted file mode 100644
index 2e94396..0000000
--- src/drivers/Android/Fl_Android_System_Driver.cxx
+++ /dev/null
@@ -1,957 +0,0 @@
-//
-// Definition of Android system driver.
-//
-// Copyright 2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-#include <config.h>
-#include "Fl_Android_System_Driver.H"
-#include <FL/Fl.H>
-#include <FL/fl_utf8.h>
-#include <FL/fl_string_functions.h>
-#include <FL/filename.H>
-#include <FL/Fl_File_Browser.H>
-#include <FL/Fl_File_Icon.H>
-#include "../../flstring.h"
-
-#if 0
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <windows.h>
-#include <rpc.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/timeb.h>
-#include <shellapi.h>
-#include <wchar.h>
-#include <process.h>
-#include <locale.h>
-#include <time.h>
-#include <direct.h>
-#include <io.h>
-#include <fcntl.h>
-
-// function pointer for the UuidCreate Function
-// RPC_STATUS RPC_ENTRY UuidCreate(UUID __RPC_FAR *Uuid);
-typedef RPC_STATUS (WINAPI *uuid_func)(UUID __RPC_FAR *Uuid);
-
-// Apparently Borland C++ defines DIRECTORY in <direct.h>, which
-// interferes with the Fl_File_Icon enumeration of the same name.
-#  ifdef DIRECTORY
-#    undef DIRECTORY
-#  endif // DIRECTORY
-
-#ifdef __CYGWIN__
-#  include <mntent.h>
-#endif
-
-inline int isdirsep(char c) { return c == '/' || c == '\\'; }
-
-static wchar_t *mbwbuf = NULL;
-static wchar_t *wbuf = NULL;
-static wchar_t *wbuf1 = NULL;
-
-extern "C" {
-  int fl_scandir(const char *dirname, struct dirent ***namelist,
-                 int (*select)(struct dirent *),
-                 int (*compar)(struct dirent **, struct dirent **));
-}
-
-/*
-  Convert a UTF-8 string to Windows wide character encoding (UTF-16).
-
-  This helper function is used throughout this file to convert UTF-8
-  strings to Windows specific UTF-16 encoding for filenames, paths, or
-  other strings to be used by system functions.
-
-  The input string can be a null-terminated string or its length can be
-  provided by the optional argument 'lg'. If 'lg' is omitted or less than 0
-  (default = -1) the string length is determined with strlen(), otherwise
-  'lg' takes precedence. Zero (0) is a valid string length (an empty string).
-
-  The argument 'wbuf' must have been initialized with NULL or a previous
-  call to malloc() or realloc().
-
-  If the converted string doesn't fit into the allocated size of 'wbuf' or if
-  'wbuf' is NULL a new buffer is allocated with realloc(). Hence the pointer
-  'wbuf' can be shared among multiple calls to this function if it has been
-  initialized with NULL (or malloc or realloc) before the first call.
-  Ideally every call to this function has its own static pointer though.
-
-  The return value is either the old value of 'wbuf' (if the string fits)
-  or a pointer at the (re)allocated buffer.
-
-  Pseudo doxygen docs (static function intentionally not documented):
-
-  param[in]     utf8    input string (UTF-8)
-  param[in,out] wbuf    in:  pointer to output string buffer
-                        out: new string (the pointer may be changed)
-  param[in]     lg      optional: input string length (default = -1)
-
-  returns       pointer to string buffer
-*/
-static wchar_t *utf8_to_wchar(const char *utf8, wchar_t *&wbuf, int lg = -1) {
-  unsigned len = (lg >= 0) ? (unsigned)lg : (unsigned)strlen(utf8);
-  unsigned wn = fl_utf8toUtf16(utf8, len, NULL, 0) + 1; // Query length
-  wbuf = (wchar_t *)realloc(wbuf, sizeof(wchar_t) * wn);
-  wn = fl_utf8toUtf16(utf8, len, (unsigned short *)wbuf, wn); // Convert string
-  wbuf[wn] = 0;
-  return wbuf;
-}
-
-/*
-  Convert a Windows wide character (UTF-16) string to UTF-8 encoding.
-
-  This helper function is used throughout this file to convert Windows
-  wide character strings as returned by system functions to UTF-8
-  encoding for internal usage.
-
-  The argument 'utf8' must have been initialized with NULL or a previous
-  call to malloc() or realloc().
-
-  If the converted string doesn't fit into the allocated size of 'utf8' or if
-  'utf8' is NULL a new buffer is allocated with realloc(). Hence the pointer
-  'utf8' can be shared among multiple calls to this function if it has been
-  initialized with NULL (or malloc or realloc) before the first call.
-  Ideally every call to this function has its own static pointer though.
-
-  The return value is either the old value of 'utf8' (if the string fits)
-  or a pointer at the (re)allocated buffer.
-
-  Pseudo doxygen docs (static function intentionally not documented):
-
-  param[in]     wstr    input string (wide character, UTF-16)
-  param[in,out] utf8    in:  pointer to output string buffer
-                        out: new string (pointer may be changed)
-
-  returns       pointer to string buffer
-*/
-static char *wchar_to_utf8(const wchar_t *wstr, char *&utf8) {
-  unsigned len = (unsigned)wcslen(wstr);
-  unsigned wn = fl_utf8fromwc(NULL, 0, wstr, len) + 1; // query length
-  utf8 = (char *)realloc(utf8, wn);
-  wn = fl_utf8fromwc(utf8, wn, wstr, len); // convert string
-  utf8[wn] = 0;
-  return utf8;
-}
-
-#endif
-
-
-/*
- Creates a driver that manages all system related calls.
-
- This function must be implemented once for every platform.
- */
-Fl_System_Driver *Fl_System_Driver::newSystemDriver()
-{
-  return new Fl_Android_System_Driver();
-}
-
-
-#if 0
-
-void Fl_WinAPI_System_Driver::warning(const char *format, va_list args) {
-  // Show nothing for warnings under Windows...
-}
-
-void Fl_WinAPI_System_Driver::error(const char *format, va_list args) {
-
-  char buf[1024];
-  vsnprintf(buf, 1024, format, args);
-  MessageBox(0, buf, "Error", MB_ICONEXCLAMATION | MB_SYSTEMMODAL);
-}
-
-void Fl_WinAPI_System_Driver::fatal(const char *format, va_list args) {
-  char buf[1024];
-  vsnprintf(buf, 1024, format, args);
-  MessageBox(0, buf, "Error", MB_ICONSTOP | MB_SYSTEMMODAL);
-  ::exit(1);
-}
-
-char *Fl_WinAPI_System_Driver::utf2mbcs(const char *utf8) {
-  static char *buf = NULL;
-  if (!utf8) return NULL;
-
-  unsigned len = (unsigned)strlen(utf8);
-
-  unsigned wn = fl_utf8toUtf16(utf8, len, NULL, 0) + 7; // Query length
-  mbwbuf = (wchar_t *)realloc(mbwbuf, sizeof(wchar_t) * wn);
-  len = fl_utf8toUtf16(utf8, len, (unsigned short *)mbwbuf, wn); // Convert string
-  mbwbuf[len] = 0;
-
-  buf = (char*)realloc(buf, len * 6 + 1);
-  len = (unsigned)wcstombs(buf, mbwbuf, len * 6);
-  buf[len] = 0;
-  return buf;
-}
-
-char *Fl_WinAPI_System_Driver::getenv(const char *var) {
-  static char *buf = NULL;
-  wchar_t *ret = _wgetenv(utf8_to_wchar(var, wbuf));
-  if (!ret) return NULL;
-  return wchar_to_utf8(ret, buf);
-}
-
-int Fl_WinAPI_System_Driver::open(const char *fnam, int oflags, int pmode) {
-  utf8_to_wchar(fnam, wbuf);
-  if (pmode == -1) return _wopen(wbuf, oflags);
-  else return _wopen(wbuf, oflags, pmode);
-}
-
-int Fl_WinAPI_System_Driver::open_ext(const char *fnam, int binary, int oflags, int pmode) {
-  if (oflags == 0) oflags = _O_RDONLY;
-  oflags |= (binary ? _O_BINARY : _O_TEXT);
-  return open(fnam, oflags, pmode);
-}
-
-FILE *Fl_WinAPI_System_Driver::fopen(const char *fnam, const char *mode) {
-  utf8_to_wchar(fnam, wbuf);
-  utf8_to_wchar(mode, wbuf1);
-  return _wfopen(wbuf, wbuf1);
-}
-
-int Fl_WinAPI_System_Driver::system(const char *cmd) {
-# ifdef __MINGW32__
-  return ::system(fl_utf2mbcs(cmd));
-# else
-  return _wsystem(utf8_to_wchar(cmd, wbuf));
-# endif
-}
-
-int Fl_WinAPI_System_Driver::execvp(const char *file, char *const *argv) {
-# ifdef __MINGW32__
-  return _execvp(fl_utf2mbcs(file), argv);
-# else
-  wchar_t **ar;
-  utf8_to_wchar(file, wbuf);
-
-  int i = 0, n = 0;
-  while (argv[i]) {i++; n++;}
-  ar = (wchar_t **)malloc(sizeof(wchar_t *) * (n + 1));
-  i = 0;
-  while (i <= n) {
-    unsigned wn;
-    unsigned len = (unsigned)strlen(argv[i]);
-    wn = fl_utf8toUtf16(argv[i], len, NULL, 0) + 1; // Query length
-    ar[i] = (wchar_t *)malloc(sizeof(wchar_t) * wn);
-    wn = fl_utf8toUtf16(argv[i], len, (unsigned short *)ar[i], wn); // Convert string
-    ar[i][wn] = 0;
-    i++;
-  }
-  ar[n] = NULL;
-  _wexecvp(wbuf, ar);   // STR #3040
-  i = 0;
-  while (i < n) {
-    free(ar[i]);
-    i++;
-  }
-  free(ar);
-  return -1;            // STR #3040
-#endif
-}
-
-int Fl_WinAPI_System_Driver::chmod(const char *fnam, int mode) {
-  return _wchmod(utf8_to_wchar(fnam, wbuf), mode);
-}
-
-int Fl_WinAPI_System_Driver::access(const char *fnam, int mode) {
-  return _waccess(utf8_to_wchar(fnam, wbuf), mode);
-}
-
-int Fl_WinAPI_System_Driver::stat(const char *fnam, struct stat *b) {
-
-  // remove trailing '/' or '\'
-  unsigned len = (unsigned)strlen(fnam);
-  if (len > 0 && (fnam[len-1] == '/' || fnam[len-1] == '\\'))
-    len--;
-  // convert filename and execute _wstat()
-  return _wstat(utf8_to_wchar(fnam, wbuf, len), (struct _stat *)b);
-}
-
-char *Fl_WinAPI_System_Driver::getcwd(char *buf, int len) {
-
-  static wchar_t *wbuf = NULL;
-  wbuf = (wchar_t *)realloc(wbuf, sizeof(wchar_t) * (len + 1));
-  wchar_t *ret = _wgetcwd(wbuf, len);
-  if (!ret) return NULL;
-
-  unsigned dstlen = (unsigned)len;
-  len = (int)wcslen(wbuf);
-  dstlen = fl_utf8fromwc(buf, dstlen, wbuf, (unsigned)len);
-  buf[dstlen] = 0;
-  return buf;
-}
-
-int Fl_WinAPI_System_Driver::chdir(const char *path) {
-  return _wchdir(utf8_to_wchar(path, wbuf));
-}
-
-int Fl_WinAPI_System_Driver::unlink(const char *fnam) {
-  return _wunlink(utf8_to_wchar(fnam, wbuf));
-}
-
-int Fl_WinAPI_System_Driver::mkdir(const char *fnam, int mode) {
-  return _wmkdir(utf8_to_wchar(fnam, wbuf));
-}
-
-int Fl_WinAPI_System_Driver::rmdir(const char *fnam) {
-  return _wrmdir(utf8_to_wchar(fnam, wbuf));
-}
-
-int Fl_WinAPI_System_Driver::rename(const char *fnam, const char *newnam) {
-  utf8_to_wchar(fnam, wbuf);
-  utf8_to_wchar(newnam, wbuf1);
-  return _wrename(wbuf, wbuf1);
-}
-
-// Two Windows-specific functions fl_utf8_to_locale() and fl_locale_to_utf8()
-// from file fl_utf8.cxx are put here for API compatibility
-
-static char *buf = NULL;
-static int buf_len = 0;
-static unsigned short *wbufa = NULL;
-unsigned int fl_codepage = 0;
-
-
-// FIXME: This should *maybe* return 'const char *' instead of 'char *'
-char *fl_utf8_to_locale(const char *s, int len, UINT codepage)
-{
-  if (!s) return (char *)"";
-  int l = 0;
-  unsigned wn = fl_utf8toUtf16(s, len, NULL, 0); // Query length
-  wn = wn * 2 + 1;
-  if (wn >= (unsigned)buf_len) {
-    buf_len = wn;
-    buf = (char*) realloc(buf, buf_len);
-    wbufa = (unsigned short*) realloc(wbufa, buf_len * sizeof(short));
-  }
-  if (codepage < 1) codepage = fl_codepage;
-  l = fl_utf8toUtf16(s, len, wbufa, wn); // Convert string
-  wbufa[l] = 0;
-  buf[l] = 0;
-  l = WideCharToMultiByte(codepage, 0, (WCHAR*)wbufa, l, buf, buf_len, NULL, NULL);
-  if (l < 0) l = 0;
-  buf[l] = 0;
-  return buf;
-}
-
-// FIXME: This should maybe return 'const char *' instead of 'char *'
-char *fl_locale_to_utf8(const char *s, int len, UINT codepage)
-{
-  if (!s) return (char *)"";
-  int l = 0;
-  if (buf_len < len * 5 + 1) {
-    buf_len = len * 5 + 1;
-    buf = (char*) realloc(buf, buf_len);
-    wbufa = (unsigned short*) realloc(wbufa, buf_len * sizeof(short));
-  }
-  if (codepage < 1) codepage = fl_codepage;
-  buf[l] = 0;
-
-  l = MultiByteToWideChar(codepage, 0, s, len, (WCHAR*)wbufa, buf_len);
-  if (l < 0) l = 0;
-  wbufa[l] = 0;
-  l = fl_utf8fromwc(buf, buf_len, (wchar_t*)wbufa, l);
-  buf[l] = 0;
-  return buf;
-}
-
-///////////////////////////////////
-
-unsigned Fl_WinAPI_System_Driver::utf8towc(const char *src, unsigned srclen, wchar_t *dst, unsigned dstlen) {
-  return fl_utf8toUtf16(src, srclen, (unsigned short*)dst, dstlen);
-}
-
-unsigned Fl_WinAPI_System_Driver::utf8fromwc(char *dst, unsigned dstlen, const wchar_t *src, unsigned srclen)
-{
-  unsigned i = 0;
-  unsigned count = 0;
-  if (dstlen) for (;;) {
-    unsigned ucs;
-    if (i >= srclen) {
-      dst[count] = 0;
-      return count;
-    }
-    ucs = src[i++];
-    if (ucs < 0x80U) {
-      dst[count++] = ucs;
-      if (count >= dstlen) {dst[count-1] = 0; break;}
-    } else if (ucs < 0x800U) { /* 2 bytes */
-      if (count+2 >= dstlen) {dst[count] = 0; count += 2; break;}
-      dst[count++] = 0xc0 | (ucs >> 6);
-      dst[count++] = 0x80 | (ucs & 0x3F);
-    } else if (ucs >= 0xd800 && ucs <= 0xdbff && i < srclen &&
-               src[i] >= 0xdc00 && src[i] <= 0xdfff) {
-      /* surrogate pair */
-      unsigned ucs2 = src[i++];
-      ucs = 0x10000U + ((ucs&0x3ff)<<10) + (ucs2&0x3ff);
-      /* all surrogate pairs turn into 4-byte UTF-8 */
-      if (count+4 >= dstlen) {dst[count] = 0; count += 4; break;}
-      dst[count++] = 0xf0 | (ucs >> 18);
-      dst[count++] = 0x80 | ((ucs >> 12) & 0x3F);
-      dst[count++] = 0x80 | ((ucs >> 6) & 0x3F);
-      dst[count++] = 0x80 | (ucs & 0x3F);
-    } else {
-      /* all others are 3 bytes: */
-      if (count+3 >= dstlen) {dst[count] = 0; count += 3; break;}
-      dst[count++] = 0xe0 | (ucs >> 12);
-      dst[count++] = 0x80 | ((ucs >> 6) & 0x3F);
-      dst[count++] = 0x80 | (ucs & 0x3F);
-    }
-  }
-  /* we filled dst, measure the rest: */
-  while (i < srclen) {
-    unsigned ucs = src[i++];
-    if (ucs < 0x80U) {
-      count++;
-    } else if (ucs < 0x800U) { /* 2 bytes */
-      count += 2;
-    } else if (ucs >= 0xd800 && ucs <= 0xdbff && i < srclen-1 &&
-               src[i+1] >= 0xdc00 && src[i+1] <= 0xdfff) {
-      /* surrogate pair */
-      ++i;
-      count += 4;
-    } else {
-      count += 3;
-    }
-  }
-  return count;
-}
-
-int Fl_WinAPI_System_Driver::utf8locale()
-{
-  static int ret = (GetACP() == CP_UTF8);
-  return ret;
-}
-
-unsigned Fl_WinAPI_System_Driver::utf8to_mb(const char *src, unsigned srclen, char *dst, unsigned dstlen) {
-  wchar_t lbuf[1024];
-  wchar_t *buf = lbuf;
-  unsigned length = fl_utf8towc(src, srclen, buf, 1024);
-  unsigned ret;
-  if (length >= 1024) {
-    buf = (wchar_t*)(malloc((length+1)*sizeof(wchar_t)));
-    fl_utf8towc(src, srclen, buf, length+1);
-  }
-  if (dstlen) {
-    // apparently this does not null-terminate, even though msdn documentation claims it does:
-    ret =
-    WideCharToMultiByte(GetACP(), 0, buf, length, dst, dstlen, 0, 0);
-    dst[ret] = 0;
-  }
-  // if it overflows or measuring length, get the actual length:
-  if (dstlen==0 || ret >= dstlen-1)
-    ret = WideCharToMultiByte(GetACP(), 0, buf, length, 0, 0, 0, 0);
-  if (buf != lbuf) free(buf);
-  return ret;
-}
-
-unsigned Fl_WinAPI_System_Driver::utf8from_mb(char *dst, unsigned dstlen, const char *src, unsigned srclen) {
-  wchar_t lbuf[1024];
-  wchar_t *buf = lbuf;
-  unsigned length;
-  unsigned ret;
-  length = MultiByteToWideChar(GetACP(), 0, src, srclen, buf, 1024);
-  if ((length == 0)&&(GetLastError()==ERROR_INSUFFICIENT_BUFFER)) {
-    length = MultiByteToWideChar(GetACP(), 0, src, srclen, 0, 0);
-    buf = (wchar_t*)(malloc(length*sizeof(wchar_t)));
-    MultiByteToWideChar(GetACP(), 0, src, srclen, buf, length);
-  }
-  ret = fl_utf8fromwc(dst, dstlen, buf, length);
-  if (buf != lbuf) free((void*)buf);
-  return ret;
-}
-
-int Fl_WinAPI_System_Driver::clocale_printf(FILE *output, const char *format, va_list args) {
-#if defined(_MSC_VER) && (_MSC_VER >= 1400 /*Visual Studio 2005*/)
-  static _locale_t c_locale = _create_locale(LC_NUMERIC, "C");
-  int retval = _vfprintf_l(output, format, c_locale, args);
-#else
-  char *saved_locale = setlocale(LC_NUMERIC, NULL);
-  setlocale(LC_NUMERIC, "C");
-  int retval = vfprintf(output, format, args);
-  setlocale(LC_NUMERIC, saved_locale);
-#endif
-  return retval;
-}
-
-int Fl_WinAPI_System_Driver::clocale_snprintf(char *output, size_t output_size, const char *format, va_list args) {
-  //... write me
-}
-
-int Fl_WinAPI_System_Driver::clocale_sscanf(const char *input, const char *format, va_list args) {
-  //... write me
-}
-
-int Fl_WinAPI_System_Driver::filename_list(const char *d, dirent ***list,
-                                           int (*sort)(struct dirent **, struct dirent **),
-                                           char *errmsg, int errmsg_sz ) {
-  // For Windows we have a special scandir implementation that uses
-  // the Win32 "wide" functions for lookup, avoiding the code page mess
-  // entirely. It also fixes up the trailing '/'.
-  return fl_scandir(d, list, 0, sort, errmsg, errmsg_sz);
-}
-
-int Fl_WinAPI_System_Driver::filename_expand(char *to, int tolen, const char *from) {
-  char *temp = new char[tolen];
-  strlcpy(temp,from, tolen);
-  char *start = temp;
-  char *end = temp+strlen(temp);
-  int ret = 0;
-  for (char *a=temp; a<end; ) { // for each slash component
-    char *e; for (e=a; e<end && !isdirsep(*e); e++) {/*empty*/} // find next slash
-    const char *value = 0; // this will point at substitute value
-    switch (*a) {
-      case '~': // a home directory name
-        if (e <= a+1) { // current user's directory
-          value = getenv("HOME");
-        }
-        break;
-      case '$':         /* an environment variable */
-      {char t = *e; *(char *)e = 0; value = getenv(a+1); *(char *)e = t;}
-        break;
-    }
-    if (value) {
-      // substitutions that start with slash delete everything before them:
-      if (isdirsep(value[0])) start = a;
-      // also if it starts with "A:"
-      if (value[0] && value[1]==':') start = a;
-      int t = (int) strlen(value); if (isdirsep(value[t-1])) t--;
-      if ((end+1-e+t) >= tolen) end += tolen - (end+1-e+t);
-      memmove(a+t, e, end+1-e);
-      end = a+t+(end-e);
-      *end = '\0';
-      memcpy(a, value, t);
-      ret++;
-    } else {
-      a = e+1;
-      if (*e == '\\') {*e = '/'; ret++;} // ha ha!
-    }
-  }
-  strlcpy(to, start, tolen);
-  delete[] temp;
-  return ret;
-}
-
-int                                                     // O - 0 if no change, 1 if changed
-Fl_WinAPI_System_Driver::filename_relative(char *to,    // O - Relative filename
-                                    int        tolen,   // I - Size of "to" buffer
-                                    const char *from,   // I - Absolute filename
-                                    const char *base)   // I - Find path relative to this path
-{
-  char          *newslash;              // Directory separator
-  const char    *slash;                 // Directory separator
-  char          *cwd = 0L, *cwd_buf = 0L;
-  if (base) cwd = cwd_buf = fl_strdup(base);
-
-  // return if "from" is not an absolute path
-  if (from[0] == '\0' ||
-      (!isdirsep(*from) && !isalpha(*from) && from[1] != ':' &&
-       !isdirsep(from[2]))) {
-        strlcpy(to, from, tolen);
-        if (cwd_buf) free(cwd_buf);
-        return 0;
-      }
-
-  // return if "cwd" is not an absolute path
-  if (!cwd || cwd[0] == '\0' ||
-      (!isdirsep(*cwd) && !isalpha(*cwd) && cwd[1] != ':' &&
-       !isdirsep(cwd[2]))) {
-        strlcpy(to, from, tolen);
-        if (cwd_buf) free(cwd_buf);
-        return 0;
-      }
-
-  // convert all backslashes into forward slashes
-  for (newslash = strchr(cwd, '\\'); newslash; newslash = strchr(newslash + 1, '\\'))
-    *newslash = '/';
-
-  // test for the exact same string and return "." if so
-  if (!strcasecmp(from, cwd)) {
-    strlcpy(to, ".", tolen);
-    free(cwd_buf);
-    return (1);
-  }
-
-  // test for the same drive. Return the absolute path if not
-  if (tolower(*from & 255) != tolower(*cwd & 255)) {
-    // Not the same drive...
-    strlcpy(to, from, tolen);
-    free(cwd_buf);
-    return 0;
-  }
-
-  // compare the path name without the drive prefix
-  from += 2; cwd += 2;
-
-  // compare both path names until we find a difference
-  for (slash = from, newslash = cwd;
-       *slash != '\0' && *newslash != '\0';
-       slash ++, newslash ++)
-    if (isdirsep(*slash) && isdirsep(*newslash)) continue;
-    else if (tolower(*slash & 255) != tolower(*newslash & 255)) break;
-
-  // skip over trailing slashes
-  if ( *newslash == '\0' && *slash != '\0' && !isdirsep(*slash)
-      &&(newslash==cwd || !isdirsep(newslash[-1])) )
-    newslash--;
-
-  // now go back to the first character of the first differing paths segment
-  while (!isdirsep(*slash) && slash > from) slash --;
-  if (isdirsep(*slash)) slash ++;
-
-  // do the same for the current dir
-  if (isdirsep(*newslash)) newslash --;
-  if (*newslash != '\0')
-    while (!isdirsep(*newslash) && newslash > cwd) newslash --;
-
-  // prepare the destination buffer
-  to[0]         = '\0';
-  to[tolen - 1] = '\0';
-
-  // now add a "previous dir" sequence for every following slash in the cwd
-  while (*newslash != '\0') {
-    if (isdirsep(*newslash)) strlcat(to, "../", tolen);
-    newslash ++;
-  }
-
-  // finally add the differing path from "from"
-  strlcat(to, slash, tolen);
-
-  free(cwd_buf);
-  return 1;
-}
-
-int Fl_WinAPI_System_Driver::filename_absolute(char *to, int tolen, const char *from) {
-  if (isdirsep(*from) || *from == '|' || from[1]==':') {
-    strlcpy(to, from, tolen);
-    return 0;
-  }
-  char *a;
-  char *temp = new char[tolen];
-  const char *start = from;
-  a = getcwd(temp, tolen);
-  if (!a) {
-    strlcpy(to, from, tolen);
-    delete[] temp;
-    return 0;
-  }
-  for (a = temp; *a; a++) if (*a=='\\') *a = '/'; // ha ha
-  if (isdirsep(*(a-1))) a--;
-  /* remove intermediate . and .. names: */
-  while (*start == '.') {
-    if (start[1]=='.' && isdirsep(start[2])) {
-      char *b;
-      for (b = a-1; b >= temp && !isdirsep(*b); b--) {/*empty*/}
-      if (b < temp) break;
-      a = b;
-      start += 3;
-    } else if (isdirsep(start[1])) {
-      start += 2;
-    } else if (!start[1]) {
-      start ++; // Skip lone "."
-      break;
-    } else
-      break;
-  }
-  *a++ = '/';
-  strlcpy(a,start,tolen - (a - temp));
-  strlcpy(to, temp, tolen);
-  delete[] temp;
-  return 1;
-}
-
-int Fl_WinAPI_System_Driver::filename_isdir(const char *n)
-{
-  struct _stat  s;
-  char          fn[FL_PATH_MAX];
-  int           length;
-  length = (int) strlen(n);
-  // This workaround brought to you by the fine folks at Microsoft!
-  // (read lots of sarcasm in that...)
-  if (length < (int)(sizeof(fn) - 1)) {
-    if (length < 4 && isalpha(n[0]) && n[1] == ':' &&
-        (isdirsep(n[2]) || !n[2])) {
-      // Always use D:/ for drive letters
-      fn[0] = n[0];
-      strcpy(fn + 1, ":/");
-      n = fn;
-    } else if (length > 0 && isdirsep(n[length - 1])) {
-      // Strip trailing slash from name...
-      length --;
-      memcpy(fn, n, length);
-      fn[length] = '\0';
-      n = fn;
-    }
-  }
-  return !_stat(n, &s) && (s.st_mode & _S_IFDIR);
-}
-
-int Fl_WinAPI_System_Driver::filename_isdir_quick(const char *n)
-{
-  // Do a quick optimization for filenames with a trailing slash...
-  if (*n && isdirsep(n[strlen(n) - 1])) return 1;
-  return filename_isdir(n);
-}
-
-const char *Fl_WinAPI_System_Driver::filename_ext(const char *buf) {
-  const char *q = 0;
-  const char *p = buf;
-  for (p = buf; *p; p++) {
-    if (isdirsep(*p) ) q = 0;
-    else if (*p == '.') q = p;
-  }
-  return q ? q : p;
-}
-
-int Fl_WinAPI_System_Driver::open_uri(const char *uri, char *msg, int msglen)
-{
-  if (msg) snprintf(msg, msglen, "open %s", uri);
-  return (int)(ShellExecute(HWND_DESKTOP, "open", uri, NULL, NULL, SW_SHOW) > (void *)32);
-}
-
-int Fl_WinAPI_System_Driver::file_browser_load_filesystem(Fl_File_Browser *browser, char *filename, int lname, Fl_File_Icon *icon)
-{
-  int num_files = 0;
-#  ifdef __CYGWIN__
-  //
-  // Cygwin provides an implementation of setmntent() to get the list
-  // of available drives...
-  //
-  FILE          *m = setmntent("/-not-used-", "r");
-  struct mntent *p;
-  while ((p = getmntent (m)) != NULL) {
-    browser->add(p->mnt_dir, icon);
-    num_files ++;
-  }
-  endmntent(m);
-#  else
-  //
-  // Normal Windows code uses drive bits...
-  //
-  DWORD drives;         // Drive available bits
-  drives = GetLogicalDrives();
-  for (int i = 'A'; i <= 'Z'; i ++, drives >>= 1)
-    if (drives & 1)
-    {
-      sprintf(filename, "%c:/", i);
-      if (i < 'C') // see also: GetDriveType and GetVolumeInformation in Windows
-        browser->add(filename, icon);
-      else
-        browser->add(filename, icon);
-      num_files ++;
-    }
-#  endif // __CYGWIN__
-  return num_files;
-}
-
-int Fl_WinAPI_System_Driver::file_browser_load_directory(const char *directory, char *filename,
-                                                         size_t name_size, dirent ***pfiles,
-                                                         Fl_File_Sort_F *sort,
-                                                         char *errmsg, int errmsg_sz)
-{
-  strlcpy(filename, directory, name_size);
-  int i = (int) (strlen(filename) - 1);
-  if (i == 2 && filename[1] == ':' &&
-      (filename[2] == '/' || filename[2] == '\\'))
-    filename[2] = '/';
-  else if (filename[i] != '/' && filename[i] != '\\')
-    strlcat(filename, "/", name_size);
-  return filename_list(filename, pfiles, sort, errmsg, errmsg_sz);
-}
-
-void Fl_WinAPI_System_Driver::newUUID(char *uuidBuffer)
-{
-  // First try and use the win API function UuidCreate(), but if that is not
-  // available, fall back to making something up from scratch.
-  // We do not want to link against the Rpcrt4.dll, as we will rarely use it,
-  // so we load the DLL dynamically, if it is available, and work from there.
-  static HMODULE hMod = NULL;
-  UUID ud;
-  UUID *pu = &ud;
-  int got_uuid = 0;
-
-  if (!hMod) {          // first time in?
-    hMod = LoadLibrary("Rpcrt4.dll");
-  }
-
-  if (hMod) {           // do we have a usable handle to Rpcrt4.dll?
-    uuid_func uuid_crt = (uuid_func)GetProcAddress(hMod, "UuidCreate");
-    if (uuid_crt != NULL) {
-      RPC_STATUS rpc_res = uuid_crt(pu);
-      if ( // is the return status OK for our needs?
-          (rpc_res == RPC_S_OK) ||              // all is well
-          (rpc_res == RPC_S_UUID_LOCAL_ONLY) || // only unique to this machine
-          (rpc_res == RPC_S_UUID_NO_ADDRESS)    // probably only locally unique
-          ) {
-        got_uuid = -1;
-        sprintf(uuidBuffer, "%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
-                pu->Data1, pu->Data2, pu->Data3, pu->Data4[0], pu->Data4[1],
-                pu->Data4[2], pu->Data4[3], pu->Data4[4],
-                pu->Data4[5], pu->Data4[6], pu->Data4[7]);
-      }
-    }
-  }
-  if (got_uuid == 0) {          // did not make a UUID - use fallback logic
-    unsigned char b[16];
-    time_t t = time(0);         // first 4 byte
-    b[0] = (unsigned char)t;
-    b[1] = (unsigned char)(t>>8);
-    b[2] = (unsigned char)(t>>16);
-    b[3] = (unsigned char)(t>>24);
-    int r = rand();             // four more bytes
-    b[4] = (unsigned char)r;
-    b[5] = (unsigned char)(r>>8);
-    b[6] = (unsigned char)(r>>16);
-    b[7] = (unsigned char)(r>>24);
-    // Now we try to find 4 more "random" bytes. We extract the
-    // lower 4 bytes from the address of t - it is created on the
-    // stack so *might* be in a different place each time...
-    // This is now done via a union to make it compile OK on 64-bit systems.
-    union { void *pv; unsigned char a[sizeof(void*)]; } v;
-    v.pv = (void *)(&t);
-    // NOTE: This assume that all WinXX systems are little-endian
-    b[8] = v.a[0];
-    b[9] = v.a[1];
-    b[10] = v.a[2];
-    b[11] = v.a[3];
-    TCHAR name[MAX_COMPUTERNAME_LENGTH + 1]; // only used to make last four bytes
-    DWORD nSize = MAX_COMPUTERNAME_LENGTH + 1;
-    // GetComputerName() does not depend on any extra libs, and returns something
-    // analogous to gethostname()
-    GetComputerName(name, &nSize);
-    //  use the first 4 TCHAR's of the name to create the last 4 bytes of our UUID
-    for (int ii = 0; ii < 4; ii++) {
-      b[12 + ii] = (unsigned char)name[ii];
-    }
-    sprintf(uuidBuffer, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
-            b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
-            b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]);
-  }
-}
-
-/*
- Note: `prefs` can be NULL!
- */
-char *Fl_WinAPI_System_Driver::preference_rootnode(Fl_Preferences *prefs, Fl_Preferences::Root root, const char *vendor,
-                                                  const char *application)
-{
-#  define FLPREFS_RESOURCE      "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
-#  define FLPREFS_RESOURCEW     L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
-  static char filename[ FL_PATH_MAX ];
-  filename[0] = 0;
-  size_t appDataLen = strlen(vendor) + strlen(application) + 8;
-  DWORD type, nn;
-  LONG err;
-  HKEY key;
-
-  switch (root&Fl_Preferences::ROOT_MASK) {
-    case Fl_Preferences::SYSTEM:
-      err = RegOpenKeyW( HKEY_LOCAL_MACHINE, FLPREFS_RESOURCEW, &key );
-      if (err == ERROR_SUCCESS) {
-        nn = (DWORD) (FL_PATH_MAX - appDataLen);
-        err = RegQueryValueExW( key, L"Common AppData", 0L, &type,
-                               (BYTE*)filename, &nn );
-        if ( ( err != ERROR_SUCCESS ) && ( type == REG_SZ ) ) {
-          filename[0] = 0;
-          filename[1] = 0;
-        }
-        RegCloseKey(key);
-      }
-      break;
-    case Fl_Preferences::USER:
-      err = RegOpenKeyW( HKEY_CURRENT_USER, FLPREFS_RESOURCEW, &key );
-      if (err == ERROR_SUCCESS) {
-        nn = (DWORD) (FL_PATH_MAX - appDataLen);
-        err = RegQueryValueExW( key, L"AppData", 0L, &type,
-                               (BYTE*)filename, &nn );
-        if ( ( err != ERROR_SUCCESS ) && ( type == REG_SZ ) ) {
-          filename[0] = 0;
-          filename[1] = 0;
-        }
-        RegCloseKey(key);
-      }
-      break;
-  }
-  if (!filename[1] && !filename[0]) {
-    strcpy(filename, "C:\\FLTK");
-  } else {
-#if 0
-    wchar_t *b = (wchar_t*)_wcsdup((wchar_t *)filename);
-#else
-    // cygwin does not come with _wcsdup. Use malloc +  wcscpy.
-    // For implementation of wcsdup functionality See
-    // - http://linenum.info/p/glibc/2.7/wcsmbs/wcsdup.c
-    wchar_t *b = (wchar_t *)malloc((wcslen((wchar_t *)filename) + 1) * sizeof(wchar_t));
-    wcscpy(b, (wchar_t *) filename);
-#endif
-    //  filename[fl_unicode2utf(b, wcslen((wchar_t*)b), filename)] = 0;
-    unsigned len = fl_utf8fromwc(filename, (FL_PATH_MAX-1), b, (unsigned) wcslen(b));
-    filename[len] = 0;
-    free(b);
-  }
-  snprintf(filename + strlen(filename), sizeof(filename) - strlen(filename),
-           "/%s/%s.prefs", vendor, application);
-  for (char *s = filename; *s; s++) if (*s == '\\') *s = '/';
-  return filename;
-}
-
-void *Fl_WinAPI_System_Driver::dlopen(const char *filename) {
-  return LoadLibraryW(utf8_to_wchar(filename, wbuf));
-}
-
-void Fl_WinAPI_System_Driver::png_extra_rgba_processing(unsigned char *ptr, int w, int h)
-{
-  // Some Windows graphics drivers don't honor transparency when RGB == white
-  // Convert RGB to 0 when alpha == 0...
-  for (int i = w * h; i > 0; i --, ptr += 4) {
-    if (!ptr[3]) ptr[0] = ptr[1] = ptr[2] = 0;
-  }
-}
-
-const char *Fl_WinAPI_System_Driver::next_dir_sep(const char *start)
-{
-  const char *p = strchr(start, '/');
-  if (!p) p = strchr(start, '\\');
-  return p;
-}
-
-int Fl_WinAPI_System_Driver::file_type(const char *filename)
-{
-  int filetype;
-  if (filename[strlen(filename) - 1] == '/')
-    filetype = Fl_File_Icon::DIRECTORY;
-  else if (filename_isdir(filename))
-    filetype = Fl_File_Icon::DIRECTORY;
-  else
-    filetype = Fl_File_Icon::PLAIN;
-  return filetype;
-}
-
-const char *Fl_WinAPI_System_Driver::home_directory_name()
-{
-  const char *h = getenv("HOME");
-  if (!h) h = getenv("UserProfile");
-  return h;
-}
-
-void Fl_WinAPI_System_Driver::gettime(time_t *sec, int *usec) {
-  struct _timeb t;
-  _ftime(&t);
-  *sec = t.time;
-  *usec = t.millitm * 1000;
-}
-
-#endif
diff --git src/drivers/Android/Fl_Android_Window_Driver.H src/drivers/Android/Fl_Android_Window_Driver.H
deleted file mode 100644
index 865fa51..0000000
--- src/drivers/Android/Fl_Android_Window_Driver.H
+++ /dev/null
@@ -1,143 +0,0 @@
-//
-// Definition of Android window driver
-// for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_Android_Window_Driver.H
- \brief Definition of Android window driver.
- */
-
-#ifndef FL_ANDROID_WINDOW_DRIVER_H
-#define FL_ANDROID_WINDOW_DRIVER_H
-
-#include "../../Fl_Window_Driver.H"
-//#include <windows.h>
-
-/*
- Move everything here that manages the native window interface.
-
- There is one window driver for each Fl_Window. Window drivers manage window
- actions such as resizing, events, decoration, fullscreen modes, etc. . All
- drawing and rendering is managed by the Surface device and the associated
- graphics driver.
-
- - window specific event handling
- - window types and styles, depth, etc.
- - decorations
-
- ? where do we handle the interface between OpenGL/DirectX and Cocoa/Windows/Glx?
- */
-
-
-struct Fl_Window_Driver::shape_data_type {
-  int lw_; ///<  width of shape image
-  int lh_; ///<  height of shape image
-  Fl_Image* shape_; ///<  shape image
-  Fl_Bitmap *effective_bitmap_; ///<  auxiliary bitmap image
-};
-
-class FL_EXPORT Fl_Android_Window_Driver : public Fl_Window_Driver
-{
-#if 0
-
-  friend class Fl_Window;
-  struct icon_data {
-    const void *legacy_icon;
-    Fl_RGB_Image **icons;
-    int count;
-    HICON big_icon;
-    HICON small_icon;
-  };
-  int screen_num_;
-private:
-  void shape_bitmap_(Fl_Image* b);
-  void shape_alpha_(Fl_Image* img, int offset);
-#endif
-
-public:
-  static inline Fl_Android_Window_Driver* driver(const Fl_Window *w) {
-    return (Fl_Android_Window_Driver*)Fl_Window_Driver::driver(w);
-  }
-
-  Fl_Android_Window_Driver(Fl_Window *w) : Fl_Window_Driver(w) {}
-  virtual ~Fl_Android_Window_Driver() override {}
-
-  virtual void make_current() override;
-  virtual void show() override;
-  virtual void hide() override;
-
-#if 0
-  HDC private_dc; // used for OpenGL
-  RECT border_width_title_bar_height(int &bx, int &by, int &bt);
-  virtual void screen_num(int n);
-  virtual int screen_num();
-
-  struct icon_data *icon_;
-  HCURSOR cursor;
-  int custom_cursor;
-  struct type_for_resize_window_between_screens {
-    int screen;
-    bool busy;
-  };
-  static type_for_resize_window_between_screens data_for_resize_window_between_screens_;
-  void set_minmax(LPMINMAXINFO minmax);
-  int fake_X_wm(int &X, int &Y, int &bt,int &bx,int &by);
-  void make_fullscreen(int X, int Y, int W, int H);
-  // --- window data
-  virtual int decorated_w();
-  virtual int decorated_h();
-
-  // --- window management
-  virtual Fl_X *makeWindow();
-  virtual void flush_double();
-  virtual void flush_overlay();
-  virtual void draw_begin();
-  virtual void label(const char *name,const char *iname);
-#endif
-  virtual void resize(int X,int Y,int W,int H) override;
-#if 0
-  virtual void map();
-  virtual void unmap();
-  virtual void fullscreen_on();
-  virtual void fullscreen_off(int X, int Y, int W, int H);
-  virtual void iconize();
-  virtual void decoration_sizes(int *top, int *left,  int *right, int *bottom);
-  // --- window cursor stuff
-  virtual int set_cursor(Fl_Cursor);
-  virtual int set_cursor(const Fl_RGB_Image*, int, int);
-
-  virtual void shape(const Fl_Image* img);
-  virtual void icons(const Fl_RGB_Image *icons[], int count);
-  virtual const void *icon() const;
-  virtual void icon(const void * ic);
-  virtual void free_icons();
-  void set_icons(); // driver-internal support function
-  // this one is implemented in Fl_win32.cxx
-  virtual void capture_titlebar_and_borders(Fl_Shared_Image*& top, Fl_Shared_Image*& left, Fl_Shared_Image*& bottom, Fl_Shared_Image*& right);
-#endif
-  virtual int scroll(int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y,
-                     void (*draw_area)(void*, int,int,int,int), void* data) override;
-#if 0
-  static void resize_after_screen_change(void *data);
-
-#endif
-
-  virtual void wait_for_expose() override { wait_for_expose_value = 1; }
-  static void expose_all();
-};
-
-
-#endif // FL_ANDROID_WINDOW_DRIVER_H
diff --git src/drivers/Android/Fl_Android_Window_Driver.cxx src/drivers/Android/Fl_Android_Window_Driver.cxx
deleted file mode 100644
index 6538bf2..0000000
--- src/drivers/Android/Fl_Android_Window_Driver.cxx
+++ /dev/null
@@ -1,826 +0,0 @@
-//
-// Definition of Android window driver for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2018-2021 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-
-#include <config.h>
-#include <FL/fl_draw.H>
-#include <FL/Fl.H>
-#include <FL/Fl_Window.H>
-#include <FL/Fl_Image.H>
-#include <FL/Fl_Bitmap.H>
-#include <FL/Fl_Window.H>
-#include <FL/Fl_Overlay_Window.H>
-#include <FL/platform.H>
-#include <math.h>
-#include "Fl_Android_Window_Driver.H"
-#include "Fl_Android_Screen_Driver.H"
-#include "Fl_Android_Graphics_Driver.H"
-#include "Fl_Android_Application.H"
-
-
-Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w)
-{
-  return new Fl_Android_Window_Driver(w);
-}
-
-
-Window fl_window = 0;
-
-
-void Fl_Android_Window_Driver::show()
-{
-  if (!shown()) {
-    // make window
-    fl_open_display();
-    if (pWindow->parent() && !Fl_X::i(pWindow->window())) {
-      pWindow->set_visible();
-      return;
-    }
-    pWindow->set_visible();
-    Fl_X *x = new Fl_X;
-    x->w = pWindow;
-    i(x);
-    x->next = Fl_X::first;
-    Fl_X::first = x;
-    // position window
-    // TODO: we want to scale the screen to hold all windows
-    // TODO: we want to allow for screen size hints to make apps look perfect, even if the screen is rotated
-    if (force_position()) {
-      // TODO: make sure that we are on a screen if this is just a regular window
-    } else {
-      // Center any new window on screen
-      pWindow->position(
-              (600-pWindow->w())/2,
-              (800-pWindow->h())/2
-      );
-    }
-    // show window or defer showing window
-    if (Fl_Android_Application::native_window()) {
-      pWindow->redraw();
-    } else {
-      pWindow->wait_for_expose();
-    }
-  } else {
-    // bring window to front
-    if (!pWindow->parent())
-      Fl::first_window(pWindow); // TODO: does this really work?
-    expose_all();
-  }
-}
-
-
-void Fl_Android_Window_Driver::hide()
-{
-  Fl_X* ip = Fl_X::i(pWindow);
-  if (hide_common()) return;
-  if (ip->region) {
-    delete ip->region;
-    ip->region = nullptr;
-  }
-  delete ip;
-  expose_all();
-}
-
-
-void Fl_Android_Window_Driver::expose_all()
-{
-  for (Fl_X *x = Fl_X::first; x; x = x->next) {
-    Fl_Window *win = x->w;
-    Fl_Android_Window_Driver::driver(win)->wait_for_expose_value = 0;
-    win->damage(FL_DAMAGE_EXPOSE);
-    win->redraw();
-  }
-  ((Fl_Android_Screen_Driver*)Fl::screen_driver())->pClearDesktop = true;
-}
-
-
-void Fl_Android_Window_Driver::make_current()
-{
-  // FXIME: that is quite a cludge:
-  ((Fl_Android_Screen_Driver*)Fl::screen_driver())->pContentChanged = true;
-
-  Fl_Android_Graphics_Driver *gd = dynamic_cast<Fl_Android_Graphics_Driver*>(fl_graphics_driver);
-  if (gd) {
-    gd->make_current(pWindow);
-  }
-
-}
-
-
-void Fl_Android_Window_Driver::resize(int X,int Y,int W,int H)
-{
-  int is_a_resize = (W != w() || H != h() || Fl_Window::is_a_rescale());
-  if (X != x() || Y != y() || Fl_Window::is_a_rescale()) {
-    force_position(1);
-  } else {
-    if (!is_a_resize)
-      return;
-  }
-  if (is_a_resize) {
-    pWindow->Fl_Group::resize(X, Y, W, H);
-    if (visible_r()) {
-      pWindow->redraw();
-      // only wait for exposure if this window has a size - a window
-      // with no width or height will never get an exposure event
-      Fl_X *i = Fl_X::i(pWindow);
-      if (i && W > 0 && H > 0)
-        wait_for_expose_value = 1;
-    }
-  } else {
-    x(X);
-    y(Y);
-  }
-  if (shown()) {
-    if (!pWindow->resizable())
-      pWindow->size_range(w(), h(), w(), h());
-    // compute window position and size in scaled units
-//    float s = Fl::screen_driver()->scale(screen_num());
-//    int scaledX = ceil(X * s), scaledY = ceil(Y * s), scaledW = ceil(W * s), scaledH = ceil(H * s);
-//    if (scaledW <= 0)
-//      scaledW = 1;
-//    if (scaledH <= 0)
-//      scaledH = 1;
-//    //SetWindowPos(fl_xid(pWindow), 0, scaledX, scaledY, scaledW, scaledH, flags);
-    expose_all();
-  }
-}
-
-/**
- Scroll a portion of the window.
- FIXME: We are currently taking the easy way out, basically telling the caller that we don;t know how to scroll
- and asking FLTK to draw the new area from scratch. It would be nice if clipping provides all calls
- that we need to implement a more efficient scrolling code.
- */
-int Fl_Android_Window_Driver::scroll(int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y,
-                                    void (*draw_area)(void*, int,int,int,int), void* data)
-{
-#if 0
-  typedef int (WINAPI* fl_GetRandomRgn_func)(HDC, HRGN, INT);
-  static fl_GetRandomRgn_func fl_GetRandomRgn = 0L;
-  static char first_time = 1;
-  // We will have to do some Region magic now, so let's see if the
-  // required function is available (and it should be starting w/Win95)
-  if (first_time) {
-    HMODULE hMod = GetModuleHandle("GDI32.DLL");
-    if (hMod) {
-      fl_GetRandomRgn = (fl_GetRandomRgn_func)GetProcAddress(hMod, "GetRandomRgn");
-    }
-    first_time = 0;
-  }
-  float s = Fl::screen_driver()->scale(screen_num());
-  src_x *= s; src_y *= s; src_w *= s; src_h *= s; dest_x *= s; dest_y *= s;
-  // Now check if the source scrolling area is fully visible.
-  // If it is, we will do a quick scroll and just update the
-  // newly exposed area. If it is not, we go the safe route and
-  // re-render the full area instead.
-  // Note 1: we could go and find the areas that are actually
-  // obscured and recursively call fl_scroll for the newly found
-  // rectangles. However, this practice would rely on the
-  // elements of the undocumented Rgn structure.
-  // Note 2: although this method should take care of most
-  // multi-screen solutions, it will not solve issues scrolling
-  // from a different resolution screen onto another.
-  // Note 3: this has been tested with image maps, too.
-  HDC gc = (HDC)fl_graphics_driver->gc();
-  if (fl_GetRandomRgn) {
-    // get the DC region minus all overlapping windows
-    HRGN sys_rgn = CreateRectRgn(0, 0, 0, 0);
-    fl_GetRandomRgn(gc, sys_rgn, 4);
-    // now get the source scrolling rectangle
-    HRGN src_rgn = CreateRectRgn(src_x, src_y, src_x+src_w, src_y+src_h);
-    POINT offset = { 0, 0 };
-    if (GetDCOrgEx(gc, &offset)) {
-      OffsetRgn(src_rgn, offset.x, offset.y);
-    }
-    // see if all source pixels are available in the system region
-    // Note: we could be a bit more merciful and subtract the
-    // scroll destination region as well.
-    HRGN dst_rgn = CreateRectRgn(0, 0, 0, 0);
-    int r = CombineRgn(dst_rgn, src_rgn, sys_rgn, RGN_DIFF);
-    DeleteObject(dst_rgn);
-    DeleteObject(src_rgn);
-    DeleteObject(sys_rgn);
-    if (r != NULLREGION) {
-      return 1;
-    }
-  }
-  // Great, we can do an accelerated scroll instead of re-rendering
-  BitBlt(gc, dest_x, dest_y, src_w, src_h, gc, src_x, src_y,SRCCOPY);
-  return 0;
-#endif
-  return 1;
-}
-
-
-#if 0
-
-Fl_WinAPI_Window_Driver::Fl_WinAPI_Window_Driver(Fl_Window *win)
-: Fl_Window_Driver(win)
-{
-  icon_ = new icon_data;
-  memset(icon_, 0, sizeof(icon_data));
-  cursor = NULL;
-  screen_num_ = -1;
-}
-
-
-Fl_WinAPI_Window_Driver::~Fl_WinAPI_Window_Driver()
-{
-  if (shape_data_) {
-    delete shape_data_->effective_bitmap_;
-    delete shape_data_;
-  }
-  delete icon_;
-}
-
-int Fl_WinAPI_Window_Driver::screen_num() {
-  if (pWindow->parent()) {
-    screen_num_ = pWindow->top_window()->driver()->screen_num();
-  }
-  return screen_num_ >= 0 ? screen_num_ : 0;
-}
-
-//FILE*LOG=fopen("log.log","w");
-
-void Fl_WinAPI_Window_Driver::screen_num(int n) {
-//fprintf(LOG, "screen_num setter old=%d new=%d\n",screen_num_, n);fflush(LOG);
-  screen_num_ = n;
-}
-
-
-RECT // frame of the decorated window in screen coordinates
-  Fl_WinAPI_Window_Driver::border_width_title_bar_height(
-                                                         int &bx, // left and right border width
-                                                         int &by, // bottom border height (=bx)
-                                                         int &bt  // height of window title bar
-                                                         )
-{
-  Fl_Window *win = pWindow;
-  RECT r = {0,0,0,0};
-  bx = by = bt = 0;
-  if (win->shown() && !win->parent() && win->border() && win->visible()) {
-    static HMODULE dwmapi_dll = LoadLibrary("dwmapi.dll");
-    typedef HRESULT (WINAPI* DwmGetWindowAttribute_type)(HWND hwnd, DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute);
-    static DwmGetWindowAttribute_type DwmGetWindowAttribute = dwmapi_dll ?
-    (DwmGetWindowAttribute_type)GetProcAddress(dwmapi_dll, "DwmGetWindowAttribute") : NULL;
-    int need_r = 1;
-    if (DwmGetWindowAttribute) {
-      const DWORD DWMWA_EXTENDED_FRAME_BOUNDS = 9;
-      if ( DwmGetWindowAttribute(fl_xid(win), DWMWA_EXTENDED_FRAME_BOUNDS, &r, sizeof(RECT)) == S_OK ) {
-        need_r = 0;
-      }
-    }
-    if (need_r) {
-      GetWindowRect(fl_xid(win), &r);
-    }
-    int width, height;
-#ifdef FLTK_HIDPI_SUPPORT
-    RECT  rc;
-    GetClientRect(fl_xid(win), &rc);
-    width = rc.right;
-    height = rc.bottom;
-#else
-    float scaling = ((Fl_WinAPI_Screen_Driver*)Fl::screen_driver())->DWM_scaling_factor();
-    width = int(win->w() * scaling);
-    height = int(win->h() * scaling);
-#endif
-    bx = (r.right - r.left - width)/2;
-    if (bx < 1) bx = 1;
-    by = bx;
-    bt = r.bottom - r.top - height - 2 * by;
-  }
-  return r;
-}
-
-
-// --- window data
-
-int Fl_WinAPI_Window_Driver::decorated_w()
-{
-  int bt, bx, by;
-  float s = Fl::screen_driver()->scale(screen_num());
-  border_width_title_bar_height(bx, by, bt);
-  int mini_bx = bx/s; if (mini_bx < 1) mini_bx = 1;
-  return w() + 2 * mini_bx;
-}
-
-int Fl_WinAPI_Window_Driver::decorated_h()
-{
-  int bt, bx, by;
-  border_width_title_bar_height(bx, by, bt);
-#ifdef FLTK_HIDPI_SUPPORT
-  float s = Fl::screen_driver()->scale(screen_num());
-  int mini_by = by/s; if (mini_by < 1) mini_by = 1;
-  return h() + (bt + by)/s + mini_by;
-#else
-  float scaling = ((Fl_WinAPI_Screen_Driver*)Fl::screen_driver())->DWM_scaling_factor();
-  return h() + bt/scaling + 2 * by +1;
-#endif
-}
-
-
-// --- window management
-
-
-
-void Fl_WinAPI_Window_Driver::shape_bitmap_(Fl_Image* b) {
-  shape_data_->shape_ = b;
-}
-
-void Fl_WinAPI_Window_Driver::shape_alpha_(Fl_Image* img, int offset) {
-  int i, j, d = img->d(), w = img->w(), h = img->h(), bytesperrow = (w+7)/8;
-  unsigned u;
-  uchar byte, onebit;
-  // build an Fl_Bitmap covering the non-fully transparent/black part of the image
-  const uchar* bits = new uchar[h*bytesperrow]; // to store the bitmap
-  const uchar* alpha = (const uchar*)*img->data() + offset; // points to alpha value of rgba pixels
-  for (i = 0; i < h; i++) {
-    uchar *p = (uchar*)bits + i * bytesperrow;
-    byte = 0;
-    onebit = 1;
-    for (j = 0; j < w; j++) {
-      if (d == 3) {
-        u = *alpha;
-        u += *(alpha+1);
-        u += *(alpha+2);
-      }
-      else u = *alpha;
-      if (u > 0) { // if the pixel is not fully transparent/black
-        byte |= onebit; // turn on the corresponding bit of the bitmap
-      }
-      onebit = onebit << 1; // move the single set bit one position to the left
-      if (onebit == 0 || j == w-1) {
-        onebit = 1;
-        *p++ = byte; // store in bitmap one pack of bits
-        byte = 0;
-      }
-      alpha += d; // point to alpha value of next pixel
-    }
-  }
-  Fl_Bitmap* bitmap = new Fl_Bitmap(bits, w, h);
-  bitmap->alloc_array = 1;
-  shape_bitmap_(bitmap);
-  shape_data_->effective_bitmap_ = bitmap;
-}
-
-void Fl_WinAPI_Window_Driver::shape(const Fl_Image* img) {
-  if (shape_data_) {
-    if (shape_data_->effective_bitmap_) { delete shape_data_->effective_bitmap_; }
-  }
-  else {
-    shape_data_ = new shape_data_type;
-  }
-  memset(shape_data_, 0, sizeof(shape_data_type));
-  pWindow->border(false);
-  int d = img->d();
-  if (d && img->count() >= 2) shape_pixmap_((Fl_Image*)img);
-  else if (d == 0) shape_bitmap_((Fl_Image*)img);
-  else if (d == 2 || d == 4) shape_alpha_((Fl_Image*)img, d - 1);
-  else if ((d == 1 || d == 3) && img->count() == 1) shape_alpha_((Fl_Image*)img, 0);
-}
-
-
-static inline BYTE bit(int x) { return (BYTE)(1 << (x%8)); }
-
-static HRGN bitmap2region(Fl_Image* image) {
-  HRGN hRgn = 0;
-  /* Does this need to be dynamically determined, perhaps? */
-  const int ALLOC_UNIT = 100;
-  DWORD maxRects = ALLOC_UNIT;
-
-  RGNDATA* pData = (RGNDATA*)malloc(sizeof(RGNDATAHEADER)+(sizeof(RECT)*maxRects));
-  pData->rdh.dwSize = sizeof(RGNDATAHEADER);
-  pData->rdh.iType = RDH_RECTANGLES;
-  pData->rdh.nCount = pData->rdh.nRgnSize = 0;
-  SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
-
-  const int bytesPerLine = (image->w() + 7)/8;
-  BYTE* p, *data = (BYTE*)*image->data();
-  for (int y = 0; y < image->h(); y++) {
-    // each row, left to right
-    for (int x = 0; x < image->w(); x++) {
-      int x0 = x;
-      while (x < image->w()) {
-        p = data + x / 8;
-        if (!((*p) & bit(x))) break; // transparent pixel
-        x++;
-      }
-      if (x > x0) {
-        RECT *pr;
-        /* Add the pixels (x0, y) to (x, y+1) as a new rectangle
-         * in the region
-         */
-        if (pData->rdh.nCount >= maxRects) {
-          maxRects += ALLOC_UNIT;
-          pData = (RGNDATA*)realloc(pData, sizeof(RGNDATAHEADER)
-                                    + (sizeof(RECT)*maxRects));
-        }
-        pr = (RECT*)&pData->Buffer;
-        SetRect(&pr[pData->rdh.nCount], x0, y, x, y+1);
-        if (x0 < pData->rdh.rcBound.left)
-          pData->rdh.rcBound.left = x0;
-        if (y < pData->rdh.rcBound.top)
-          pData->rdh.rcBound.top = y;
-        if (x > pData->rdh.rcBound.right)
-          pData->rdh.rcBound.right = x;
-        if (y+1 > pData->rdh.rcBound.bottom)
-          pData->rdh.rcBound.bottom = y+1;
-        pData->rdh.nCount++;
-        /* On Windows98, ExtCreateRegion() may fail if the
-         * number of rectangles is too large (ie: >
-         * 4000). Therefore, we have to create the region by
-         * multiple steps.
-         */
-        if (pData->rdh.nCount == 2000) {
-          HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER)
-                                   + (sizeof(RECT)*maxRects), pData);
-          if (hRgn) {
-            CombineRgn(hRgn, hRgn, h, RGN_OR);
-            DeleteObject(h);
-          } else
-            hRgn = h;
-          pData->rdh.nCount = 0;
-          SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
-        }
-      }
-    }
-    /* Go to next row */
-    data += bytesPerLine;
-  }
-  /* Create or extend the region with the remaining rectangles*/
-  HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER)
-                           + (sizeof(RECT)*maxRects), pData);
-  if (hRgn) {
-    CombineRgn(hRgn, hRgn, h, RGN_OR);
-    DeleteObject(h);
-  } else hRgn = h;
-  free(pData); // I've created the region so I can free this now, right?
-  return hRgn;
-}
-
-
-void Fl_WinAPI_Window_Driver::draw_begin()
-{
-  if (shape_data_) {
-    float s = Fl::screen_driver()->scale(screen_num());
-    if ((shape_data_->lw_ != s*w() || shape_data_->lh_ != s*h()) && shape_data_->shape_) {
-      // size of window has changed since last time
-      shape_data_->lw_ = s*w();
-      shape_data_->lh_ = s*h();
-      Fl_Image* temp = shape_data_->shape_->copy(shape_data_->lw_, shape_data_->lh_);
-      HRGN region = bitmap2region(temp);
-      SetWindowRgn(fl_xid(pWindow), region, TRUE); // the system deletes the region when it's no longer needed
-      delete temp;
-    }
-  }
-}
-
-
-void Fl_WinAPI_Window_Driver::flush_double()
-{
-  if (!shown()) return;
-  pWindow->make_current(); // make sure fl_gc is non-zero
-  Fl_X *i = Fl_X::i(pWindow);
-  if (!i) return; // window not yet created
-
-  if (!other_xid) {
-    other_xid = fl_create_offscreen(w(), h());
-    pWindow->clear_damage(FL_DAMAGE_ALL);
-  }
-  if (pWindow->damage() & ~FL_DAMAGE_EXPOSE) {
-    fl_clip_region(i->region); i->region = 0;
-    fl_begin_offscreen(other_xid);
-    fl_graphics_driver->clip_region( 0 );
-    draw();
-    fl_end_offscreen();
-  }
-
-  int X = 0, Y = 0, W = 0, H = 0;
-  fl_clip_box(0, 0, w(), h(), X, Y, W, H);
-  if (other_xid) fl_copy_offscreen(X, Y, W, H, other_xid, X, Y);
-}
-
-
-void Fl_WinAPI_Window_Driver::flush_overlay()
-{
-  Fl_Overlay_Window *oWindow = pWindow->as_overlay_window();
-
-  if (!shown()) return;
-  pWindow->make_current(); // make sure fl_gc is non-zero
-  Fl_X *i = Fl_X::i(pWindow);
-  if (!i) return; // window not yet created
-
-  int eraseoverlay = (pWindow->damage()&FL_DAMAGE_OVERLAY);
-  pWindow->clear_damage((uchar)(pWindow->damage()&~FL_DAMAGE_OVERLAY));
-
-  if (!other_xid) {
-    other_xid = fl_create_offscreen(w(), h());
-    pWindow->clear_damage(FL_DAMAGE_ALL);
-  }
-  if (pWindow->damage() & ~FL_DAMAGE_EXPOSE) {
-    fl_clip_region(i->region); i->region = 0;
-    fl_begin_offscreen(other_xid);
-    fl_graphics_driver->clip_region(0);
-    draw();
-    fl_end_offscreen();
-  }
-
-  if (eraseoverlay) fl_clip_region(0);
-  int X = 0, Y = 0, W = 0, H = 0;
-  fl_clip_box(0, 0, w(), h(), X, Y, W, H);
-  if (other_xid) fl_copy_offscreen(X, Y, W, H, other_xid, X, Y);
-
-  if (overlay() == oWindow) oWindow->draw_overlay();
-}
-
-
-void Fl_WinAPI_Window_Driver::icons(const Fl_RGB_Image *icons[], int count) {
-  free_icons();
-
-  if (count > 0) {
-    icon_->icons = new Fl_RGB_Image*[count];
-    icon_->count = count;
-    // FIXME: Fl_RGB_Image lacks const modifiers on methods
-    for (int i = 0;i < count;i++)
-      icon_->icons[i] = (Fl_RGB_Image*)((Fl_RGB_Image*)icons[i])->copy();
-  }
-
-  if (Fl_X::i(pWindow))
-    set_icons();
-}
-
-const void *Fl_WinAPI_Window_Driver::icon() const {
-  return icon_->legacy_icon;
-}
-
-void Fl_WinAPI_Window_Driver::icon(const void * ic) {
-  free_icons();
-  icon_->legacy_icon = ic;
-}
-
-void Fl_WinAPI_Window_Driver::free_icons() {
-  int i;
-  icon_->legacy_icon = 0L;
-  if (icon_->icons) {
-    for (i = 0;i < icon_->count;i++)
-      delete icon_->icons[i];
-    delete [] icon_->icons;
-    icon_->icons = 0L;
-  }
-  icon_->count = 0;
-  if (icon_->big_icon)
-    DestroyIcon(icon_->big_icon);
-  if (icon_->small_icon)
-    DestroyIcon(icon_->small_icon);
-  icon_->big_icon = NULL;
-  icon_->small_icon = NULL;
-}
-
-
-void Fl_WinAPI_Window_Driver::make_current() {
-  fl_GetDC(fl_xid(pWindow));
-
-#if USE_COLORMAP
-  // Windows maintains a hardware and software color palette; the
-  // SelectPalette() call updates the current soft->hard mapping
-  // for all drawing calls, so we must select it here before any
-  // code does any drawing...
-  fl_select_palette();
-#endif // USE_COLORMAP
-
-  fl_graphics_driver->clip_region(0);
-  ((Fl_GDI_Graphics_Driver*)fl_graphics_driver)->scale(Fl::screen_driver()->scale(screen_num()));
-}
-
-void Fl_WinAPI_Window_Driver::label(const char *name,const char *iname) {
-  if (shown() && !parent()) {
-    if (!name) name = "";
-    size_t l = strlen(name);
-    //  WCHAR *lab = (WCHAR*) malloc((l + 1) * sizeof(short));
-    //  l = fl_utf2unicode((unsigned char*)name, l, (wchar_t*)lab);
-    unsigned wlen = fl_utf8toUtf16(name, (unsigned) l, NULL, 0); // Pass NULL to query length
-    wlen++;
-    unsigned short * lab = (unsigned short*)malloc(sizeof(unsigned short)*wlen);
-    wlen = fl_utf8toUtf16(name, (unsigned) l, lab, wlen);
-    lab[wlen] = 0;
-    SetWindowTextW(fl_xid(pWindow), (WCHAR *)lab);
-    free(lab);
-  }
-}
-
-
-extern void fl_clipboard_notify_retarget(HWND wnd);
-extern void fl_update_clipboard(void);
-
-void Fl_WinAPI_Window_Driver::hide() {
-  Fl_X* ip = Fl_X::i(pWindow);
-  // STR#3079: if there remains a window and a non-modal window, and the window is deleted,
-  // the app remains running without any apparent window.
-  // Bug mechanism: hiding an owner window unmaps the owned (non-modal) window(s)
-  // but does not delete it(them) in FLTK.
-  // Fix for it:
-  // when hiding a window, build list of windows it owns, and do hide/show on them.
-  int count = 0;
-  Fl_Window *win, **doit = NULL;
-  for (win = Fl::first_window(); win && ip; win = Fl::next_window(win)) {
-    if (win->non_modal() && GetWindow(fl_xid(win), GW_OWNER) == ip->xid) {
-      count++;
-    }
-  }
-  if (count) {
-    doit = new Fl_Window*[count];
-    count = 0;
-    for (win = Fl::first_window(); win && ip; win = Fl::next_window(win)) {
-      if (win->non_modal() && GetWindow(fl_xid(win), GW_OWNER) == ip->xid) {
-        doit[count++] = win;
-      }
-    }
-  }
-
-  if (hide_common()) return;
-
-  // make sure any custom icons get freed
-//  icons(NULL, 0); // free_icons() is called by the Fl_Window destructor
-  // this little trick keeps the current clipboard alive, even if we are about
-  // to destroy the window that owns the selection.
-  if (GetClipboardOwner()==ip->xid)
-    fl_update_clipboard();
-  // Make sure we unlink this window from the clipboard chain
-  fl_clipboard_notify_retarget(ip->xid);
-  // Send a message to myself so that I'll get out of the event loop...
-  PostMessage(ip->xid, WM_APP, 0, 0);
-  if (private_dc) fl_release_dc(ip->xid, private_dc);
-  if (ip->xid == fl_window && fl_graphics_driver->gc()) {
-    fl_release_dc(fl_window, (HDC)fl_graphics_driver->gc());
-    fl_window = (HWND)-1;
-    fl_graphics_driver->gc(0);
-# ifdef FLTK_HAVE_CAIROEXT
-    if (Fl::cairo_autolink_context()) Fl::cairo_make_current((Fl_Window*) 0);
-# endif
-  }
-
-  if (ip->region) Fl_Graphics_Driver::default_driver().XDestroyRegion(ip->region);
-
-  // this little trickery seems to avoid the popup window stacking problem
-  HWND p = GetForegroundWindow();
-  if (p==GetParent(ip->xid)) {
-    ShowWindow(ip->xid, SW_HIDE);
-    ShowWindow(p, SW_SHOWNA);
-  }
-  DestroyWindow(ip->xid);
-  // end of fix for STR#3079
-  if (count) {
-    int ii;
-    for (ii = 0; ii < count; ii++)  doit[ii]->hide();
-    for (ii = 0; ii < count; ii++)  {
-      if (ii != 0) doit[0]->show(); // Fix for STR#3165
-      doit[ii]->show();
-    }
-    delete[] doit;
-  }
-  // Try to stop the annoying "raise another program" behavior
-  if (pWindow->non_modal() && Fl::first_window() && Fl::first_window()->shown())
-    Fl::first_window()->show();
-  delete ip;
-  screen_num_ = -1;
-}
-
-
-void Fl_WinAPI_Window_Driver::map() {
-  ShowWindow(fl_xid(pWindow), SW_RESTORE); // extra map calls are harmless
-}
-
-
-void Fl_WinAPI_Window_Driver::unmap() {
-  ShowWindow(fl_xid(pWindow), SW_HIDE);
-}
-
-#if !defined(FL_DOXYGEN)
-
-void Fl_WinAPI_Window_Driver::make_fullscreen(int X, int Y, int W, int H) {
-  Fl_Window *w = pWindow;
-  int top, bottom, left, right;
-  int sx, sy, sw, sh;
-
-  top = fullscreen_screen_top();
-  bottom = fullscreen_screen_bottom();
-  left = fullscreen_screen_left();
-  right = fullscreen_screen_right();
-
-  if ((top < 0) || (bottom < 0) || (left < 0) || (right < 0)) {
-    top = screen_num();
-    bottom = top;
-    left = top;
-    right = top;
-  }
-
-  Fl::screen_xywh(sx, sy, sw, sh, top);
-  Y = sy;
-  Fl::screen_xywh(sx, sy, sw, sh, bottom);
-  H = sy + sh - Y;
-  Fl::screen_xywh(sx, sy, sw, sh, left);
-  X = sx;
-  Fl::screen_xywh(sx, sy, sw, sh, right);
-  W = sx + sw - X;
-
-  DWORD flags = GetWindowLong(fl_xid(w), GWL_STYLE);
-  flags = flags & ~(WS_THICKFRAME|WS_CAPTION);
-  SetWindowLong(fl_xid(w), GWL_STYLE, flags);
-
-  // SWP_NOSENDCHANGING is so that we can override size limits
-  float s = Fl::screen_driver()->scale(screen_num());
-  SetWindowPos(fl_xid(w), HWND_TOP, X*s, Y*s, W*s, H*s, SWP_NOSENDCHANGING | SWP_FRAMECHANGED);
-}
-
-#endif // !defined(FL_DOXYGEN)
-
-
-void Fl_WinAPI_Window_Driver::fullscreen_on() {
-  pWindow->_set_fullscreen();
-  make_fullscreen(x(), y(), w(), h());
-  Fl::handle(FL_FULLSCREEN, pWindow);
-}
-
-
-void Fl_WinAPI_Window_Driver::fullscreen_off(int X, int Y, int W, int H) {
-  pWindow->_clear_fullscreen();
-  DWORD style = GetWindowLong(fl_xid(pWindow), GWL_STYLE);
-  // Remove the xid temporarily so that Fl_WinAPI_Window_Driver::fake_X_wm() behaves like it
-  // does in Fl_WinAPI_Window_Driver::makeWindow().
-  HWND xid = fl_xid(pWindow);
-  Fl_X::i(pWindow)->xid = NULL;
-  int wx, wy, bt, bx, by;
-  switch (fake_X_wm(wx, wy, bt, bx, by)) {
-    case 0:
-      break;
-    case 1:
-      style |= WS_CAPTION;
-      break;
-    case 2:
-      if (border()) {
-        style |= WS_THICKFRAME | WS_CAPTION;
-      }
-      break;
-  }
-  Fl_X::i(pWindow)->xid = xid;
-  // compute window position and size in scaled units
-  float s = Fl::screen_driver()->scale(screen_num());
-  int scaledX = ceil(X*s), scaledY= ceil(Y*s), scaledW = ceil(W*s), scaledH = ceil(H*s);
-  // Adjust for decorations (but not if that puts the decorations
-  // outside the screen)
-  if ((X != x()) || (Y != y())) {
-    scaledX -= bx;
-    scaledY -= by+bt;
-  }
-  scaledW += bx*2;
-  scaledH += by*2+bt;
-  SetWindowLong(fl_xid(pWindow), GWL_STYLE, style);
-  SetWindowPos(fl_xid(pWindow), 0, scaledX, scaledY, scaledW, scaledH,
-               SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
-  Fl::handle(FL_FULLSCREEN, pWindow);
-}
-
-
-void Fl_WinAPI_Window_Driver::iconize() {
-  ShowWindow(fl_xid(pWindow), SW_SHOWMINNOACTIVE);
-}
-
-
-void Fl_WinAPI_Window_Driver::decoration_sizes(int *top, int *left,  int *right, int *bottom) {
-  if (size_range_set() && (maxw() != minw() || maxh() != minh())) {
-    *left = *right = GetSystemMetrics(SM_CXSIZEFRAME);
-    *top = *bottom = GetSystemMetrics(SM_CYSIZEFRAME);
-  } else {
-    *left = *right = GetSystemMetrics(SM_CXFIXEDFRAME);
-    *top = *bottom = GetSystemMetrics(SM_CYFIXEDFRAME);
-  }
-  *top += GetSystemMetrics(SM_CYCAPTION);
-}
-
-
-Fl_WinAPI_Window_Driver::type_for_resize_window_between_screens Fl_WinAPI_Window_Driver::data_for_resize_window_between_screens_ = {0, false};
-
-void Fl_WinAPI_Window_Driver::resize_after_screen_change(void *data) {
-  Fl_Window *win = (Fl_Window*)data;
-  RECT r;
-  GetClientRect(fl_xid(win), &r);
-  float old_f = float(r.right)/win->w();
-  int ns = data_for_resize_window_between_screens_.screen;
-  win->driver()->resize_after_scale_change(ns, old_f, Fl::screen_driver()->scale(ns));
-  data_for_resize_window_between_screens_.busy = false;
-}
-
-#endif
diff --git src/drivers/Android/README.txt src/drivers/Android/README.txt
deleted file mode 100644
index f2bccf6..0000000
--- src/drivers/Android/README.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-WonkoBook:Android matt$ svn ps svn:keywords "author date id revision" Fl_Android_Application.*
-property 'svn:keywords' set on 'Fl_Android_Application.cpp'
-property 'svn:keywords' set on 'Fl_Android_Application.h'
-WonkoBook:Android matt$ svn pg svn:eol-style Fl_Font.H
-native
-WonkoBook:Android matt$ svn ps svn:eol-style "native" Fl_Android_Application.*
-property 'svn:eol-style' set on 'Fl_Android_Application.cpp'
-property 'svn:eol-style' set on 'Fl_Android_Application.h'
-
-
diff --git src/drivers/Android/stb_truetype.h src/drivers/Android/stb_truetype.h
deleted file mode 100644
index e2efae2..0000000
--- src/drivers/Android/stb_truetype.h
+++ /dev/null
@@ -1,4853 +0,0 @@
-// stb_truetype.h - v1.19 - public domain
-// authored from 2009-2016 by Sean Barrett / RAD Game Tools
-//
-//   This library processes TrueType files:
-//        parse files
-//        extract glyph metrics
-//        extract glyph shapes
-//        render glyphs to one-channel bitmaps with antialiasing (box filter)
-//        render glyphs to one-channel SDF bitmaps (signed-distance field/function)
-//
-//   Todo:
-//        non-MS cmaps
-//        crashproof on bad data
-//        hinting? (no longer patented)
-//        cleartype-style AA?
-//        optimize: use simple memory allocator for intermediates
-//        optimize: build edge-list directly from curves
-//        optimize: rasterize directly from curves?
-//
-// ADDITIONAL CONTRIBUTORS
-//
-//   Mikko Mononen: compound shape support, more cmap formats
-//   Tor Andersson: kerning, subpixel rendering
-//   Dougall Johnson: OpenType / Type 2 font handling
-//   Daniel Ribeiro Maciel: basic GPOS-based kerning
-//
-//   Misc other:
-//       Ryan Gordon
-//       Simon Glass
-//       github:IntellectualKitty
-//       Imanol Celaya
-//       Daniel Ribeiro Maciel
-//
-//   Bug/warning reports/fixes:
-//       "Zer" on mollyrocket       Fabian "ryg" Giesen
-//       Cass Everitt               Martins Mozeiko
-//       stoiko (Haemimont Games)   Cap Petschulat
-//       Brian Hook                 Omar Cornut
-//       Walter van Niftrik         github:aloucks
-//       David Gow                  Peter LaValle
-//       David Given                Sergey Popov
-//       Ivan-Assen Ivanov          Giumo X. Clanjor
-//       Anthony Pesch              Higor Euripedes
-//       Johan Duparc               Thomas Fields
-//       Hou Qiming                 Derek Vinyard
-//       Rob Loach                  Cort Stratton
-//       Kenney Phillis Jr.         github:oyvindjam
-//       Brian Costabile            github:vassvik
-//
-// VERSION HISTORY
-//
-//   1.19 (2018-02-11) GPOS kerning, STBTT_fmod
-//   1.18 (2018-01-29) add missing function
-//   1.17 (2017-07-23) make more arguments const; doc fix
-//   1.16 (2017-07-12) SDF support
-//   1.15 (2017-03-03) make more arguments const
-//   1.14 (2017-01-16) num-fonts-in-TTC function
-//   1.13 (2017-01-02) support OpenType fonts, certain Apple fonts
-//   1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
-//   1.11 (2016-04-02) fix unused-variable warning
-//   1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef
-//   1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly
-//   1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
-//   1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
-//                     variant PackFontRanges to pack and render in separate phases;
-//                     fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);
-//                     fixed an assert() bug in the new rasterizer
-//                     replace assert() with STBTT_assert() in new rasterizer
-//
-//   Full history can be found at the end of this file.
-//
-// LICENSE
-//
-//   See end of file for license information.
-//
-// USAGE
-//
-//   Include this file in whatever places neeed to refer to it. In ONE C/C++
-//   file, write:
-//      #define STB_TRUETYPE_IMPLEMENTATION
-//   before the #include of this file. This expands out the actual
-//   implementation into that C/C++ file.
-//
-//   To make the implementation private to the file that generates the implementation,
-//      #define STBTT_STATIC
-//
-//   Simple 3D API (don't ship this, but it's fine for tools and quick start)
-//           stbtt_BakeFontBitmap()               -- bake a font to a bitmap for use as texture
-//           stbtt_GetBakedQuad()                 -- compute quad to draw for a given char
-//
-//   Improved 3D API (more shippable):
-//           #include "stb_rect_pack.h"           -- optional, but you really want it
-//           stbtt_PackBegin()
-//           stbtt_PackSetOversampling()          -- for improved quality on small fonts
-//           stbtt_PackFontRanges()               -- pack and renders
-//           stbtt_PackEnd()
-//           stbtt_GetPackedQuad()
-//
-//   "Load" a font file from a memory buffer (you have to keep the buffer loaded)
-//           stbtt_InitFont()
-//           stbtt_GetFontOffsetForIndex()        -- indexing for TTC font collections
-//           stbtt_GetNumberOfFonts()             -- number of fonts for TTC font collections
-//
-//   Render a unicode codepoint to a bitmap
-//           stbtt_GetCodepointBitmap()           -- allocates and returns a bitmap
-//           stbtt_MakeCodepointBitmap()          -- renders into bitmap you provide
-//           stbtt_GetCodepointBitmapBox()        -- how big the bitmap must be
-//
-//   Character advance/positioning
-//           stbtt_GetCodepointHMetrics()
-//           stbtt_GetFontVMetrics()
-//           stbtt_GetFontVMetricsOS2()
-//           stbtt_GetCodepointKernAdvance()
-//
-//   Starting with version 1.06, the rasterizer was replaced with a new,
-//   faster and generally-more-precise rasterizer. The new rasterizer more
-//   accurately measures pixel coverage for anti-aliasing, except in the case
-//   where multiple shapes overlap, in which case it overestimates the AA pixel
-//   coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If
-//   this turns out to be a problem, you can re-enable the old rasterizer with
-//        #define STBTT_RASTERIZER_VERSION 1
-//   which will incur about a 15% speed hit.
-//
-// ADDITIONAL DOCUMENTATION
-//
-//   Immediately after this block comment are a series of sample programs.
-//
-//   After the sample programs is the "header file" section. This section
-//   includes documentation for each API function.
-//
-//   Some important concepts to understand to use this library:
-//
-//      Codepoint
-//         Characters are defined by unicode codepoints, e.g. 65 is
-//         uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is
-//         the hiragana for "ma".
-//
-//      Glyph
-//         A visual character shape (every codepoint is rendered as
-//         some glyph)
-//
-//      Glyph index
-//         A font-specific integer ID representing a glyph
-//
-//      Baseline
-//         Glyph shapes are defined relative to a baseline, which is the
-//         bottom of uppercase characters. Characters extend both above
-//         and below the baseline.
-//
-//      Current Point
-//         As you draw text to the screen, you keep track of a "current point"
-//         which is the origin of each character. The current point's vertical
-//         position is the baseline. Even "baked fonts" use this model.
-//
-//      Vertical Font Metrics
-//         The vertical qualities of the font, used to vertically position
-//         and space the characters. See docs for stbtt_GetFontVMetrics.
-//
-//      Font Size in Pixels or Points
-//         The preferred interface for specifying font sizes in stb_truetype
-//         is to specify how tall the font's vertical extent should be in pixels.
-//         If that sounds good enough, skip the next paragraph.
-//
-//         Most font APIs instead use "points", which are a common typographic
-//         measurement for describing font size, defined as 72 points per inch.
-//         stb_truetype provides a point API for compatibility. However, true
-//         "per inch" conventions don't make much sense on computer displays
-//         since different monitors have different number of pixels per
-//         inch. For example, Windows traditionally uses a convention that
-//         there are 96 pixels per inch, thus making 'inch' measurements have
-//         nothing to do with inches, and thus effectively defining a point to
-//         be 1.333 pixels. Additionally, the TrueType font data provides
-//         an explicit scale factor to scale a given font's glyphs to points,
-//         but the author has observed that this scale factor is often wrong
-//         for non-commercial fonts, thus making fonts scaled in points
-//         according to the TrueType spec incoherently sized in practice.
-//
-// DETAILED USAGE:
-//
-//  Scale:
-//    Select how high you want the font to be, in points or pixels.
-//    Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute
-//    a scale factor SF that will be used by all other functions.
-//
-//  Baseline:
-//    You need to select a y-coordinate that is the baseline of where
-//    your text will appear. Call GetFontBoundingBox to get the baseline-relative
-//    bounding box for all characters. SF*-y0 will be the distance in pixels
-//    that the worst-case character could extend above the baseline, so if
-//    you want the top edge of characters to appear at the top of the
-//    screen where y=0, then you would set the baseline to SF*-y0.
-//
-//  Current point:
-//    Set the current point where the first character will appear. The
-//    first character could extend left of the current point; this is font
-//    dependent. You can either choose a current point that is the leftmost
-//    point and hope, or add some padding, or check the bounding box or
-//    left-side-bearing of the first character to be displayed and set
-//    the current point based on that.
-//
-//  Displaying a character:
-//    Compute the bounding box of the character. It will contain signed values
-//    relative to <current_point, baseline>. I.e. if it returns x0,y0,x1,y1,
-//    then the character should be displayed in the rectangle from
-//    <current_point+SF*x0, baseline+SF*y0> to <current_point+SF*x1,baseline+SF*y1).
-//
-//  Advancing for the next character:
-//    Call GlyphHMetrics, and compute 'current_point += SF * advance'.
-//
-//
-// ADVANCED USAGE
-//
-//   Quality:
-//
-//    - Use the functions with Subpixel at the end to allow your characters
-//      to have subpixel positioning. Since the font is anti-aliased, not
-//      hinted, this is very import for quality. (This is not possible with
-//      baked fonts.)
-//
-//    - Kerning is now supported, and if you're supporting subpixel rendering
-//      then kerning is worth using to give your text a polished look.
-//
-//   Performance:
-//
-//    - Convert Unicode codepoints to glyph indexes and operate on the glyphs;
-//      if you don't do this, stb_truetype is forced to do the conversion on
-//      every call.
-//
-//    - There are a lot of memory allocations. We should modify it to take
-//      a temp buffer and allocate from the temp buffer (without freeing),
-//      should help performance a lot.
-//
-// NOTES
-//
-//   The system uses the raw data found in the .ttf file without changing it
-//   and without building auxiliary data structures. This is a bit inefficient
-//   on little-endian systems (the data is big-endian), but assuming you're
-//   caching the bitmaps or glyph shapes this shouldn't be a big deal.
-//
-//   It appears to be very hard to programmatically determine what font a
-//   given file is in a general way. I provide an API for this, but I don't
-//   recommend it.
-//
-//
-// SOURCE STATISTICS (based on v0.6c, 2050 LOC)
-//
-//   Documentation & header file        520 LOC  \___ 660 LOC documentation
-//   Sample code                        140 LOC  /
-//   Truetype parsing                   620 LOC  ---- 620 LOC TrueType
-//   Software rasterization             240 LOC  \                           .
-//   Curve tesselation                  120 LOC   \__ 550 LOC Bitmap creation
-//   Bitmap management                  100 LOC   /
-//   Baked bitmap interface              70 LOC  /
-//   Font name matching & access        150 LOC  ---- 150
-//   C runtime library abstraction       60 LOC  ----  60
-//
-//
-// PERFORMANCE MEASUREMENTS FOR 1.06:
-//
-//                      32-bit     64-bit
-//   Previous release:  8.83 s     7.68 s
-//   Pool allocations:  7.72 s     6.34 s
-//   Inline sort     :  6.54 s     5.65 s
-//   New rasterizer  :  5.63 s     5.00 s
-
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-////
-////  SAMPLE PROGRAMS
-////
-//
-//  Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless
-//
-#if 0
-#define STB_TRUETYPE_IMPLEMENTATION  // force following include to generate implementation
-#include "stb_truetype.h"
-
-unsigned char ttf_buffer[1<<20];
-unsigned char temp_bitmap[512*512];
-
-stbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs
-GLuint ftex;
-
-void my_stbtt_initfont(void)
-{
-   fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb"));
-   stbtt_BakeFontBitmap(ttf_buffer,0, 32.0, temp_bitmap,512,512, 32,96, cdata); // no guarantee this fits!
-   // can free ttf_buffer at this point
-   glGenTextures(1, &ftex);
-   glBindTexture(GL_TEXTURE_2D, ftex);
-   glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512,512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
-   // can free temp_bitmap at this point
-   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-}
-
-void my_stbtt_print(float x, float y, char *text)
-{
-   // assume orthographic projection with units = screen pixels, origin at top left
-   glEnable(GL_TEXTURE_2D);
-   glBindTexture(GL_TEXTURE_2D, ftex);
-   glBegin(GL_QUADS);
-   while (*text) {
-      if (*text >= 32 && *text < 128) {
-         stbtt_aligned_quad q;
-         stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9
-         glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0);
-         glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0);
-         glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1);
-         glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1);
-      }
-      ++text;
-   }
-   glEnd();
-}
-#endif
-//
-//
-//////////////////////////////////////////////////////////////////////////////
-//
-// Complete program (this compiles): get a single bitmap, print as ASCII art
-//
-#if 0
-#include <stdio.h>
-#define STB_TRUETYPE_IMPLEMENTATION  // force following include to generate implementation
-#include "stb_truetype.h"
-
-char ttf_buffer[1<<25];
-
-int main(int argc, char **argv)
-{
-   stbtt_fontinfo font;
-   unsigned char *bitmap;
-   int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20);
-
-   fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb"));
-
-   stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));
-   bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0);
-
-   for (j=0; j < h; ++j) {
-      for (i=0; i < w; ++i)
-         putchar(" .:ioVM@"[bitmap[j*w+i]>>5]);
-      putchar('\n');
-   }
-   return 0;
-}
-#endif
-//
-// Output:
-//
-//     .ii.
-//    @@@@@@.
-//   V@Mio@@o
-//   :i.  V@V
-//     :oM@@M
-//   :@@@MM@M
-//   @@o  o@M
-//  :@@.  M@M
-//   @@@o@@@@
-//   :M@@V:@@.
-//
-//////////////////////////////////////////////////////////////////////////////
-//
-// Complete program: print "Hello World!" banner, with bugs
-//
-#if 0
-char buffer[24<<20];
-unsigned char screen[20][79];
-
-int main(int arg, char **argv)
-{
-   stbtt_fontinfo font;
-   int i,j,ascent,baseline,ch=0;
-   float scale, xpos=2; // leave a little padding in case the character extends left
-   char *text = "Heljo World!"; // intentionally misspelled to show 'lj' brokenness
-
-   fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
-   stbtt_InitFont(&font, buffer, 0);
-
-   scale = stbtt_ScaleForPixelHeight(&font, 15);
-   stbtt_GetFontVMetrics(&font, &ascent,0,0);
-   baseline = (int) (ascent*scale);
-
-   while (text[ch]) {
-      int advance,lsb,x0,y0,x1,y1;
-      float x_shift = xpos - (float) floor(xpos);
-      stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb);
-      stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1);
-      stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]);
-      // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong
-      // because this API is really for baking character bitmaps into textures. if you want to render
-      // a sequence of characters, you really need to render each bitmap to a temp buffer, then
-      // "alpha blend" that into the working buffer
-      xpos += (advance * scale);
-      if (text[ch+1])
-         xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]);
-      ++ch;
-   }
-
-   for (j=0; j < 20; ++j) {
-      for (i=0; i < 78; ++i)
-         putchar(" .:ioVM@"[screen[j][i]>>5]);
-      putchar('\n');
-   }
-
-   return 0;
-}
-#endif
-
-
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-////
-////   INTEGRATION WITH YOUR CODEBASE
-////
-////   The following sections allow you to supply alternate definitions
-////   of C library functions used by stb_truetype, e.g. if you don't
-////   link with the C runtime library.
-
-#ifdef STB_TRUETYPE_IMPLEMENTATION
-   // #define your own (u)stbtt_int8/16/32 before including to override this
-   #ifndef stbtt_uint8
-   typedef unsigned char   stbtt_uint8;
-   typedef signed   char   stbtt_int8;
-   typedef unsigned short  stbtt_uint16;
-   typedef signed   short  stbtt_int16;
-   typedef unsigned int    stbtt_uint32;
-   typedef signed   int    stbtt_int32;
-   #endif
-
-   typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1];
-   typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1];
-
-   // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h
-   #ifndef STBTT_ifloor
-   #include <math.h>
-   #define STBTT_ifloor(x)   ((int) floor(x))
-   #define STBTT_iceil(x)    ((int) ceil(x))
-   #endif
-
-   #ifndef STBTT_sqrt
-   #include <math.h>
-   #define STBTT_sqrt(x)      sqrt(x)
-   #define STBTT_pow(x,y)     pow(x,y)
-   #endif
-
-   #ifndef STBTT_fmod
-   #include <math.h>
-   #define STBTT_fmod(x,y)    fmod(x,y)
-   #endif
-
-   #ifndef STBTT_cos
-   #include <math.h>
-   #define STBTT_cos(x)       cos(x)
-   #define STBTT_acos(x)      acos(x)
-   #endif
-
-   #ifndef STBTT_fabs
-   #include <math.h>
-   #define STBTT_fabs(x)      fabs(x)
-   #endif
-
-   // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h
-   #ifndef STBTT_malloc
-   #include <stdlib.h>
-   #define STBTT_malloc(x,u)  ((void)(u),malloc(x))
-   #define STBTT_free(x,u)    ((void)(u),free(x))
-   #endif
-
-   #ifndef STBTT_assert
-   #include <assert.h>
-   #define STBTT_assert(x)    assert(x)
-   #endif
-
-   #ifndef STBTT_strlen
-   #include <string.h>
-   #define STBTT_strlen(x)    strlen(x)
-   #endif
-
-   #ifndef STBTT_memcpy
-   #include <string.h>
-   #define STBTT_memcpy       memcpy
-   #define STBTT_memset       memset
-   #endif
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-////
-////   INTERFACE
-////
-////
-
-#ifndef __STB_INCLUDE_STB_TRUETYPE_H__
-#define __STB_INCLUDE_STB_TRUETYPE_H__
-
-#ifdef STBTT_STATIC
-#define STBTT_DEF static
-#else
-#define STBTT_DEF extern
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// private structure
-typedef struct
-{
-   unsigned char *data;
-   int cursor;
-   int size;
-} stbtt__buf;
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// TEXTURE BAKING API
-//
-// If you use this API, you only have to call two functions ever.
-//
-
-typedef struct
-{
-   unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap
-   float xoff,yoff,xadvance;
-} stbtt_bakedchar;
-
-STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,  // font location (use offset=0 for plain .ttf)
-                                float pixel_height,                     // height of font in pixels
-                                unsigned char *pixels, int pw, int ph,  // bitmap to be filled in
-                                int first_char, int num_chars,          // characters to bake
-                                stbtt_bakedchar *chardata);             // you allocate this, it's num_chars long
-// if return is positive, the first unused row of the bitmap
-// if return is negative, returns the negative of the number of characters that fit
-// if return is 0, no characters fit and no rows were used
-// This uses a very crappy packing.
-
-typedef struct
-{
-   float x0,y0,s0,t0; // top-left
-   float x1,y1,s1,t1; // bottom-right
-} stbtt_aligned_quad;
-
-STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph,  // same data as above
-                               int char_index,             // character to display
-                               float *xpos, float *ypos,   // pointers to current position in screen pixel space
-                               stbtt_aligned_quad *q,      // output: quad to draw
-                               int opengl_fillrule);       // true if opengl fill rule; false if DX9 or earlier
-// Call GetBakedQuad with char_index = 'character - first_char', and it
-// creates the quad you need to draw and advances the current position.
-//
-// The coordinate system used assumes y increases downwards.
-//
-// Characters will extend both above and below the current position;
-// see discussion of "BASELINE" above.
-//
-// It's inefficient; you might want to c&p it and optimize it.
-
-
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// NEW TEXTURE BAKING API
-//
-// This provides options for packing multiple fonts into one atlas, not
-// perfectly but better than nothing.
-
-typedef struct
-{
-   unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap
-   float xoff,yoff,xadvance;
-   float xoff2,yoff2;
-} stbtt_packedchar;
-
-typedef struct stbtt_pack_context stbtt_pack_context;
-typedef struct stbtt_fontinfo stbtt_fontinfo;
-#ifndef STB_RECT_PACK_VERSION
-typedef struct stbrp_rect stbrp_rect;
-#endif
-
-STBTT_DEF int  stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context);
-// Initializes a packing context stored in the passed-in stbtt_pack_context.
-// Future calls using this context will pack characters into the bitmap passed
-// in here: a 1-channel bitmap that is width * height. stride_in_bytes is
-// the distance from one row to the next (or 0 to mean they are packed tightly
-// together). "padding" is the amount of padding to leave between each
-// character (normally you want '1' for bitmaps you'll use as textures with
-// bilinear filtering).
-//
-// Returns 0 on failure, 1 on success.
-
-STBTT_DEF void stbtt_PackEnd  (stbtt_pack_context *spc);
-// Cleans up the packing context and frees all memory.
-
-#define STBTT_POINT_SIZE(x)   (-(x))
-
-STBTT_DEF int  stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,
-                                int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range);
-// Creates character bitmaps from the font_index'th font found in fontdata (use
-// font_index=0 if you don't know what that is). It creates num_chars_in_range
-// bitmaps for characters with unicode values starting at first_unicode_char_in_range
-// and increasing. Data for how to render them is stored in chardata_for_range;
-// pass these to stbtt_GetPackedQuad to get back renderable quads.
-//
-// font_size is the full height of the character from ascender to descender,
-// as computed by stbtt_ScaleForPixelHeight. To use a point size as computed
-// by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE()
-// and pass that result as 'font_size':
-//       ...,                  20 , ... // font max minus min y is 20 pixels tall
-//       ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall
-
-typedef struct
-{
-   float font_size;
-   int first_unicode_codepoint_in_range;  // if non-zero, then the chars are continuous, and this is the first codepoint
-   int *array_of_unicode_codepoints;       // if non-zero, then this is an array of unicode codepoints
-   int num_chars;
-   stbtt_packedchar *chardata_for_range; // output
-   unsigned char h_oversample, v_oversample; // don't set these, they're used internally
-} stbtt_pack_range;
-
-STBTT_DEF int  stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges);
-// Creates character bitmaps from multiple ranges of characters stored in
-// ranges. This will usually create a better-packed bitmap than multiple
-// calls to stbtt_PackFontRange. Note that you can call this multiple
-// times within a single PackBegin/PackEnd.
-
-STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample);
-// Oversampling a font increases the quality by allowing higher-quality subpixel
-// positioning, and is especially valuable at smaller text sizes.
-//
-// This function sets the amount of oversampling for all following calls to
-// stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given
-// pack context. The default (no oversampling) is achieved by h_oversample=1
-// and v_oversample=1. The total number of pixels required is
-// h_oversample*v_oversample larger than the default; for example, 2x2
-// oversampling requires 4x the storage of 1x1. For best results, render
-// oversampled textures with bilinear filtering. Look at the readme in
-// stb/tests/oversample for information about oversampled fonts
-//
-// To use with PackFontRangesGather etc., you must set it before calls
-// call to PackFontRangesGatherRects.
-
-STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph,  // same data as above
-                               int char_index,             // character to display
-                               float *xpos, float *ypos,   // pointers to current position in screen pixel space
-                               stbtt_aligned_quad *q,      // output: quad to draw
-                               int align_to_integer);
-
-STBTT_DEF int  stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
-STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects);
-STBTT_DEF int  stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
-// Calling these functions in sequence is roughly equivalent to calling
-// stbtt_PackFontRanges(). If you more control over the packing of multiple
-// fonts, or if you want to pack custom data into a font texture, take a look
-// at the source to of stbtt_PackFontRanges() and create a custom version
-// using these functions, e.g. call GatherRects multiple times,
-// building up a single array of rects, then call PackRects once,
-// then call RenderIntoRects repeatedly. This may result in a
-// better packing than calling PackFontRanges multiple times
-// (or it may not).
-
-// this is an opaque structure that you shouldn't mess with which holds
-// all the context needed from PackBegin to PackEnd.
-struct stbtt_pack_context {
-   void *user_allocator_context;
-   void *pack_info;
-   int   width;
-   int   height;
-   int   stride_in_bytes;
-   int   padding;
-   unsigned int   h_oversample, v_oversample;
-   unsigned char *pixels;
-   void  *nodes;
-};
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// FONT LOADING
-//
-//
-
-STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data);
-// This function will determine the number of fonts in a font file.  TrueType
-// collection (.ttc) files may contain multiple fonts, while TrueType font
-// (.ttf) files only contain one font. The number of fonts can be used for
-// indexing with the previous function where the index is between zero and one
-// less than the total fonts. If an error occurs, -1 is returned.
-
-STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
-// Each .ttf/.ttc file may have more than one font. Each font has a sequential
-// index number starting from 0. Call this function to get the font offset for
-// a given index; it returns -1 if the index is out of range. A regular .ttf
-// file will only define one font and it always be at offset 0, so it will
-// return '0' for index 0, and -1 for all other indices.
-
-// The following structure is defined publically so you can declare one on
-// the stack or as a global or etc, but you should treat it as opaque.
-struct stbtt_fontinfo
-{
-   void           * userdata;
-   unsigned char  * data;              // pointer to .ttf file
-   int              fontstart;         // offset of start of font
-
-   int numGlyphs;                     // number of glyphs, needed for range checking
-
-   int loca,head,glyf,hhea,hmtx,kern,gpos; // table locations as offset from start of .ttf
-   int index_map;                     // a cmap mapping for our chosen character encoding
-   int indexToLocFormat;              // format needed to map from glyph index to glyph
-
-   stbtt__buf cff;                    // cff font data
-   stbtt__buf charstrings;            // the charstring index
-   stbtt__buf gsubrs;                 // global charstring subroutines index
-   stbtt__buf subrs;                  // private charstring subroutines index
-   stbtt__buf fontdicts;              // array of font dicts
-   stbtt__buf fdselect;               // map from glyph to fontdict
-};
-
-STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset);
-// Given an offset into the file that defines a font, this function builds
-// the necessary cached info for the rest of the system. You must allocate
-// the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't
-// need to do anything special to free it, because the contents are pure
-// value data with no additional data structures. Returns 0 on failure.
-
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// CHARACTER TO GLYPH-INDEX CONVERSIOn
-
-STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint);
-// If you're going to perform multiple operations on the same character
-// and you want a speed-up, call this function with the character you're
-// going to process, then use glyph-based functions instead of the
-// codepoint-based functions.
-
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// CHARACTER PROPERTIES
-//
-
-STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels);
-// computes a scale factor to produce a font whose "height" is 'pixels' tall.
-// Height is measured as the distance from the highest ascender to the lowest
-// descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics
-// and computing:
-//       scale = pixels / (ascent - descent)
-// so if you prefer to measure height by the ascent only, use a similar calculation.
-
-STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels);
-// computes a scale factor to produce a font whose EM size is mapped to
-// 'pixels' tall. This is probably what traditional APIs compute, but
-// I'm not positive.
-
-STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap);
-// ascent is the coordinate above the baseline the font extends; descent
-// is the coordinate below the baseline the font extends (i.e. it is typically negative)
-// lineGap is the spacing between one row's descent and the next row's ascent...
-// so you should advance the vertical position by "*ascent - *descent + *lineGap"
-//   these are expressed in unscaled coordinates, so you must multiply by
-//   the scale factor for a given size
-
-STBTT_DEF int  stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap);
-// analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2
-// table (specific to MS/Windows TTF files).
-//
-// Returns 1 on success (table present), 0 on failure.
-
-STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1);
-// the bounding box around all possible characters
-
-STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing);
-// leftSideBearing is the offset from the current horizontal position to the left edge of the character
-// advanceWidth is the offset from the current horizontal position to the next horizontal position
-//   these are expressed in unscaled coordinates
-
-STBTT_DEF int  stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2);
-// an additional amount to add to the 'advance' value between ch1 and ch2
-
-STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1);
-// Gets the bounding box of the visible part of the glyph, in unscaled coordinates
-
-STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing);
-STBTT_DEF int  stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2);
-STBTT_DEF int  stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
-// as above, but takes one or more glyph indices for greater efficiency
-
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// GLYPH SHAPES (you probably don't need these, but they have to go before
-// the bitmaps for C declaration-order reasons)
-//
-
-#ifndef STBTT_vmove // you can predefine these to use different values (but why?)
-   enum {
-      STBTT_vmove=1,
-      STBTT_vline,
-      STBTT_vcurve,
-      STBTT_vcubic
-   };
-#endif
-
-#ifndef stbtt_vertex // you can predefine this to use different values
-                   // (we share this with other code at RAD)
-   #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file
-   typedef struct
-   {
-      stbtt_vertex_type x,y,cx,cy,cx1,cy1;
-      unsigned char type,padding;
-   } stbtt_vertex;
-#endif
-
-STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index);
-// returns non-zero if nothing is drawn for this glyph
-
-STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices);
-STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices);
-// returns # of vertices and fills *vertices with the pointer to them
-//   these are expressed in "unscaled" coordinates
-//
-// The shape is a series of countours. Each one starts with
-// a STBTT_moveto, then consists of a series of mixed
-// STBTT_lineto and STBTT_curveto segments. A lineto
-// draws a line from previous endpoint to its x,y; a curveto
-// draws a quadratic bezier from previous endpoint to
-// its x,y, using cx,cy as the bezier control point.
-
-STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
-// frees the data allocated above
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// BITMAP RENDERING
-//
-
-STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata);
-// frees the bitmap allocated below
-
-STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
-// allocates a large-enough single-channel 8bpp bitmap and renders the
-// specified character/glyph at the specified scale into it, with
-// antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque).
-// *width & *height are filled out with the width & height of the bitmap,
-// which is stored left-to-right, top-to-bottom.
-//
-// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap
-
-STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
-// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel
-// shift for the character
-
-STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint);
-// the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap
-// in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap
-// is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the
-// width and height and positioning info for it first.
-
-STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint);
-// same as stbtt_MakeCodepointBitmap, but you can specify a subpixel
-// shift for the character
-
-STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint);
-// same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering
-// is performed (see stbtt_PackSetOversampling)
-
-STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
-// get the bbox of the bitmap centered around the glyph origin; so the
-// bitmap width is ix1-ix0, height is iy1-iy0, and location to place
-// the bitmap top left is (leftSideBearing*scale,iy0).
-// (Note that the bitmap uses y-increases-down, but the shape uses
-// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.)
-
-STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);
-// same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel
-// shift for the character
-
-// the following functions are equivalent to the above functions, but operate
-// on glyph indices instead of Unicode codepoints (for efficiency)
-STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff);
-STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff);
-STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph);
-STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph);
-STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph);
-STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
-STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);
-
-
-// @TODO: don't expose this structure
-typedef struct
-{
-   int w,h,stride;
-   unsigned char *pixels;
-} stbtt__bitmap;
-
-// rasterize a shape with quadratic beziers into a bitmap
-STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result,        // 1-channel bitmap to draw into
-                               float flatness_in_pixels,     // allowable error of curve in pixels
-                               stbtt_vertex *vertices,       // array of vertices defining shape
-                               int num_verts,                // number of vertices in above array
-                               float scale_x, float scale_y, // scale applied to input vertices
-                               float shift_x, float shift_y, // translation applied to input vertices
-                               int x_off, int y_off,         // another translation applied to input
-                               int invert,                   // if non-zero, vertically flip shape
-                               void *userdata);              // context for to STBTT_MALLOC
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// Signed Distance Function (or Field) rendering
-
-STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata);
-// frees the SDF bitmap allocated below
-
-STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
-STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
-// These functions compute a discretized SDF field for a single character, suitable for storing
-// in a single-channel texture, sampling with bilinear filtering, and testing against
-// larger than some threshhold to produce scalable fonts.
-//        info              --  the font
-//        scale             --  controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap
-//        glyph/codepoint   --  the character to generate the SDF for
-//        padding           --  extra "pixels" around the character which are filled with the distance to the character (not 0),
-//                                 which allows effects like bit outlines
-//        onedge_value      --  value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character)
-//        pixel_dist_scale  --  what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale)
-//                                 if positive, > onedge_value is inside; if negative, < onedge_value is inside
-//        width,height      --  output height & width of the SDF bitmap (including padding)
-//        xoff,yoff         --  output origin of the character
-//        return value      --  a 2D array of bytes 0..255, width*height in size
-//
-// pixel_dist_scale & onedge_value are a scale & bias that allows you to make
-// optimal use of the limited 0..255 for your application, trading off precision
-// and special effects. SDF values outside the range 0..255 are clamped to 0..255.
-//
-// Example:
-//      scale = stbtt_ScaleForPixelHeight(22)
-//      padding = 5
-//      onedge_value = 180
-//      pixel_dist_scale = 180/5.0 = 36.0
-//
-//      This will create an SDF bitmap in which the character is about 22 pixels
-//      high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled
-//      shape, sample the SDF at each pixel and fill the pixel if the SDF value
-//      is greater than or equal to 180/255. (You'll actually want to antialias,
-//      which is beyond the scope of this example.) Additionally, you can compute
-//      offset outlines (e.g. to stroke the character border inside & outside,
-//      or only outside). For example, to fill outside the character up to 3 SDF
-//      pixels, you would compare against (180-36.0*3)/255 = 72/255. The above
-//      choice of variables maps a range from 5 pixels outside the shape to
-//      2 pixels inside the shape to 0..255; this is intended primarily for apply
-//      outside effects only (the interior range is needed to allow proper
-//      antialiasing of the font at *smaller* sizes)
-//
-// The function computes the SDF analytically at each SDF pixel, not by e.g.
-// building a higher-res bitmap and approximating it. In theory the quality
-// should be as high as possible for an SDF of this size & representation, but
-// unclear if this is true in practice (perhaps building a higher-res bitmap
-// and computing from that can allow drop-out prevention).
-//
-// The algorithm has not been optimized at all, so expect it to be slow
-// if computing lots of characters or very large sizes.
-
-
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// Finding the right font...
-//
-// You should really just solve this offline, keep your own tables
-// of what font is what, and don't try to get it out of the .ttf file.
-// That's because getting it out of the .ttf file is really hard, because
-// the names in the file can appear in many possible encodings, in many
-// possible languages, and e.g. if you need a case-insensitive comparison,
-// the details of that depend on the encoding & language in a complex way
-// (actually underspecified in truetype, but also gigantic).
-//
-// But you can use the provided functions in two possible ways:
-//     stbtt_FindMatchingFont() will use *case-sensitive* comparisons on
-//             unicode-encoded names to try to find the font you want;
-//             you can run this before calling stbtt_InitFont()
-//
-//     stbtt_GetFontNameString() lets you get any of the various strings
-//             from the file yourself and do your own comparisons on them.
-//             You have to have called stbtt_InitFont() first.
-
-
-STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags);
-// returns the offset (not index) of the font that matches, or -1 if none
-//   if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold".
-//   if you use any other flag, use a font name like "Arial"; this checks
-//     the 'macStyle' header field; i don't know if fonts set this consistently
-#define STBTT_MACSTYLE_DONTCARE     0
-#define STBTT_MACSTYLE_BOLD         1
-#define STBTT_MACSTYLE_ITALIC       2
-#define STBTT_MACSTYLE_UNDERSCORE   4
-#define STBTT_MACSTYLE_NONE         8   // <= not same as 0, this makes us check the bitfield is 0
-
-STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2);
-// returns 1/0 whether the first string interpreted as utf8 is identical to
-// the second string interpreted as big-endian utf16... useful for strings from next func
-
-STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID);
-// returns the string (which may be big-endian double byte, e.g. for unicode)
-// and puts the length in bytes in *length.
-//
-// some of the values for the IDs are below; for more see the truetype spec:
-//     http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html
-//     http://www.microsoft.com/typography/otspec/name.htm
-
-enum { // platformID
-   STBTT_PLATFORM_ID_UNICODE   =0,
-   STBTT_PLATFORM_ID_MAC       =1,
-   STBTT_PLATFORM_ID_ISO       =2,
-   STBTT_PLATFORM_ID_MICROSOFT =3
-};
-
-enum { // encodingID for STBTT_PLATFORM_ID_UNICODE
-   STBTT_UNICODE_EID_UNICODE_1_0    =0,
-   STBTT_UNICODE_EID_UNICODE_1_1    =1,
-   STBTT_UNICODE_EID_ISO_10646      =2,
-   STBTT_UNICODE_EID_UNICODE_2_0_BMP=3,
-   STBTT_UNICODE_EID_UNICODE_2_0_FULL=4
-};
-
-enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT
-   STBTT_MS_EID_SYMBOL        =0,
-   STBTT_MS_EID_UNICODE_BMP   =1,
-   STBTT_MS_EID_SHIFTJIS      =2,
-   STBTT_MS_EID_UNICODE_FULL  =10
-};
-
-enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes
-   STBTT_MAC_EID_ROMAN        =0,   STBTT_MAC_EID_ARABIC       =4,
-   STBTT_MAC_EID_JAPANESE     =1,   STBTT_MAC_EID_HEBREW       =5,
-   STBTT_MAC_EID_CHINESE_TRAD =2,   STBTT_MAC_EID_GREEK        =6,
-   STBTT_MAC_EID_KOREAN       =3,   STBTT_MAC_EID_RUSSIAN      =7
-};
-
-enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID...
-       // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs
-   STBTT_MS_LANG_ENGLISH     =0x0409,   STBTT_MS_LANG_ITALIAN     =0x0410,
-   STBTT_MS_LANG_CHINESE     =0x0804,   STBTT_MS_LANG_JAPANESE    =0x0411,
-   STBTT_MS_LANG_DUTCH       =0x0413,   STBTT_MS_LANG_KOREAN      =0x0412,
-   STBTT_MS_LANG_FRENCH      =0x040c,   STBTT_MS_LANG_RUSSIAN     =0x0419,
-   STBTT_MS_LANG_GERMAN      =0x0407,   STBTT_MS_LANG_SPANISH     =0x0409,
-   STBTT_MS_LANG_HEBREW      =0x040d,   STBTT_MS_LANG_SWEDISH     =0x041D
-};
-
-enum { // languageID for STBTT_PLATFORM_ID_MAC
-   STBTT_MAC_LANG_ENGLISH      =0 ,   STBTT_MAC_LANG_JAPANESE     =11,
-   STBTT_MAC_LANG_ARABIC       =12,   STBTT_MAC_LANG_KOREAN       =23,
-   STBTT_MAC_LANG_DUTCH        =4 ,   STBTT_MAC_LANG_RUSSIAN      =32,
-   STBTT_MAC_LANG_FRENCH       =1 ,   STBTT_MAC_LANG_SPANISH      =6 ,
-   STBTT_MAC_LANG_GERMAN       =2 ,   STBTT_MAC_LANG_SWEDISH      =5 ,
-   STBTT_MAC_LANG_HEBREW       =10,   STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33,
-   STBTT_MAC_LANG_ITALIAN      =3 ,   STBTT_MAC_LANG_CHINESE_TRAD =19
-};
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // __STB_INCLUDE_STB_TRUETYPE_H__
-
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-////
-////   IMPLEMENTATION
-////
-////
-
-#ifdef STB_TRUETYPE_IMPLEMENTATION
-
-#ifndef STBTT_MAX_OVERSAMPLE
-#define STBTT_MAX_OVERSAMPLE   8
-#endif
-
-#if STBTT_MAX_OVERSAMPLE > 255
-#error "STBTT_MAX_OVERSAMPLE cannot be > 255"
-#endif
-
-typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1];
-
-#ifndef STBTT_RASTERIZER_VERSION
-#define STBTT_RASTERIZER_VERSION 2
-#endif
-
-#ifdef _MSC_VER
-#define STBTT__NOTUSED(v)  (void)(v)
-#else
-#define STBTT__NOTUSED(v)  (void)sizeof(v)
-#endif
-
-//////////////////////////////////////////////////////////////////////////
-//
-// stbtt__buf helpers to parse data from file
-//
-
-static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b)
-{
-   if (b->cursor >= b->size)
-      return 0;
-   return b->data[b->cursor++];
-}
-
-static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b)
-{
-   if (b->cursor >= b->size)
-      return 0;
-   return b->data[b->cursor];
-}
-
-static void stbtt__buf_seek(stbtt__buf *b, int o)
-{
-   STBTT_assert(!(o > b->size || o < 0));
-   b->cursor = (o > b->size || o < 0) ? b->size : o;
-}
-
-static void stbtt__buf_skip(stbtt__buf *b, int o)
-{
-   stbtt__buf_seek(b, b->cursor + o);
-}
-
-static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n)
-{
-   stbtt_uint32 v = 0;
-   int i;
-   STBTT_assert(n >= 1 && n <= 4);
-   for (i = 0; i < n; i++)
-      v = (v << 8) | stbtt__buf_get8(b);
-   return v;
-}
-
-static stbtt__buf stbtt__new_buf(const void *p, size_t size)
-{
-   stbtt__buf r;
-   STBTT_assert(size < 0x40000000);
-   r.data = (stbtt_uint8*) p;
-   r.size = (int) size;
-   r.cursor = 0;
-   return r;
-}
-
-#define stbtt__buf_get16(b)  stbtt__buf_get((b), 2)
-#define stbtt__buf_get32(b)  stbtt__buf_get((b), 4)
-
-static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s)
-{
-   stbtt__buf r = stbtt__new_buf(NULL, 0);
-   if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r;
-   r.data = b->data + o;
-   r.size = s;
-   return r;
-}
-
-static stbtt__buf stbtt__cff_get_index(stbtt__buf *b)
-{
-   int count, start, offsize;
-   start = b->cursor;
-   count = stbtt__buf_get16(b);
-   if (count) {
-      offsize = stbtt__buf_get8(b);
-      STBTT_assert(offsize >= 1 && offsize <= 4);
-      stbtt__buf_skip(b, offsize * count);
-      stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1);
-   }
-   return stbtt__buf_range(b, start, b->cursor - start);
-}
-
-static stbtt_uint32 stbtt__cff_int(stbtt__buf *b)
-{
-   int b0 = stbtt__buf_get8(b);
-   if (b0 >= 32 && b0 <= 246)       return b0 - 139;
-   else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108;
-   else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108;
-   else if (b0 == 28)               return stbtt__buf_get16(b);
-   else if (b0 == 29)               return stbtt__buf_get32(b);
-   STBTT_assert(0);
-   return 0;
-}
-
-static void stbtt__cff_skip_operand(stbtt__buf *b) {
-   int v, b0 = stbtt__buf_peek8(b);
-   STBTT_assert(b0 >= 28);
-   if (b0 == 30) {
-      stbtt__buf_skip(b, 1);
-      while (b->cursor < b->size) {
-         v = stbtt__buf_get8(b);
-         if ((v & 0xF) == 0xF || (v >> 4) == 0xF)
-            break;
-      }
-   } else {
-      stbtt__cff_int(b);
-   }
-}
-
-static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key)
-{
-   stbtt__buf_seek(b, 0);
-   while (b->cursor < b->size) {
-      int start = b->cursor, end, op;
-      while (stbtt__buf_peek8(b) >= 28)
-         stbtt__cff_skip_operand(b);
-      end = b->cursor;
-      op = stbtt__buf_get8(b);
-      if (op == 12)  op = stbtt__buf_get8(b) | 0x100;
-      if (op == key) return stbtt__buf_range(b, start, end-start);
-   }
-   return stbtt__buf_range(b, 0, 0);
-}
-
-static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out)
-{
-   int i;
-   stbtt__buf operands = stbtt__dict_get(b, key);
-   for (i = 0; i < outcount && operands.cursor < operands.size; i++)
-      out[i] = stbtt__cff_int(&operands);
-}
-
-static int stbtt__cff_index_count(stbtt__buf *b)
-{
-   stbtt__buf_seek(b, 0);
-   return stbtt__buf_get16(b);
-}
-
-static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i)
-{
-   int count, offsize, start, end;
-   stbtt__buf_seek(&b, 0);
-   count = stbtt__buf_get16(&b);
-   offsize = stbtt__buf_get8(&b);
-   STBTT_assert(i >= 0 && i < count);
-   STBTT_assert(offsize >= 1 && offsize <= 4);
-   stbtt__buf_skip(&b, i*offsize);
-   start = stbtt__buf_get(&b, offsize);
-   end = stbtt__buf_get(&b, offsize);
-   return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start);
-}
-
-//////////////////////////////////////////////////////////////////////////
-//
-// accessors to parse data from file
-//
-
-// on platforms that don't allow misaligned reads, if we want to allow
-// truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE
-
-#define ttBYTE(p)     (* (stbtt_uint8 *) (p))
-#define ttCHAR(p)     (* (stbtt_int8 *) (p))
-#define ttFixed(p)    ttLONG(p)
-
-static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; }
-static stbtt_int16 ttSHORT(stbtt_uint8 *p)   { return p[0]*256 + p[1]; }
-static stbtt_uint32 ttULONG(stbtt_uint8 *p)  { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
-static stbtt_int32 ttLONG(stbtt_uint8 *p)    { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
-
-#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
-#define stbtt_tag(p,str)           stbtt_tag4(p,str[0],str[1],str[2],str[3])
-
-static int stbtt__isfont(stbtt_uint8 *font)
-{
-   // check the version number
-   if (stbtt_tag4(font, '1',0,0,0))  return 1; // TrueType 1
-   if (stbtt_tag(font, "typ1"))   return 1; // TrueType with type 1 font -- we don't support this!
-   if (stbtt_tag(font, "OTTO"))   return 1; // OpenType with CFF
-   if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0
-   if (stbtt_tag(font, "true"))   return 1; // Apple specification for TrueType fonts
-   return 0;
-}
-
-// @OPTIMIZE: binary search
-static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag)
-{
-   stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);
-   stbtt_uint32 tabledir = fontstart + 12;
-   stbtt_int32 i;
-   for (i=0; i < num_tables; ++i) {
-      stbtt_uint32 loc = tabledir + 16*i;
-      if (stbtt_tag(data+loc+0, tag))
-         return ttULONG(data+loc+8);
-   }
-   return 0;
-}
-
-static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index)
-{
-   // if it's just a font, there's only one valid index
-   if (stbtt__isfont(font_collection))
-      return index == 0 ? 0 : -1;
-
-   // check if it's a TTC
-   if (stbtt_tag(font_collection, "ttcf")) {
-      // version 1?
-      if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
-         stbtt_int32 n = ttLONG(font_collection+8);
-         if (index >= n)
-            return -1;
-         return ttULONG(font_collection+12+index*4);
-      }
-   }
-   return -1;
-}
-
-static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection)
-{
-   // if it's just a font, there's only one valid font
-   if (stbtt__isfont(font_collection))
-      return 1;
-
-   // check if it's a TTC
-   if (stbtt_tag(font_collection, "ttcf")) {
-      // version 1?
-      if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
-         return ttLONG(font_collection+8);
-      }
-   }
-   return 0;
-}
-
-static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict)
-{
-   stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 };
-   stbtt__buf pdict;
-   stbtt__dict_get_ints(&fontdict, 18, 2, private_loc);
-   if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0);
-   pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]);
-   stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff);
-   if (!subrsoff) return stbtt__new_buf(NULL, 0);
-   stbtt__buf_seek(&cff, private_loc[1]+subrsoff);
-   return stbtt__cff_get_index(&cff);
-}
-
-static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart)
-{
-   stbtt_uint32 cmap, t;
-   stbtt_int32 i,numTables;
-
-   info->data = data;
-   info->fontstart = fontstart;
-   info->cff = stbtt__new_buf(NULL, 0);
-
-   cmap = stbtt__find_table(data, fontstart, "cmap");       // required
-   info->loca = stbtt__find_table(data, fontstart, "loca"); // required
-   info->head = stbtt__find_table(data, fontstart, "head"); // required
-   info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required
-   info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required
-   info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required
-   info->kern = stbtt__find_table(data, fontstart, "kern"); // not required
-   info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required
-
-   if (!cmap || !info->head || !info->hhea || !info->hmtx)
-      return 0;
-   if (info->glyf) {
-      // required for truetype
-      if (!info->loca) return 0;
-   } else {
-      // initialization for CFF / Type2 fonts (OTF)
-      stbtt__buf b, topdict, topdictidx;
-      stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0;
-      stbtt_uint32 cff;
-
-      cff = stbtt__find_table(data, fontstart, "CFF ");
-      if (!cff) return 0;
-
-      info->fontdicts = stbtt__new_buf(NULL, 0);
-      info->fdselect = stbtt__new_buf(NULL, 0);
-
-      // @TODO this should use size from table (not 512MB)
-      info->cff = stbtt__new_buf(data+cff, 512*1024*1024);
-      b = info->cff;
-
-      // read the header
-      stbtt__buf_skip(&b, 2);
-      stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize
-
-      // @TODO the name INDEX could list multiple fonts,
-      // but we just use the first one.
-      stbtt__cff_get_index(&b);  // name INDEX
-      topdictidx = stbtt__cff_get_index(&b);
-      topdict = stbtt__cff_index_get(topdictidx, 0);
-      stbtt__cff_get_index(&b);  // string INDEX
-      info->gsubrs = stbtt__cff_get_index(&b);
-
-      stbtt__dict_get_ints(&topdict, 17, 1, &charstrings);
-      stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype);
-      stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff);
-      stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff);
-      info->subrs = stbtt__get_subrs(b, topdict);
-
-      // we only support Type 2 charstrings
-      if (cstype != 2) return 0;
-      if (charstrings == 0) return 0;
-
-      if (fdarrayoff) {
-         // looks like a CID font
-         if (!fdselectoff) return 0;
-         stbtt__buf_seek(&b, fdarrayoff);
-         info->fontdicts = stbtt__cff_get_index(&b);
-         info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff);
-      }
-
-      stbtt__buf_seek(&b, charstrings);
-      info->charstrings = stbtt__cff_get_index(&b);
-   }
-
-   t = stbtt__find_table(data, fontstart, "maxp");
-   if (t)
-      info->numGlyphs = ttUSHORT(data+t+4);
-   else
-      info->numGlyphs = 0xffff;
-
-   // find a cmap encoding table we understand *now* to avoid searching
-   // later. (todo: could make this installable)
-   // the same regardless of glyph.
-   numTables = ttUSHORT(data + cmap + 2);
-   info->index_map = 0;
-   for (i=0; i < numTables; ++i) {
-      stbtt_uint32 encoding_record = cmap + 4 + 8 * i;
-      // find an encoding we understand:
-      switch(ttUSHORT(data+encoding_record)) {
-         case STBTT_PLATFORM_ID_MICROSOFT:
-            switch (ttUSHORT(data+encoding_record+2)) {
-               case STBTT_MS_EID_UNICODE_BMP:
-               case STBTT_MS_EID_UNICODE_FULL:
-                  // MS/Unicode
-                  info->index_map = cmap + ttULONG(data+encoding_record+4);
-                  break;
-            }
-            break;
-        case STBTT_PLATFORM_ID_UNICODE:
-            // Mac/iOS has these
-            // all the encodingIDs are unicode, so we don't bother to check it
-            info->index_map = cmap + ttULONG(data+encoding_record+4);
-            break;
-      }
-   }
-   if (info->index_map == 0)
-      return 0;
-
-   info->indexToLocFormat = ttUSHORT(data+info->head + 50);
-   return 1;
-}
-
-STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
-{
-   stbtt_uint8 *data = info->data;
-   stbtt_uint32 index_map = info->index_map;
-
-   stbtt_uint16 format = ttUSHORT(data + index_map + 0);
-   if (format == 0) { // apple byte encoding
-      stbtt_int32 bytes = ttUSHORT(data + index_map + 2);
-      if (unicode_codepoint < bytes-6)
-         return ttBYTE(data + index_map + 6 + unicode_codepoint);
-      return 0;
-   } else if (format == 6) {
-      stbtt_uint32 first = ttUSHORT(data + index_map + 6);
-      stbtt_uint32 count = ttUSHORT(data + index_map + 8);
-      if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count)
-         return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2);
-      return 0;
-   } else if (format == 2) {
-      STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean
-      return 0;
-   } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges
-      stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1;
-      stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1;
-      stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10);
-      stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1;
-
-      // do a binary search of the segments
-      stbtt_uint32 endCount = index_map + 14;
-      stbtt_uint32 search = endCount;
-
-      if (unicode_codepoint > 0xffff)
-         return 0;
-
-      // they lie from endCount .. endCount + segCount
-      // but searchRange is the nearest power of two, so...
-      if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2))
-         search += rangeShift*2;
-
-      // now decrement to bias correctly to find smallest
-      search -= 2;
-      while (entrySelector) {
-         stbtt_uint16 end;
-         searchRange >>= 1;
-         end = ttUSHORT(data + search + searchRange*2);
-         if (unicode_codepoint > end)
-            search += searchRange*2;
-         --entrySelector;
-      }
-      search += 2;
-
-      {
-         stbtt_uint16 offset, start;
-         stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);
-
-         STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
-         start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
-         if (unicode_codepoint < start)
-            return 0;
-
-         offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
-         if (offset == 0)
-            return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
-
-         return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
-      }
-   } else if (format == 12 || format == 13) {
-      stbtt_uint32 ngroups = ttULONG(data+index_map+12);
-      stbtt_int32 low,high;
-      low = 0; high = (stbtt_int32)ngroups;
-      // Binary search the right group.
-      while (low < high) {
-         stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high
-         stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12);
-         stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4);
-         if ((stbtt_uint32) unicode_codepoint < start_char)
-            high = mid;
-         else if ((stbtt_uint32) unicode_codepoint > end_char)
-            low = mid+1;
-         else {
-            stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8);
-            if (format == 12)
-               return start_glyph + unicode_codepoint-start_char;
-            else // format == 13
-               return start_glyph;
-         }
-      }
-      return 0; // not found
-   }
-   // @TODO
-   STBTT_assert(0);
-   return 0;
-}
-
-STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices)
-{
-   return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices);
-}
-
-static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy)
-{
-   v->type = type;
-   v->x = (stbtt_int16) x;
-   v->y = (stbtt_int16) y;
-   v->cx = (stbtt_int16) cx;
-   v->cy = (stbtt_int16) cy;
-}
-
-static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index)
-{
-   int g1,g2;
-
-   STBTT_assert(!info->cff.size);
-
-   if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range
-   if (info->indexToLocFormat >= 2)    return -1; // unknown index->glyph map format
-
-   if (info->indexToLocFormat == 0) {
-      g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
-      g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
-   } else {
-      g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4);
-      g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4);
-   }
-
-   return g1==g2 ? -1 : g1; // if length is 0, return -1
-}
-
-static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
-
-STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
-{
-   if (info->cff.size) {
-      stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1);
-   } else {
-      int g = stbtt__GetGlyfOffset(info, glyph_index);
-      if (g < 0) return 0;
-
-      if (x0) *x0 = ttSHORT(info->data + g + 2);
-      if (y0) *y0 = ttSHORT(info->data + g + 4);
-      if (x1) *x1 = ttSHORT(info->data + g + 6);
-      if (y1) *y1 = ttSHORT(info->data + g + 8);
-   }
-   return 1;
-}
-
-STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1)
-{
-   return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1);
-}
-
-STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index)
-{
-   stbtt_int16 numberOfContours;
-   int g;
-   if (info->cff.size)
-      return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0;
-   g = stbtt__GetGlyfOffset(info, glyph_index);
-   if (g < 0) return 1;
-   numberOfContours = ttSHORT(info->data + g);
-   return numberOfContours == 0;
-}
-
-static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off,
-    stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy)
-{
-   if (start_off) {
-      if (was_off)
-         stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
-      stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy);
-   } else {
-      if (was_off)
-         stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy);
-      else
-         stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);
-   }
-   return num_vertices;
-}
-
-static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
-{
-   stbtt_int16 numberOfContours;
-   stbtt_uint8 *endPtsOfContours;
-   stbtt_uint8 *data = info->data;
-   stbtt_vertex *vertices=0;
-   int num_vertices=0;
-   int g = stbtt__GetGlyfOffset(info, glyph_index);
-
-   *pvertices = NULL;
-
-   if (g < 0) return 0;
-
-   numberOfContours = ttSHORT(data + g);
-
-   if (numberOfContours > 0) {
-      stbtt_uint8 flags=0,flagcount;
-      stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
-      stbtt_int32 x,y,cx,cy,sx,sy, scx,scy;
-      stbtt_uint8 *points;
-      endPtsOfContours = (data + g + 10);
-      ins = ttUSHORT(data + g + 10 + numberOfContours * 2);
-      points = data + g + 10 + numberOfContours * 2 + 2 + ins;
-
-      n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);
-
-      m = n + 2*numberOfContours;  // a loose bound on how many vertices we might need
-      vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata);
-      if (vertices == 0)
-         return 0;
-
-      next_move = 0;
-      flagcount=0;
-
-      // in first pass, we load uninterpreted data into the allocated array
-      // above, shifted to the end of the array so we won't overwrite it when
-      // we create our final data starting from the front
-
-      off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated
-
-      // first load flags
-
-      for (i=0; i < n; ++i) {
-         if (flagcount == 0) {
-            flags = *points++;
-            if (flags & 8)
-               flagcount = *points++;
-         } else
-            --flagcount;
-         vertices[off+i].type = flags;
-      }
-
-      // now load x coordinates
-      x=0;
-      for (i=0; i < n; ++i) {
-         flags = vertices[off+i].type;
-         if (flags & 2) {
-            stbtt_int16 dx = *points++;
-            x += (flags & 16) ? dx : -dx; // ???
-         } else {
-            if (!(flags & 16)) {
-               x = x + (stbtt_int16) (points[0]*256 + points[1]);
-               points += 2;
-            }
-         }
-         vertices[off+i].x = (stbtt_int16) x;
-      }
-
-      // now load y coordinates
-      y=0;
-      for (i=0; i < n; ++i) {
-         flags = vertices[off+i].type;
-         if (flags & 4) {
-            stbtt_int16 dy = *points++;
-            y += (flags & 32) ? dy : -dy; // ???
-         } else {
-            if (!(flags & 32)) {
-               y = y + (stbtt_int16) (points[0]*256 + points[1]);
-               points += 2;
-            }
-         }
-         vertices[off+i].y = (stbtt_int16) y;
-      }
-
-      // now convert them to our format
-      num_vertices=0;
-      sx = sy = cx = cy = scx = scy = 0;
-      for (i=0; i < n; ++i) {
-         flags = vertices[off+i].type;
-         x     = (stbtt_int16) vertices[off+i].x;
-         y     = (stbtt_int16) vertices[off+i].y;
-
-         if (next_move == i) {
-            if (i != 0)
-               num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
-
-            // now start the new one
-            start_off = !(flags & 1);
-            if (start_off) {
-               // if we start off with an off-curve point, then when we need to find a point on the curve
-               // where we can start, and we need to save some state for when we wraparound.
-               scx = x;
-               scy = y;
-               if (!(vertices[off+i+1].type & 1)) {
-                  // next point is also a curve point, so interpolate an on-point curve
-                  sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1;
-                  sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1;
-               } else {
-                  // otherwise just use the next point as our start point
-                  sx = (stbtt_int32) vertices[off+i+1].x;
-                  sy = (stbtt_int32) vertices[off+i+1].y;
-                  ++i; // we're using point i+1 as the starting point, so skip it
-               }
-            } else {
-               sx = x;
-               sy = y;
-            }
-            stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0);
-            was_off = 0;
-            next_move = 1 + ttUSHORT(endPtsOfContours+j*2);
-            ++j;
-         } else {
-            if (!(flags & 1)) { // if it's a curve
-               if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint
-                  stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
-               cx = x;
-               cy = y;
-               was_off = 1;
-            } else {
-               if (was_off)
-                  stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy);
-               else
-                  stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0);
-               was_off = 0;
-            }
-         }
-      }
-      num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
-   } else if (numberOfContours == -1) {
-      // Compound shapes.
-      int more = 1;
-      stbtt_uint8 *comp = data + g + 10;
-      num_vertices = 0;
-      vertices = 0;
-      while (more) {
-         stbtt_uint16 flags, gidx;
-         int comp_num_verts = 0, i;
-         stbtt_vertex *comp_verts = 0, *tmp = 0;
-         float mtx[6] = {1,0,0,1,0,0}, m, n;
-
-         flags = ttSHORT(comp); comp+=2;
-         gidx = ttSHORT(comp); comp+=2;
-
-         if (flags & 2) { // XY values
-            if (flags & 1) { // shorts
-               mtx[4] = ttSHORT(comp); comp+=2;
-               mtx[5] = ttSHORT(comp); comp+=2;
-            } else {
-               mtx[4] = ttCHAR(comp); comp+=1;
-               mtx[5] = ttCHAR(comp); comp+=1;
-            }
-         }
-         else {
-            // @TODO handle matching point
-            STBTT_assert(0);
-         }
-         if (flags & (1<<3)) { // WE_HAVE_A_SCALE
-            mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
-            mtx[1] = mtx[2] = 0;
-         } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE
-            mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
-            mtx[1] = mtx[2] = 0;
-            mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
-         } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO
-            mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
-            mtx[1] = ttSHORT(comp)/16384.0f; comp+=2;
-            mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;
-            mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
-         }
-
-         // Find transformation scales.
-         m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
-         n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
-
-         // Get indexed glyph.
-         comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts);
-         if (comp_num_verts > 0) {
-            // Transform vertices.
-            for (i = 0; i < comp_num_verts; ++i) {
-               stbtt_vertex* v = &comp_verts[i];
-               stbtt_vertex_type x,y;
-               x=v->x; y=v->y;
-               v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
-               v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
-               x=v->cx; y=v->cy;
-               v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
-               v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
-            }
-            // Append vertices.
-            tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata);
-            if (!tmp) {
-               if (vertices) STBTT_free(vertices, info->userdata);
-               if (comp_verts) STBTT_free(comp_verts, info->userdata);
-               return 0;
-            }
-            if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
-            STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
-            if (vertices) STBTT_free(vertices, info->userdata);
-            vertices = tmp;
-            STBTT_free(comp_verts, info->userdata);
-            num_vertices += comp_num_verts;
-         }
-         // More components ?
-         more = flags & (1<<5);
-      }
-   } else if (numberOfContours < 0) {
-      // @TODO other compound variations?
-      STBTT_assert(0);
-   } else {
-      // numberOfCounters == 0, do nothing
-   }
-
-   *pvertices = vertices;
-   return num_vertices;
-}
-
-typedef struct
-{
-   int bounds;
-   int started;
-   float first_x, first_y;
-   float x, y;
-   stbtt_int32 min_x, max_x, min_y, max_y;
-
-   stbtt_vertex *pvertices;
-   int num_vertices;
-} stbtt__csctx;
-
-#define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0}
-
-static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y)
-{
-   if (x > c->max_x || !c->started) c->max_x = x;
-   if (y > c->max_y || !c->started) c->max_y = y;
-   if (x < c->min_x || !c->started) c->min_x = x;
-   if (y < c->min_y || !c->started) c->min_y = y;
-   c->started = 1;
-}
-
-static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1)
-{
-   if (c->bounds) {
-      stbtt__track_vertex(c, x, y);
-      if (type == STBTT_vcubic) {
-         stbtt__track_vertex(c, cx, cy);
-         stbtt__track_vertex(c, cx1, cy1);
-      }
-   } else {
-      stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy);
-      c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1;
-      c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1;
-   }
-   c->num_vertices++;
-}
-
-static void stbtt__csctx_close_shape(stbtt__csctx *ctx)
-{
-   if (ctx->first_x != ctx->x || ctx->first_y != ctx->y)
-      stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0);
-}
-
-static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy)
-{
-   stbtt__csctx_close_shape(ctx);
-   ctx->first_x = ctx->x = ctx->x + dx;
-   ctx->first_y = ctx->y = ctx->y + dy;
-   stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
-}
-
-static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy)
-{
-   ctx->x += dx;
-   ctx->y += dy;
-   stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
-}
-
-static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3)
-{
-   float cx1 = ctx->x + dx1;
-   float cy1 = ctx->y + dy1;
-   float cx2 = cx1 + dx2;
-   float cy2 = cy1 + dy2;
-   ctx->x = cx2 + dx3;
-   ctx->y = cy2 + dy3;
-   stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2);
-}
-
-static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n)
-{
-   int count = stbtt__cff_index_count(&idx);
-   int bias = 107;
-   if (count >= 33900)
-      bias = 32768;
-   else if (count >= 1240)
-      bias = 1131;
-   n += bias;
-   if (n < 0 || n >= count)
-      return stbtt__new_buf(NULL, 0);
-   return stbtt__cff_index_get(idx, n);
-}
-
-static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index)
-{
-   stbtt__buf fdselect = info->fdselect;
-   int nranges, start, end, v, fmt, fdselector = -1, i;
-
-   stbtt__buf_seek(&fdselect, 0);
-   fmt = stbtt__buf_get8(&fdselect);
-   if (fmt == 0) {
-      // untested
-      stbtt__buf_skip(&fdselect, glyph_index);
-      fdselector = stbtt__buf_get8(&fdselect);
-   } else if (fmt == 3) {
-      nranges = stbtt__buf_get16(&fdselect);
-      start = stbtt__buf_get16(&fdselect);
-      for (i = 0; i < nranges; i++) {
-         v = stbtt__buf_get8(&fdselect);
-         end = stbtt__buf_get16(&fdselect);
-         if (glyph_index >= start && glyph_index < end) {
-            fdselector = v;
-            break;
-         }
-         start = end;
-      }
-   }
-   if (fdselector == -1) stbtt__new_buf(NULL, 0);
-   return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector));
-}
-
-static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c)
-{
-   int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0;
-   int has_subrs = 0, clear_stack;
-   float s[48];
-   stbtt__buf subr_stack[10], subrs = info->subrs, b;
-   float f;
-
-#define STBTT__CSERR(s) (0)
-
-   // this currently ignores the initial width value, which isn't needed if we have hmtx
-   b = stbtt__cff_index_get(info->charstrings, glyph_index);
-   while (b.cursor < b.size) {
-      i = 0;
-      clear_stack = 1;
-      b0 = stbtt__buf_get8(&b);
-      switch (b0) {
-      // @TODO implement hinting
-      case 0x13: // hintmask
-      case 0x14: // cntrmask
-         if (in_header)
-            maskbits += (sp / 2); // implicit "vstem"
-         in_header = 0;
-         stbtt__buf_skip(&b, (maskbits + 7) / 8);
-         break;
-
-      case 0x01: // hstem
-      case 0x03: // vstem
-      case 0x12: // hstemhm
-      case 0x17: // vstemhm
-         maskbits += (sp / 2);
-         break;
-
-      case 0x15: // rmoveto
-         in_header = 0;
-         if (sp < 2) return STBTT__CSERR("rmoveto stack");
-         stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]);
-         break;
-      case 0x04: // vmoveto
-         in_header = 0;
-         if (sp < 1) return STBTT__CSERR("vmoveto stack");
-         stbtt__csctx_rmove_to(c, 0, s[sp-1]);
-         break;
-      case 0x16: // hmoveto
-         in_header = 0;
-         if (sp < 1) return STBTT__CSERR("hmoveto stack");
-         stbtt__csctx_rmove_to(c, s[sp-1], 0);
-         break;
-
-      case 0x05: // rlineto
-         if (sp < 2) return STBTT__CSERR("rlineto stack");
-         for (; i + 1 < sp; i += 2)
-            stbtt__csctx_rline_to(c, s[i], s[i+1]);
-         break;
-
-      // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical
-      // starting from a different place.
-
-      case 0x07: // vlineto
-         if (sp < 1) return STBTT__CSERR("vlineto stack");
-         goto vlineto;
-      case 0x06: // hlineto
-         if (sp < 1) return STBTT__CSERR("hlineto stack");
-         for (;;) {
-            if (i >= sp) break;
-            stbtt__csctx_rline_to(c, s[i], 0);
-            i++;
-      vlineto:
-            if (i >= sp) break;
-            stbtt__csctx_rline_to(c, 0, s[i]);
-            i++;
-         }
-         break;
-
-      case 0x1F: // hvcurveto
-         if (sp < 4) return STBTT__CSERR("hvcurveto stack");
-         goto hvcurveto;
-      case 0x1E: // vhcurveto
-         if (sp < 4) return STBTT__CSERR("vhcurveto stack");
-         for (;;) {
-            if (i + 3 >= sp) break;
-            stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f);
-            i += 4;
-      hvcurveto:
-            if (i + 3 >= sp) break;
-            stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]);
-            i += 4;
-         }
-         break;
-
-      case 0x08: // rrcurveto
-         if (sp < 6) return STBTT__CSERR("rcurveline stack");
-         for (; i + 5 < sp; i += 6)
-            stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
-         break;
-
-      case 0x18: // rcurveline
-         if (sp < 8) return STBTT__CSERR("rcurveline stack");
-         for (; i + 5 < sp - 2; i += 6)
-            stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
-         if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack");
-         stbtt__csctx_rline_to(c, s[i], s[i+1]);
-         break;
-
-      case 0x19: // rlinecurve
-         if (sp < 8) return STBTT__CSERR("rlinecurve stack");
-         for (; i + 1 < sp - 6; i += 2)
-            stbtt__csctx_rline_to(c, s[i], s[i+1]);
-         if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack");
-         stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
-         break;
-
-      case 0x1A: // vvcurveto
-      case 0x1B: // hhcurveto
-         if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack");
-         f = 0.0;
-         if (sp & 1) { f = s[i]; i++; }
-         for (; i + 3 < sp; i += 4) {
-            if (b0 == 0x1B)
-               stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0);
-            else
-               stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]);
-            f = 0.0;
-         }
-         break;
-
-      case 0x0A: // callsubr
-         if (!has_subrs) {
-            if (info->fdselect.size)
-               subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);
-            has_subrs = 1;
-         }
-         // fallthrough
-      case 0x1D: // callgsubr
-         if (sp < 1) return STBTT__CSERR("call(g|)subr stack");
-         v = (int) s[--sp];
-         if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit");
-         subr_stack[subr_stack_height++] = b;
-         b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v);
-         if (b.size == 0) return STBTT__CSERR("subr not found");
-         b.cursor = 0;
-         clear_stack = 0;
-         break;
-
-      case 0x0B: // return
-         if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr");
-         b = subr_stack[--subr_stack_height];
-         clear_stack = 0;
-         break;
-
-      case 0x0E: // endchar
-         stbtt__csctx_close_shape(c);
-         return 1;
-
-      case 0x0C: { // two-byte escape
-         float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6;
-         float dx, dy;
-         int b1 = stbtt__buf_get8(&b);
-         switch (b1) {
-         // @TODO These "flex" implementations ignore the flex-depth and resolution,
-         // and always draw beziers.
-         case 0x22: // hflex
-            if (sp < 7) return STBTT__CSERR("hflex stack");
-            dx1 = s[0];
-            dx2 = s[1];
-            dy2 = s[2];
-            dx3 = s[3];
-            dx4 = s[4];
-            dx5 = s[5];
-            dx6 = s[6];
-            stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0);
-            stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0);
-            break;
-
-         case 0x23: // flex
-            if (sp < 13) return STBTT__CSERR("flex stack");
-            dx1 = s[0];
-            dy1 = s[1];
-            dx2 = s[2];
-            dy2 = s[3];
-            dx3 = s[4];
-            dy3 = s[5];
-            dx4 = s[6];
-            dy4 = s[7];
-            dx5 = s[8];
-            dy5 = s[9];
-            dx6 = s[10];
-            dy6 = s[11];
-            //fd is s[12]
-            stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
-            stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
-            break;
-
-         case 0x24: // hflex1
-            if (sp < 9) return STBTT__CSERR("hflex1 stack");
-            dx1 = s[0];
-            dy1 = s[1];
-            dx2 = s[2];
-            dy2 = s[3];
-            dx3 = s[4];
-            dx4 = s[5];
-            dx5 = s[6];
-            dy5 = s[7];
-            dx6 = s[8];
-            stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0);
-            stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5));
-            break;
-
-         case 0x25: // flex1
-            if (sp < 11) return STBTT__CSERR("flex1 stack");
-            dx1 = s[0];
-            dy1 = s[1];
-            dx2 = s[2];
-            dy2 = s[3];
-            dx3 = s[4];
-            dy3 = s[5];
-            dx4 = s[6];
-            dy4 = s[7];
-            dx5 = s[8];
-            dy5 = s[9];
-            dx6 = dy6 = s[10];
-            dx = dx1+dx2+dx3+dx4+dx5;
-            dy = dy1+dy2+dy3+dy4+dy5;
-            if (STBTT_fabs(dx) > STBTT_fabs(dy))
-               dy6 = -dy;
-            else
-               dx6 = -dx;
-            stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
-            stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
-            break;
-
-         default:
-            return STBTT__CSERR("unimplemented");
-         }
-      } break;
-
-      default:
-         if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254))
-            return STBTT__CSERR("reserved operator");
-
-         // push immediate
-         if (b0 == 255) {
-            f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000;
-         } else {
-            stbtt__buf_skip(&b, -1);
-            f = (float)(stbtt_int16)stbtt__cff_int(&b);
-         }
-         if (sp >= 48) return STBTT__CSERR("push stack overflow");
-         s[sp++] = f;
-         clear_stack = 0;
-         break;
-      }
-      if (clear_stack) sp = 0;
-   }
-   return STBTT__CSERR("no endchar");
-
-#undef STBTT__CSERR
-}
-
-static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
-{
-   // runs the charstring twice, once to count and once to output (to avoid realloc)
-   stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1);
-   stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0);
-   if (stbtt__run_charstring(info, glyph_index, &count_ctx)) {
-      *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata);
-      output_ctx.pvertices = *pvertices;
-      if (stbtt__run_charstring(info, glyph_index, &output_ctx)) {
-         STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices);
-         return output_ctx.num_vertices;
-      }
-   }
-   *pvertices = NULL;
-   return 0;
-}
-
-static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
-{
-   stbtt__csctx c = STBTT__CSCTX_INIT(1);
-   int r = stbtt__run_charstring(info, glyph_index, &c);
-   if (x0)  *x0 = r ? c.min_x : 0;
-   if (y0)  *y0 = r ? c.min_y : 0;
-   if (x1)  *x1 = r ? c.max_x : 0;
-   if (y1)  *y1 = r ? c.max_y : 0;
-   return r ? c.num_vertices : 0;
-}
-
-STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
-{
-   if (!info->cff.size)
-      return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices);
-   else
-      return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices);
-}
-
-STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing)
-{
-   stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34);
-   if (glyph_index < numOfLongHorMetrics) {
-      if (advanceWidth)     *advanceWidth    = ttSHORT(info->data + info->hmtx + 4*glyph_index);
-      if (leftSideBearing)  *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
-   } else {
-      if (advanceWidth)     *advanceWidth    = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
-      if (leftSideBearing)  *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
-   }
-}
-
-static int  stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
-{
-   stbtt_uint8 *data = info->data + info->kern;
-   stbtt_uint32 needle, straw;
-   int l, r, m;
-
-   // we only look at the first table. it must be 'horizontal' and format 0.
-   if (!info->kern)
-      return 0;
-   if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
-      return 0;
-   if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
-      return 0;
-
-   l = 0;
-   r = ttUSHORT(data+10) - 1;
-   needle = glyph1 << 16 | glyph2;
-   while (l <= r) {
-      m = (l + r) >> 1;
-      straw = ttULONG(data+18+(m*6)); // note: unaligned read
-      if (needle < straw)
-         r = m - 1;
-      else if (needle > straw)
-         l = m + 1;
-      else
-         return ttSHORT(data+22+(m*6));
-   }
-   return 0;
-}
-
-static stbtt_int32  stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)
-{
-    stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
-    switch(coverageFormat) {
-        case 1: {
-            stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
-
-            // Binary search.
-            stbtt_int32 l=0, r=glyphCount-1, m;
-            int straw, needle=glyph;
-            while (l <= r) {
-                stbtt_uint8 *glyphArray = coverageTable + 4;
-                stbtt_uint16 glyphID;
-                m = (l + r) >> 1;
-                glyphID = ttUSHORT(glyphArray + 2 * m);
-                straw = glyphID;
-                if (needle < straw)
-                    r = m - 1;
-                else if (needle > straw)
-                    l = m + 1;
-                else {
-                     return m;
-                }
-            }
-        } break;
-
-        case 2: {
-            stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
-            stbtt_uint8 *rangeArray = coverageTable + 4;
-
-            // Binary search.
-            stbtt_int32 l=0, r=rangeCount-1, m;
-            int strawStart, strawEnd, needle=glyph;
-            while (l <= r) {
-                stbtt_uint8 *rangeRecord;
-                m = (l + r) >> 1;
-                rangeRecord = rangeArray + 6 * m;
-                strawStart = ttUSHORT(rangeRecord);
-                strawEnd = ttUSHORT(rangeRecord + 2);
-                if (needle < strawStart)
-                    r = m - 1;
-                else if (needle > strawEnd)
-                    l = m + 1;
-                else {
-                    stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
-                    return startCoverageIndex + glyph - strawStart;
-                }
-            }
-        } break;
-
-        default: {
-            // There are no other cases.
-            STBTT_assert(0);
-        } break;
-    }
-
-    return -1;
-}
-
-static stbtt_int32  stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
-{
-    stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
-    switch(classDefFormat)
-    {
-        case 1: {
-            stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
-            stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4);
-            stbtt_uint8 *classDef1ValueArray = classDefTable + 6;
-
-            if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
-                return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
-
-            classDefTable = classDef1ValueArray + 2 * glyphCount;
-        } break;
-
-        case 2: {
-            stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
-            stbtt_uint8 *classRangeRecords = classDefTable + 4;
-
-            // Binary search.
-            stbtt_int32 l=0, r=classRangeCount-1, m;
-            int strawStart, strawEnd, needle=glyph;
-            while (l <= r) {
-                stbtt_uint8 *classRangeRecord;
-                m = (l + r) >> 1;
-                classRangeRecord = classRangeRecords + 6 * m;
-                strawStart = ttUSHORT(classRangeRecord);
-                strawEnd = ttUSHORT(classRangeRecord + 2);
-                if (needle < strawStart)
-                    r = m - 1;
-                else if (needle > strawEnd)
-                    l = m + 1;
-                else
-                    return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
-            }
-
-            classDefTable = classRangeRecords + 6 * classRangeCount;
-        } break;
-
-        default: {
-            // There are no other cases.
-            STBTT_assert(0);
-        } break;
-    }
-
-    return -1;
-}
-
-// Define to STBTT_assert(x) if you want to break on unimplemented formats.
-#define STBTT_GPOS_TODO_assert(x)
-
-static stbtt_int32  stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
-{
-    stbtt_uint16 lookupListOffset;
-    stbtt_uint8 *lookupList;
-    stbtt_uint16 lookupCount;
-    stbtt_uint8 *data;
-    stbtt_int32 i;
-
-    if (!info->gpos) return 0;
-
-    data = info->data + info->gpos;
-
-    if (ttUSHORT(data+0) != 1) return 0; // Major version 1
-    if (ttUSHORT(data+2) != 0) return 0; // Minor version 0
-
-    lookupListOffset = ttUSHORT(data+8);
-    lookupList = data + lookupListOffset;
-    lookupCount = ttUSHORT(lookupList);
-
-    for (i=0; i<lookupCount; ++i) {
-        stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
-        stbtt_uint8 *lookupTable = lookupList + lookupOffset;
-
-        stbtt_uint16 lookupType = ttUSHORT(lookupTable);
-        stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
-        stbtt_uint8 *subTableOffsets = lookupTable + 6;
-        switch(lookupType) {
-            case 2: { // Pair Adjustment Positioning Subtable
-                stbtt_int32 sti;
-                for (sti=0; sti<subTableCount; sti++) {
-                    stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
-                    stbtt_uint8 *table = lookupTable + subtableOffset;
-                    stbtt_uint16 posFormat = ttUSHORT(table);
-                    stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
-                    stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
-                    if (coverageIndex == -1) continue;
-
-                    switch (posFormat) {
-                        case 1: {
-                            stbtt_int32 l, r, m;
-                            int straw, needle;
-                            stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
-                            stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
-                            stbtt_int32 valueRecordPairSizeInBytes = 2;
-                            stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
-                            stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
-                            stbtt_uint8 *pairValueTable = table + pairPosOffset;
-                            stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
-                            stbtt_uint8 *pairValueArray = pairValueTable + 2;
-                            // TODO: Support more formats.
-                            STBTT_GPOS_TODO_assert(valueFormat1 == 4);
-                            if (valueFormat1 != 4) return 0;
-                            STBTT_GPOS_TODO_assert(valueFormat2 == 0);
-                            if (valueFormat2 != 0) return 0;
-
-                            STBTT_assert(coverageIndex < pairSetCount);
-
-                            needle=glyph2;
-                            r=pairValueCount-1;
-                            l=0;
-
-                            // Binary search.
-                            while (l <= r) {
-                                stbtt_uint16 secondGlyph;
-                                stbtt_uint8 *pairValue;
-                                m = (l + r) >> 1;
-                                pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
-                                secondGlyph = ttUSHORT(pairValue);
-                                straw = secondGlyph;
-                                if (needle < straw)
-                                    r = m - 1;
-                                else if (needle > straw)
-                                    l = m + 1;
-                                else {
-                                    stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
-                                    return xAdvance;
-                                }
-                            }
-                        } break;
-
-                        case 2: {
-                            stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
-                            stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
-
-                            stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
-                            stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
-                            int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
-                            int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);
-
-                            stbtt_uint16 class1Count = ttUSHORT(table + 12);
-                            stbtt_uint16 class2Count = ttUSHORT(table + 14);
-                            STBTT_assert(glyph1class < class1Count);
-                            STBTT_assert(glyph2class < class2Count);
-
-                            // TODO: Support more formats.
-                            STBTT_GPOS_TODO_assert(valueFormat1 == 4);
-                            if (valueFormat1 != 4) return 0;
-                            STBTT_GPOS_TODO_assert(valueFormat2 == 0);
-                            if (valueFormat2 != 0) return 0;
-
-                            if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) {
-                                stbtt_uint8 *class1Records = table + 16;
-                                stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count);
-                                stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class);
-                                return xAdvance;
-                            }
-                        } break;
-
-                        default: {
-                            // There are no other cases.
-                            STBTT_assert(0);
-                            break;
-                        };
-                    }
-                }
-                break;
-            };
-
-            default:
-                // TODO: Implement other stuff.
-                break;
-        }
-    }
-
-    return 0;
-}
-
-STBTT_DEF int  stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2)
-{
-   int xAdvance = 0;
-
-   if (info->gpos)
-      xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);
-
-   if (info->kern)
-      xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);
-
-   return xAdvance;
-}
-
-STBTT_DEF int  stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2)
-{
-   if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs
-      return 0;
-   return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2));
-}
-
-STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing)
-{
-   stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing);
-}
-
-STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap)
-{
-   if (ascent ) *ascent  = ttSHORT(info->data+info->hhea + 4);
-   if (descent) *descent = ttSHORT(info->data+info->hhea + 6);
-   if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8);
-}
-
-STBTT_DEF int  stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap)
-{
-   int tab = stbtt__find_table(info->data, info->fontstart, "OS/2");
-   if (!tab)
-      return 0;
-   if (typoAscent ) *typoAscent  = ttSHORT(info->data+tab + 68);
-   if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70);
-   if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72);
-   return 1;
-}
-
-STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1)
-{
-   *x0 = ttSHORT(info->data + info->head + 36);
-   *y0 = ttSHORT(info->data + info->head + 38);
-   *x1 = ttSHORT(info->data + info->head + 40);
-   *y1 = ttSHORT(info->data + info->head + 42);
-}
-
-STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height)
-{
-   int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6);
-   return (float) height / fheight;
-}
-
-STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels)
-{
-   int unitsPerEm = ttUSHORT(info->data + info->head + 18);
-   return pixels / unitsPerEm;
-}
-
-STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
-{
-   STBTT_free(v, info->userdata);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// antialiasing software rasterizer
-//
-
-STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
-{
-   int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning
-   if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
-      // e.g. space character
-      if (ix0) *ix0 = 0;
-      if (iy0) *iy0 = 0;
-      if (ix1) *ix1 = 0;
-      if (iy1) *iy1 = 0;
-   } else {
-      // move to integral bboxes (treating pixels as little squares, what pixels get touched)?
-      if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x);
-      if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y);
-      if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x);
-      if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y);
-   }
-}
-
-STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
-{
-   stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);
-}
-
-STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
-{
-   stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1);
-}
-
-STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
-{
-   stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-//  Rasterizer
-
-typedef struct stbtt__hheap_chunk
-{
-   struct stbtt__hheap_chunk *next;
-} stbtt__hheap_chunk;
-
-typedef struct stbtt__hheap
-{
-   struct stbtt__hheap_chunk *head;
-   void   *first_free;
-   int    num_remaining_in_head_chunk;
-} stbtt__hheap;
-
-static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata)
-{
-   if (hh->first_free) {
-      void *p = hh->first_free;
-      hh->first_free = * (void **) p;
-      return p;
-   } else {
-      if (hh->num_remaining_in_head_chunk == 0) {
-         int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
-         stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata);
-         if (c == NULL)
-            return NULL;
-         c->next = hh->head;
-         hh->head = c;
-         hh->num_remaining_in_head_chunk = count;
-      }
-      --hh->num_remaining_in_head_chunk;
-      return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk;
-   }
-}
-
-static void stbtt__hheap_free(stbtt__hheap *hh, void *p)
-{
-   *(void **) p = hh->first_free;
-   hh->first_free = p;
-}
-
-static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata)
-{
-   stbtt__hheap_chunk *c = hh->head;
-   while (c) {
-      stbtt__hheap_chunk *n = c->next;
-      STBTT_free(c, userdata);
-      c = n;
-   }
-}
-
-typedef struct stbtt__edge {
-   float x0,y0, x1,y1;
-   int invert;
-} stbtt__edge;
-
-
-typedef struct stbtt__active_edge
-{
-   struct stbtt__active_edge *next;
-   #if STBTT_RASTERIZER_VERSION==1
-   int x,dx;
-   float ey;
-   int direction;
-   #elif STBTT_RASTERIZER_VERSION==2
-   float fx,fdx,fdy;
-   float direction;
-   float sy;
-   float ey;
-   #else
-   #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
-   #endif
-} stbtt__active_edge;
-
-#if STBTT_RASTERIZER_VERSION == 1
-#define STBTT_FIXSHIFT   10
-#define STBTT_FIX        (1 << STBTT_FIXSHIFT)
-#define STBTT_FIXMASK    (STBTT_FIX-1)
-
-static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
-{
-   stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
-   float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
-   STBTT_assert(z != NULL);
-   if (!z) return z;
-
-   // round dx down to avoid overshooting
-   if (dxdy < 0)
-      z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy);
-   else
-      z->dx = STBTT_ifloor(STBTT_FIX * dxdy);
-
-   z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount
-   z->x -= off_x * STBTT_FIX;
-
-   z->ey = e->y1;
-   z->next = 0;
-   z->direction = e->invert ? 1 : -1;
-   return z;
-}
-#elif STBTT_RASTERIZER_VERSION == 2
-static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
-{
-   stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
-   float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
-   STBTT_assert(z != NULL);
-   //STBTT_assert(e->y0 <= start_point);
-   if (!z) return z;
-   z->fdx = dxdy;
-   z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f;
-   z->fx = e->x0 + dxdy * (start_point - e->y0);
-   z->fx -= off_x;
-   z->direction = e->invert ? 1.0f : -1.0f;
-   z->sy = e->y0;
-   z->ey = e->y1;
-   z->next = 0;
-   return z;
-}
-#else
-#error "Unrecognized value of STBTT_RASTERIZER_VERSION"
-#endif
-
-#if STBTT_RASTERIZER_VERSION == 1
-// note: this routine clips fills that extend off the edges... ideally this
-// wouldn't happen, but it could happen if the truetype glyph bounding boxes
-// are wrong, or if the user supplies a too-small bitmap
-static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight)
-{
-   // non-zero winding fill
-   int x0=0, w=0;
-
-   while (e) {
-      if (w == 0) {
-         // if we're currently at zero, we need to record the edge start point
-         x0 = e->x; w += e->direction;
-      } else {
-         int x1 = e->x; w += e->direction;
-         // if we went to zero, we need to draw
-         if (w == 0) {
-            int i = x0 >> STBTT_FIXSHIFT;
-            int j = x1 >> STBTT_FIXSHIFT;
-
-            if (i < len && j >= 0) {
-               if (i == j) {
-                  // x0,x1 are the same pixel, so compute combined coverage
-                  scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT);
-               } else {
-                  if (i >= 0) // add antialiasing for x0
-                     scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT);
-                  else
-                     i = -1; // clip
-
-                  if (j < len) // add antialiasing for x1
-                     scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT);
-                  else
-                     j = len; // clip
-
-                  for (++i; i < j; ++i) // fill pixels between x0 and x1
-                     scanline[i] = scanline[i] + (stbtt_uint8) max_weight;
-               }
-            }
-         }
-      }
-
-      e = e->next;
-   }
-}
-
-static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
-{
-   stbtt__hheap hh = { 0, 0, 0 };
-   stbtt__active_edge *active = NULL;
-   int y,j=0;
-   int max_weight = (255 / vsubsample);  // weight per vertical scanline
-   int s; // vertical subsample index
-   unsigned char scanline_data[512], *scanline;
-
-   if (result->w > 512)
-      scanline = (unsigned char *) STBTT_malloc(result->w, userdata);
-   else
-      scanline = scanline_data;
-
-   y = off_y * vsubsample;
-   e[n].y0 = (off_y + result->h) * (float) vsubsample + 1;
-
-   while (j < result->h) {
-      STBTT_memset(scanline, 0, result->w);
-      for (s=0; s < vsubsample; ++s) {
-         // find center of pixel for this scanline
-         float scan_y = y + 0.5f;
-         stbtt__active_edge **step = &active;
-
-         // update all active edges;
-         // remove all active edges that terminate before the center of this scanline
-         while (*step) {
-            stbtt__active_edge * z = *step;
-            if (z->ey <= scan_y) {
-               *step = z->next; // delete from list
-               STBTT_assert(z->direction);
-               z->direction = 0;
-               stbtt__hheap_free(&hh, z);
-            } else {
-               z->x += z->dx; // advance to position for current scanline
-               step = &((*step)->next); // advance through list
-            }
-         }
-
-         // resort the list if needed
-         for(;;) {
-            int changed=0;
-            step = &active;
-            while (*step && (*step)->next) {
-               if ((*step)->x > (*step)->next->x) {
-                  stbtt__active_edge *t = *step;
-                  stbtt__active_edge *q = t->next;
-
-                  t->next = q->next;
-                  q->next = t;
-                  *step = q;
-                  changed = 1;
-               }
-               step = &(*step)->next;
-            }
-            if (!changed) break;
-         }
-
-         // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline
-         while (e->y0 <= scan_y) {
-            if (e->y1 > scan_y) {
-               stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata);
-               if (z != NULL) {
-                  // find insertion point
-                  if (active == NULL)
-                     active = z;
-                  else if (z->x < active->x) {
-                     // insert at front
-                     z->next = active;
-                     active = z;
-                  } else {
-                     // find thing to insert AFTER
-                     stbtt__active_edge *p = active;
-                     while (p->next && p->next->x < z->x)
-                        p = p->next;
-                     // at this point, p->next->x is NOT < z->x
-                     z->next = p->next;
-                     p->next = z;
-                  }
-               }
-            }
-            ++e;
-         }
-
-         // now process all active edges in XOR fashion
-         if (active)
-            stbtt__fill_active_edges(scanline, result->w, active, max_weight);
-
-         ++y;
-      }
-      STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w);
-      ++j;
-   }
-
-   stbtt__hheap_cleanup(&hh, userdata);
-
-   if (scanline != scanline_data)
-      STBTT_free(scanline, userdata);
-}
-
-#elif STBTT_RASTERIZER_VERSION == 2
-
-// the edge passed in here does not cross the vertical line at x or the vertical line at x+1
-// (i.e. it has already been clipped to those)
-static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1)
-{
-   if (y0 == y1) return;
-   STBTT_assert(y0 < y1);
-   STBTT_assert(e->sy <= e->ey);
-   if (y0 > e->ey) return;
-   if (y1 < e->sy) return;
-   if (y0 < e->sy) {
-      x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
-      y0 = e->sy;
-   }
-   if (y1 > e->ey) {
-      x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
-      y1 = e->ey;
-   }
-
-   if (x0 == x)
-      STBTT_assert(x1 <= x+1);
-   else if (x0 == x+1)
-      STBTT_assert(x1 >= x);
-   else if (x0 <= x)
-      STBTT_assert(x1 <= x);
-   else if (x0 >= x+1)
-      STBTT_assert(x1 >= x+1);
-   else
-      STBTT_assert(x1 >= x && x1 <= x+1);
-
-   if (x0 <= x && x1 <= x)
-      scanline[x] += e->direction * (y1-y0);
-   else if (x0 >= x+1 && x1 >= x+1)
-      ;
-   else {
-      STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
-      scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position
-   }
-}
-
-static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top)
-{
-   float y_bottom = y_top+1;
-
-   while (e) {
-      // brute force every pixel
-
-      // compute intersection points with top & bottom
-      STBTT_assert(e->ey >= y_top);
-
-      if (e->fdx == 0) {
-         float x0 = e->fx;
-         if (x0 < len) {
-            if (x0 >= 0) {
-               stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);
-               stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);
-            } else {
-               stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
-            }
-         }
-      } else {
-         float x0 = e->fx;
-         float dx = e->fdx;
-         float xb = x0 + dx;
-         float x_top, x_bottom;
-         float sy0,sy1;
-         float dy = e->fdy;
-         STBTT_assert(e->sy <= y_bottom && e->ey >= y_top);
-
-         // compute endpoints of line segment clipped to this scanline (if the
-         // line segment starts on this scanline. x0 is the intersection of the
-         // line with y_top, but that may be off the line segment.
-         if (e->sy > y_top) {
-            x_top = x0 + dx * (e->sy - y_top);
-            sy0 = e->sy;
-         } else {
-            x_top = x0;
-            sy0 = y_top;
-         }
-         if (e->ey < y_bottom) {
-            x_bottom = x0 + dx * (e->ey - y_top);
-            sy1 = e->ey;
-         } else {
-            x_bottom = xb;
-            sy1 = y_bottom;
-         }
-
-         if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) {
-            // from here on, we don't have to range check x values
-
-            if ((int) x_top == (int) x_bottom) {
-               float height;
-               // simple case, only spans one pixel
-               int x = (int) x_top;
-               height = sy1 - sy0;
-               STBTT_assert(x >= 0 && x < len);
-               scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2)  * height;
-               scanline_fill[x] += e->direction * height; // everything right of this pixel is filled
-            } else {
-               int x,x1,x2;
-               float y_crossing, step, sign, area;
-               // covers 2+ pixels
-               if (x_top > x_bottom) {
-                  // flip scanline vertically; signed area is the same
-                  float t;
-                  sy0 = y_bottom - (sy0 - y_top);
-                  sy1 = y_bottom - (sy1 - y_top);
-                  t = sy0, sy0 = sy1, sy1 = t;
-                  t = x_bottom, x_bottom = x_top, x_top = t;
-                  dx = -dx;
-                  dy = -dy;
-                  t = x0, x0 = xb, xb = t;
-               }
-
-               x1 = (int) x_top;
-               x2 = (int) x_bottom;
-               // compute intersection with y axis at x1+1
-               y_crossing = (x1+1 - x0) * dy + y_top;
-
-               sign = e->direction;
-               // area of the rectangle covered from y0..y_crossing
-               area = sign * (y_crossing-sy0);
-               // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing)
-               scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2);
-
-               step = sign * dy;
-               for (x = x1+1; x < x2; ++x) {
-                  scanline[x] += area + step/2;
-                  area += step;
-               }
-               y_crossing += dy * (x2 - (x1+1));
-
-               STBTT_assert(STBTT_fabs(area) <= 1.01f);
-
-               scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing);
-
-               scanline_fill[x2] += sign * (sy1-sy0);
-            }
-         } else {
-            // if edge goes outside of box we're drawing, we require
-            // clipping logic. since this does not match the intended use
-            // of this library, we use a different, very slow brute
-            // force implementation
-            int x;
-            for (x=0; x < len; ++x) {
-               // cases:
-               //
-               // there can be up to two intersections with the pixel. any intersection
-               // with left or right edges can be handled by splitting into two (or three)
-               // regions. intersections with top & bottom do not necessitate case-wise logic.
-               //
-               // the old way of doing this found the intersections with the left & right edges,
-               // then used some simple logic to produce up to three segments in sorted order
-               // from top-to-bottom. however, this had a problem: if an x edge was epsilon
-               // across the x border, then the corresponding y position might not be distinct
-               // from the other y segment, and it might ignored as an empty segment. to avoid
-               // that, we need to explicitly produce segments based on x positions.
-
-               // rename variables to clearly-defined pairs
-               float y0 = y_top;
-               float x1 = (float) (x);
-               float x2 = (float) (x+1);
-               float x3 = xb;
-               float y3 = y_bottom;
-
-               // x = e->x + e->dx * (y-y_top)
-               // (y-y_top) = (x - e->x) / e->dx
-               // y = (x - e->x) / e->dx + y_top
-               float y1 = (x - x0) / dx + y_top;
-               float y2 = (x+1 - x0) / dx + y_top;
-
-               if (x0 < x1 && x3 > x2) {         // three segments descending down-right
-                  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
-                  stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2);
-                  stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
-               } else if (x3 < x1 && x0 > x2) {  // three segments descending down-left
-                  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
-                  stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1);
-                  stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
-               } else if (x0 < x1 && x3 > x1) {  // two segments across x, down-right
-                  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
-                  stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
-               } else if (x3 < x1 && x0 > x1) {  // two segments across x, down-left
-                  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
-                  stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
-               } else if (x0 < x2 && x3 > x2) {  // two segments across x+1, down-right
-                  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
-                  stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
-               } else if (x3 < x2 && x0 > x2) {  // two segments across x+1, down-left
-                  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
-                  stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
-               } else {  // one segment
-                  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3);
-               }
-            }
-         }
-      }
-      e = e->next;
-   }
-}
-
-// directly AA rasterize edges w/o supersampling
-static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
-{
-   stbtt__hheap hh = { 0, 0, 0 };
-   stbtt__active_edge *active = NULL;
-   int y,j=0, i;
-   float scanline_data[129], *scanline, *scanline2;
-
-   STBTT__NOTUSED(vsubsample);
-
-   if (result->w > 64)
-      scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata);
-   else
-      scanline = scanline_data;
-
-   scanline2 = scanline + result->w;
-
-   y = off_y;
-   e[n].y0 = (float) (off_y + result->h) + 1;
-
-   while (j < result->h) {
-      // find center of pixel for this scanline
-      float scan_y_top    = y + 0.0f;
-      float scan_y_bottom = y + 1.0f;
-      stbtt__active_edge **step = &active;
-
-      STBTT_memset(scanline , 0, result->w*sizeof(scanline[0]));
-      STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0]));
-
-      // update all active edges;
-      // remove all active edges that terminate before the top of this scanline
-      while (*step) {
-         stbtt__active_edge * z = *step;
-         if (z->ey <= scan_y_top) {
-            *step = z->next; // delete from list
-            STBTT_assert(z->direction);
-            z->direction = 0;
-            stbtt__hheap_free(&hh, z);
-         } else {
-            step = &((*step)->next); // advance through list
-         }
-      }
-
-      // insert all edges that start before the bottom of this scanline
-      while (e->y0 <= scan_y_bottom) {
-         if (e->y0 != e->y1) {
-            stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
-            if (z != NULL) {
-               STBTT_assert(z->ey >= scan_y_top);
-               // insert at front
-               z->next = active;
-               active = z;
-            }
-         }
-         ++e;
-      }
-
-      // now process all active edges
-      if (active)
-         stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);
-
-      {
-         float sum = 0;
-         for (i=0; i < result->w; ++i) {
-            float k;
-            int m;
-            sum += scanline2[i];
-            k = scanline[i] + sum;
-            k = (float) STBTT_fabs(k)*255 + 0.5f;
-            m = (int) k;
-            if (m > 255) m = 255;
-            result->pixels[j*result->stride + i] = (unsigned char) m;
-         }
-      }
-      // advance all the edges
-      step = &active;
-      while (*step) {
-         stbtt__active_edge *z = *step;
-         z->fx += z->fdx; // advance to position for current scanline
-         step = &((*step)->next); // advance through list
-      }
-
-      ++y;
-      ++j;
-   }
-
-   stbtt__hheap_cleanup(&hh, userdata);
-
-   if (scanline != scanline_data)
-      STBTT_free(scanline, userdata);
-}
-#else
-#error "Unrecognized value of STBTT_RASTERIZER_VERSION"
-#endif
-
-#define STBTT__COMPARE(a,b)  ((a)->y0 < (b)->y0)
-
-static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n)
-{
-   int i,j;
-   for (i=1; i < n; ++i) {
-      stbtt__edge t = p[i], *a = &t;
-      j = i;
-      while (j > 0) {
-         stbtt__edge *b = &p[j-1];
-         int c = STBTT__COMPARE(a,b);
-         if (!c) break;
-         p[j] = p[j-1];
-         --j;
-      }
-      if (i != j)
-         p[j] = t;
-   }
-}
-
-static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n)
-{
-   /* threshhold for transitioning to insertion sort */
-   while (n > 12) {
-      stbtt__edge t;
-      int c01,c12,c,m,i,j;
-
-      /* compute median of three */
-      m = n >> 1;
-      c01 = STBTT__COMPARE(&p[0],&p[m]);
-      c12 = STBTT__COMPARE(&p[m],&p[n-1]);
-      /* if 0 >= mid >= end, or 0 < mid < end, then use mid */
-      if (c01 != c12) {
-         /* otherwise, we'll need to swap something else to middle */
-         int z;
-         c = STBTT__COMPARE(&p[0],&p[n-1]);
-         /* 0>mid && mid<n:  0>n => n; 0<n => 0 */
-         /* 0<mid && mid>n:  0>n => 0; 0<n => n */
-         z = (c == c12) ? 0 : n-1;
-         t = p[z];
-         p[z] = p[m];
-         p[m] = t;
-      }
-      /* now p[m] is the median-of-three */
-      /* swap it to the beginning so it won't move around */
-      t = p[0];
-      p[0] = p[m];
-      p[m] = t;
-
-      /* partition loop */
-      i=1;
-      j=n-1;
-      for(;;) {
-         /* handling of equality is crucial here */
-         /* for sentinels & efficiency with duplicates */
-         for (;;++i) {
-            if (!STBTT__COMPARE(&p[i], &p[0])) break;
-         }
-         for (;;--j) {
-            if (!STBTT__COMPARE(&p[0], &p[j])) break;
-         }
-         /* make sure we haven't crossed */
-         if (i >= j) break;
-         t = p[i];
-         p[i] = p[j];
-         p[j] = t;
-
-         ++i;
-         --j;
-      }
-      /* recurse on smaller side, iterate on larger */
-      if (j < (n-i)) {
-         stbtt__sort_edges_quicksort(p,j);
-         p = p+i;
-         n = n-i;
-      } else {
-         stbtt__sort_edges_quicksort(p+i, n-i);
-         n = j;
-      }
-   }
-}
-
-static void stbtt__sort_edges(stbtt__edge *p, int n)
-{
-   stbtt__sort_edges_quicksort(p, n);
-   stbtt__sort_edges_ins_sort(p, n);
-}
-
-typedef struct
-{
-   float x,y;
-} stbtt__point;
-
-static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata)
-{
-   float y_scale_inv = invert ? -scale_y : scale_y;
-   stbtt__edge *e;
-   int n,i,j,k,m;
-#if STBTT_RASTERIZER_VERSION == 1
-   int vsubsample = result->h < 8 ? 15 : 5;
-#elif STBTT_RASTERIZER_VERSION == 2
-   int vsubsample = 1;
-#else
-   #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
-#endif
-   // vsubsample should divide 255 evenly; otherwise we won't reach full opacity
-
-   // now we have to blow out the windings into explicit edge lists
-   n = 0;
-   for (i=0; i < windings; ++i)
-      n += wcount[i];
-
-   e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel
-   if (e == 0) return;
-   n = 0;
-
-   m=0;
-   for (i=0; i < windings; ++i) {
-      stbtt__point *p = pts + m;
-      m += wcount[i];
-      j = wcount[i]-1;
-      for (k=0; k < wcount[i]; j=k++) {
-         int a=k,b=j;
-         // skip the edge if horizontal
-         if (p[j].y == p[k].y)
-            continue;
-         // add edge from j to k to the list
-         e[n].invert = 0;
-         if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
-            e[n].invert = 1;
-            a=j,b=k;
-         }
-         e[n].x0 = p[a].x * scale_x + shift_x;
-         e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample;
-         e[n].x1 = p[b].x * scale_x + shift_x;
-         e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample;
-         ++n;
-      }
-   }
-
-   // now sort the edges by their highest point (should snap to integer, and then by x)
-   //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare);
-   stbtt__sort_edges(e, n);
-
-   // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule
-   stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);
-
-   STBTT_free(e, userdata);
-}
-
-static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
-{
-   if (!points) return; // during first pass, it's unallocated
-   points[n].x = x;
-   points[n].y = y;
-}
-
-// tesselate until threshhold p is happy... @TODO warped to compensate for non-linear stretching
-static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n)
-{
-   // midpoint
-   float mx = (x0 + 2*x1 + x2)/4;
-   float my = (y0 + 2*y1 + y2)/4;
-   // versus directly drawn line
-   float dx = (x0+x2)/2 - mx;
-   float dy = (y0+y2)/2 - my;
-   if (n > 16) // 65536 segments on one curve better be enough!
-      return 1;
-   if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA
-      stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
-      stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
-   } else {
-      stbtt__add_point(points, *num_points,x2,y2);
-      *num_points = *num_points+1;
-   }
-   return 1;
-}
-
-static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n)
-{
-   // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough
-   float dx0 = x1-x0;
-   float dy0 = y1-y0;
-   float dx1 = x2-x1;
-   float dy1 = y2-y1;
-   float dx2 = x3-x2;
-   float dy2 = y3-y2;
-   float dx = x3-x0;
-   float dy = y3-y0;
-   float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2));
-   float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy);
-   float flatness_squared = longlen*longlen-shortlen*shortlen;
-
-   if (n > 16) // 65536 segments on one curve better be enough!
-      return;
-
-   if (flatness_squared > objspace_flatness_squared) {
-      float x01 = (x0+x1)/2;
-      float y01 = (y0+y1)/2;
-      float x12 = (x1+x2)/2;
-      float y12 = (y1+y2)/2;
-      float x23 = (x2+x3)/2;
-      float y23 = (y2+y3)/2;
-
-      float xa = (x01+x12)/2;
-      float ya = (y01+y12)/2;
-      float xb = (x12+x23)/2;
-      float yb = (y12+y23)/2;
-
-      float mx = (xa+xb)/2;
-      float my = (ya+yb)/2;
-
-      stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1);
-      stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1);
-   } else {
-      stbtt__add_point(points, *num_points,x3,y3);
-      *num_points = *num_points+1;
-   }
-}
-
-// returns number of contours
-static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata)
-{
-   stbtt__point *points=0;
-   int num_points=0;
-
-   float objspace_flatness_squared = objspace_flatness * objspace_flatness;
-   int i,n=0,start=0, pass;
-
-   // count how many "moves" there are to get the contour count
-   for (i=0; i < num_verts; ++i)
-      if (vertices[i].type == STBTT_vmove)
-         ++n;
-
-   *num_contours = n;
-   if (n == 0) return 0;
-
-   *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata);
-
-   if (*contour_lengths == 0) {
-      *num_contours = 0;
-      return 0;
-   }
-
-   // make two passes through the points so we don't need to realloc
-   for (pass=0; pass < 2; ++pass) {
-      float x=0,y=0;
-      if (pass == 1) {
-         points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata);
-         if (points == NULL) goto error;
-      }
-      num_points = 0;
-      n= -1;
-      for (i=0; i < num_verts; ++i) {
-         switch (vertices[i].type) {
-            case STBTT_vmove:
-               // start the next contour
-               if (n >= 0)
-                  (*contour_lengths)[n] = num_points - start;
-               ++n;
-               start = num_points;
-
-               x = vertices[i].x, y = vertices[i].y;
-               stbtt__add_point(points, num_points++, x,y);
-               break;
-            case STBTT_vline:
-               x = vertices[i].x, y = vertices[i].y;
-               stbtt__add_point(points, num_points++, x, y);
-               break;
-            case STBTT_vcurve:
-               stbtt__tesselate_curve(points, &num_points, x,y,
-                                        vertices[i].cx, vertices[i].cy,
-                                        vertices[i].x,  vertices[i].y,
-                                        objspace_flatness_squared, 0);
-               x = vertices[i].x, y = vertices[i].y;
-               break;
-            case STBTT_vcubic:
-               stbtt__tesselate_cubic(points, &num_points, x,y,
-                                        vertices[i].cx, vertices[i].cy,
-                                        vertices[i].cx1, vertices[i].cy1,
-                                        vertices[i].x,  vertices[i].y,
-                                        objspace_flatness_squared, 0);
-               x = vertices[i].x, y = vertices[i].y;
-               break;
-         }
-      }
-      (*contour_lengths)[n] = num_points - start;
-   }
-
-   return points;
-error:
-   STBTT_free(points, userdata);
-   STBTT_free(*contour_lengths, userdata);
-   *contour_lengths = 0;
-   *num_contours = 0;
-   return NULL;
-}
-
-STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata)
-{
-   float scale            = scale_x > scale_y ? scale_y : scale_x;
-   int winding_count      = 0;
-   int *winding_lengths   = NULL;
-   stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
-   if (windings) {
-      stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);
-      STBTT_free(winding_lengths, userdata);
-      STBTT_free(windings, userdata);
-   }
-}
-
-STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)
-{
-   STBTT_free(bitmap, userdata);
-}
-
-STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff)
-{
-   int ix0,iy0,ix1,iy1;
-   stbtt__bitmap gbm;
-   stbtt_vertex *vertices;
-   int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
-
-   if (scale_x == 0) scale_x = scale_y;
-   if (scale_y == 0) {
-      if (scale_x == 0) {
-         STBTT_free(vertices, info->userdata);
-         return NULL;
-      }
-      scale_y = scale_x;
-   }
-
-   stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1);
-
-   // now we get the size
-   gbm.w = (ix1 - ix0);
-   gbm.h = (iy1 - iy0);
-   gbm.pixels = NULL; // in case we error
-
-   if (width ) *width  = gbm.w;
-   if (height) *height = gbm.h;
-   if (xoff  ) *xoff   = ix0;
-   if (yoff  ) *yoff   = iy0;
-
-   if (gbm.w && gbm.h) {
-      gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);
-      if (gbm.pixels) {
-         gbm.stride = gbm.w;
-
-         stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata);
-      }
-   }
-   STBTT_free(vertices, info->userdata);
-   return gbm.pixels;
-}
-
-STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff)
-{
-   return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff);
-}
-
-STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph)
-{
-   int ix0,iy0;
-   stbtt_vertex *vertices;
-   int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
-   stbtt__bitmap gbm;
-
-   stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0);
-   gbm.pixels = output;
-   gbm.w = out_w;
-   gbm.h = out_h;
-   gbm.stride = out_stride;
-
-   if (gbm.w && gbm.h)
-      stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata);
-
-   STBTT_free(vertices, info->userdata);
-}
-
-STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph)
-{
-   stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph);
-}
-
-STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
-{
-   return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
-}
-
-STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint)
-{
-   stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint));
-}
-
-STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint)
-{
-   stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint));
-}
-
-STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
-{
-   return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff);
-}
-
-STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint)
-{
-   stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// bitmap baking
-//
-// This is SUPER-CRAPPY packing to keep source code small
-
-static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset,  // font location (use offset=0 for plain .ttf)
-                                float pixel_height,                     // height of font in pixels
-                                unsigned char *pixels, int pw, int ph,  // bitmap to be filled in
-                                int first_char, int num_chars,          // characters to bake
-                                stbtt_bakedchar *chardata)
-{
-   float scale;
-   int x,y,bottom_y, i;
-   stbtt_fontinfo f;
-   f.userdata = NULL;
-   if (!stbtt_InitFont(&f, data, offset))
-      return -1;
-   STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
-   x=y=1;
-   bottom_y = 1;
-
-   scale = stbtt_ScaleForPixelHeight(&f, pixel_height);
-
-   for (i=0; i < num_chars; ++i) {
-      int advance, lsb, x0,y0,x1,y1,gw,gh;
-      int g = stbtt_FindGlyphIndex(&f, first_char + i);
-      stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb);
-      stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1);
-      gw = x1-x0;
-      gh = y1-y0;
-      if (x + gw + 1 >= pw)
-         y = bottom_y, x = 1; // advance to next row
-      if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row
-         return -i;
-      STBTT_assert(x+gw < pw);
-      STBTT_assert(y+gh < ph);
-      stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g);
-      chardata[i].x0 = (stbtt_int16) x;
-      chardata[i].y0 = (stbtt_int16) y;
-      chardata[i].x1 = (stbtt_int16) (x + gw);
-      chardata[i].y1 = (stbtt_int16) (y + gh);
-      chardata[i].xadvance = scale * advance;
-      chardata[i].xoff     = (float) x0;
-      chardata[i].yoff     = (float) y0;
-      x = x + gw + 1;
-      if (y+gh+1 > bottom_y)
-         bottom_y = y+gh+1;
-   }
-   return bottom_y;
-}
-
-STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule)
-{
-   float d3d_bias = opengl_fillrule ? 0 : -0.5f;
-   float ipw = 1.0f / pw, iph = 1.0f / ph;
-   const stbtt_bakedchar *b = chardata + char_index;
-   int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f);
-   int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f);
-
-   q->x0 = round_x + d3d_bias;
-   q->y0 = round_y + d3d_bias;
-   q->x1 = round_x + b->x1 - b->x0 + d3d_bias;
-   q->y1 = round_y + b->y1 - b->y0 + d3d_bias;
-
-   q->s0 = b->x0 * ipw;
-   q->t0 = b->y0 * iph;
-   q->s1 = b->x1 * ipw;
-   q->t1 = b->y1 * iph;
-
-   *xpos += b->xadvance;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// rectangle packing replacement routines if you don't have stb_rect_pack.h
-//
-
-#ifndef STB_RECT_PACK_VERSION
-
-typedef int stbrp_coord;
-
-////////////////////////////////////////////////////////////////////////////////////
-//                                                                                //
-//                                                                                //
-// COMPILER WARNING ?!?!?                                                         //
-//                                                                                //
-//                                                                                //
-// if you get a compile warning due to these symbols being defined more than      //
-// once, move #include "stb_rect_pack.h" before #include "stb_truetype.h"         //
-//                                                                                //
-////////////////////////////////////////////////////////////////////////////////////
-
-typedef struct
-{
-   int width,height;
-   int x,y,bottom_y;
-} stbrp_context;
-
-typedef struct
-{
-   unsigned char x;
-} stbrp_node;
-
-struct stbrp_rect
-{
-   stbrp_coord x,y;
-   int id,w,h,was_packed;
-};
-
-static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes)
-{
-   con->width  = pw;
-   con->height = ph;
-   con->x = 0;
-   con->y = 0;
-   con->bottom_y = 0;
-   STBTT__NOTUSED(nodes);
-   STBTT__NOTUSED(num_nodes);
-}
-
-static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects)
-{
-   int i;
-   for (i=0; i < num_rects; ++i) {
-      if (con->x + rects[i].w > con->width) {
-         con->x = 0;
-         con->y = con->bottom_y;
-      }
-      if (con->y + rects[i].h > con->height)
-         break;
-      rects[i].x = con->x;
-      rects[i].y = con->y;
-      rects[i].was_packed = 1;
-      con->x += rects[i].w;
-      if (con->y + rects[i].h > con->bottom_y)
-         con->bottom_y = con->y + rects[i].h;
-   }
-   for (   ; i < num_rects; ++i)
-      rects[i].was_packed = 0;
-}
-#endif
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// bitmap baking
-//
-// This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If
-// stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy.
-
-STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context)
-{
-   stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context)            ,alloc_context);
-   int            num_nodes = pw - padding;
-   stbrp_node    *nodes   = (stbrp_node    *) STBTT_malloc(sizeof(*nodes  ) * num_nodes,alloc_context);
-
-   if (context == NULL || nodes == NULL) {
-      if (context != NULL) STBTT_free(context, alloc_context);
-      if (nodes   != NULL) STBTT_free(nodes  , alloc_context);
-      return 0;
-   }
-
-   spc->user_allocator_context = alloc_context;
-   spc->width = pw;
-   spc->height = ph;
-   spc->pixels = pixels;
-   spc->pack_info = context;
-   spc->nodes = nodes;
-   spc->padding = padding;
-   spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
-   spc->h_oversample = 1;
-   spc->v_oversample = 1;
-
-   stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
-
-   if (pixels)
-      STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
-
-   return 1;
-}
-
-STBTT_DEF void stbtt_PackEnd  (stbtt_pack_context *spc)
-{
-   STBTT_free(spc->nodes    , spc->user_allocator_context);
-   STBTT_free(spc->pack_info, spc->user_allocator_context);
-}
-
-STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample)
-{
-   STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE);
-   STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE);
-   if (h_oversample <= STBTT_MAX_OVERSAMPLE)
-      spc->h_oversample = h_oversample;
-   if (v_oversample <= STBTT_MAX_OVERSAMPLE)
-      spc->v_oversample = v_oversample;
-}
-
-#define STBTT__OVER_MASK  (STBTT_MAX_OVERSAMPLE-1)
-
-static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
-{
-   unsigned char buffer[STBTT_MAX_OVERSAMPLE];
-   int safe_w = w - kernel_width;
-   int j;
-   STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
-   for (j=0; j < h; ++j) {
-      int i;
-      unsigned int total;
-      STBTT_memset(buffer, 0, kernel_width);
-
-      total = 0;
-
-      // make kernel_width a constant in common cases so compiler can optimize out the divide
-      switch (kernel_width) {
-         case 2:
-            for (i=0; i <= safe_w; ++i) {
-               total += pixels[i] - buffer[i & STBTT__OVER_MASK];
-               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
-               pixels[i] = (unsigned char) (total / 2);
-            }
-            break;
-         case 3:
-            for (i=0; i <= safe_w; ++i) {
-               total += pixels[i] - buffer[i & STBTT__OVER_MASK];
-               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
-               pixels[i] = (unsigned char) (total / 3);
-            }
-            break;
-         case 4:
-            for (i=0; i <= safe_w; ++i) {
-               total += pixels[i] - buffer[i & STBTT__OVER_MASK];
-               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
-               pixels[i] = (unsigned char) (total / 4);
-            }
-            break;
-         case 5:
-            for (i=0; i <= safe_w; ++i) {
-               total += pixels[i] - buffer[i & STBTT__OVER_MASK];
-               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
-               pixels[i] = (unsigned char) (total / 5);
-            }
-            break;
-         default:
-            for (i=0; i <= safe_w; ++i) {
-               total += pixels[i] - buffer[i & STBTT__OVER_MASK];
-               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
-               pixels[i] = (unsigned char) (total / kernel_width);
-            }
-            break;
-      }
-
-      for (; i < w; ++i) {
-         STBTT_assert(pixels[i] == 0);
-         total -= buffer[i & STBTT__OVER_MASK];
-         pixels[i] = (unsigned char) (total / kernel_width);
-      }
-
-      pixels += stride_in_bytes;
-   }
-}
-
-static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
-{
-   unsigned char buffer[STBTT_MAX_OVERSAMPLE];
-   int safe_h = h - kernel_width;
-   int j;
-   STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
-   for (j=0; j < w; ++j) {
-      int i;
-      unsigned int total;
-      STBTT_memset(buffer, 0, kernel_width);
-
-      total = 0;
-
-      // make kernel_width a constant in common cases so compiler can optimize out the divide
-      switch (kernel_width) {
-         case 2:
-            for (i=0; i <= safe_h; ++i) {
-               total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
-               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
-               pixels[i*stride_in_bytes] = (unsigned char) (total / 2);
-            }
-            break;
-         case 3:
-            for (i=0; i <= safe_h; ++i) {
-               total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
-               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
-               pixels[i*stride_in_bytes] = (unsigned char) (total / 3);
-            }
-            break;
-         case 4:
-            for (i=0; i <= safe_h; ++i) {
-               total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
-               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
-               pixels[i*stride_in_bytes] = (unsigned char) (total / 4);
-            }
-            break;
-         case 5:
-            for (i=0; i <= safe_h; ++i) {
-               total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
-               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
-               pixels[i*stride_in_bytes] = (unsigned char) (total / 5);
-            }
-            break;
-         default:
-            for (i=0; i <= safe_h; ++i) {
-               total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
-               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
-               pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);
-            }
-            break;
-      }
-
-      for (; i < h; ++i) {
-         STBTT_assert(pixels[i*stride_in_bytes] == 0);
-         total -= buffer[i & STBTT__OVER_MASK];
-         pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);
-      }
-
-      pixels += 1;
-   }
-}
-
-static float stbtt__oversample_shift(int oversample)
-{
-   if (!oversample)
-      return 0.0f;
-
-   // The prefilter is a box filter of width "oversample",
-   // which shifts phase by (oversample - 1)/2 pixels in
-   // oversampled space. We want to shift in the opposite
-   // direction to counter this.
-   return (float)-(oversample - 1) / (2.0f * (float)oversample);
-}
-
-// rects array must be big enough to accommodate all characters in the given ranges
-STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
-{
-   int i,j,k;
-
-   k=0;
-   for (i=0; i < num_ranges; ++i) {
-      float fh = ranges[i].font_size;
-      float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
-      ranges[i].h_oversample = (unsigned char) spc->h_oversample;
-      ranges[i].v_oversample = (unsigned char) spc->v_oversample;
-      for (j=0; j < ranges[i].num_chars; ++j) {
-         int x0,y0,x1,y1;
-         int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
-         int glyph = stbtt_FindGlyphIndex(info, codepoint);
-         stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
-                                         scale * spc->h_oversample,
-                                         scale * spc->v_oversample,
-                                         0,0,
-                                         &x0,&y0,&x1,&y1);
-         rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
-         rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
-         ++k;
-      }
-   }
-
-   return k;
-}
-
-STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph)
-{
-   stbtt_MakeGlyphBitmapSubpixel(info,
-                                 output,
-                                 out_w - (prefilter_x - 1),
-                                 out_h - (prefilter_y - 1),
-                                 out_stride,
-                                 scale_x,
-                                 scale_y,
-                                 shift_x,
-                                 shift_y,
-                                 glyph);
-
-   if (prefilter_x > 1)
-      stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x);
-
-   if (prefilter_y > 1)
-      stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y);
-
-   *sub_x = stbtt__oversample_shift(prefilter_x);
-   *sub_y = stbtt__oversample_shift(prefilter_y);
-}
-
-// rects array must be big enough to accommodate all characters in the given ranges
-STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
-{
-   int i,j,k, return_value = 1;
-
-   // save current values
-   int old_h_over = spc->h_oversample;
-   int old_v_over = spc->v_oversample;
-
-   k = 0;
-   for (i=0; i < num_ranges; ++i) {
-      float fh = ranges[i].font_size;
-      float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
-      float recip_h,recip_v,sub_x,sub_y;
-      spc->h_oversample = ranges[i].h_oversample;
-      spc->v_oversample = ranges[i].v_oversample;
-      recip_h = 1.0f / spc->h_oversample;
-      recip_v = 1.0f / spc->v_oversample;
-      sub_x = stbtt__oversample_shift(spc->h_oversample);
-      sub_y = stbtt__oversample_shift(spc->v_oversample);
-      for (j=0; j < ranges[i].num_chars; ++j) {
-         stbrp_rect *r = &rects[k];
-         if (r->was_packed) {
-            stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
-            int advance, lsb, x0,y0,x1,y1;
-            int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
-            int glyph = stbtt_FindGlyphIndex(info, codepoint);
-            stbrp_coord pad = (stbrp_coord) spc->padding;
-
-            // pad on left and top
-            r->x += pad;
-            r->y += pad;
-            r->w -= pad;
-            r->h -= pad;
-            stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb);
-            stbtt_GetGlyphBitmapBox(info, glyph,
-                                    scale * spc->h_oversample,
-                                    scale * spc->v_oversample,
-                                    &x0,&y0,&x1,&y1);
-            stbtt_MakeGlyphBitmapSubpixel(info,
-                                          spc->pixels + r->x + r->y*spc->stride_in_bytes,
-                                          r->w - spc->h_oversample+1,
-                                          r->h - spc->v_oversample+1,
-                                          spc->stride_in_bytes,
-                                          scale * spc->h_oversample,
-                                          scale * spc->v_oversample,
-                                          0,0,
-                                          glyph);
-
-            if (spc->h_oversample > 1)
-               stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
-                                  r->w, r->h, spc->stride_in_bytes,
-                                  spc->h_oversample);
-
-            if (spc->v_oversample > 1)
-               stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
-                                  r->w, r->h, spc->stride_in_bytes,
-                                  spc->v_oversample);
-
-            bc->x0       = (stbtt_int16)  r->x;
-            bc->y0       = (stbtt_int16)  r->y;
-            bc->x1       = (stbtt_int16) (r->x + r->w);
-            bc->y1       = (stbtt_int16) (r->y + r->h);
-            bc->xadvance =                scale * advance;
-            bc->xoff     =       (float)  x0 * recip_h + sub_x;
-            bc->yoff     =       (float)  y0 * recip_v + sub_y;
-            bc->xoff2    =                (x0 + r->w) * recip_h + sub_x;
-            bc->yoff2    =                (y0 + r->h) * recip_v + sub_y;
-         } else {
-            return_value = 0; // if any fail, report failure
-         }
-
-         ++k;
-      }
-   }
-
-   // restore original values
-   spc->h_oversample = old_h_over;
-   spc->v_oversample = old_v_over;
-
-   return return_value;
-}
-
-STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects)
-{
-   stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects);
-}
-
-STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
-{
-   stbtt_fontinfo info;
-   int i,j,n, return_value = 1;
-   //stbrp_context *context = (stbrp_context *) spc->pack_info;
-   stbrp_rect    *rects;
-
-   // flag all characters as NOT packed
-   for (i=0; i < num_ranges; ++i)
-      for (j=0; j < ranges[i].num_chars; ++j)
-         ranges[i].chardata_for_range[j].x0 =
-         ranges[i].chardata_for_range[j].y0 =
-         ranges[i].chardata_for_range[j].x1 =
-         ranges[i].chardata_for_range[j].y1 = 0;
-
-   n = 0;
-   for (i=0; i < num_ranges; ++i)
-      n += ranges[i].num_chars;
-
-   rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);
-   if (rects == NULL)
-      return 0;
-
-   info.userdata = spc->user_allocator_context;
-   stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index));
-
-   n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects);
-
-   stbtt_PackFontRangesPackRects(spc, rects, n);
-
-   return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects);
-
-   STBTT_free(rects, spc->user_allocator_context);
-   return return_value;
-}
-
-STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,
-            int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range)
-{
-   stbtt_pack_range range;
-   range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range;
-   range.array_of_unicode_codepoints = NULL;
-   range.num_chars                   = num_chars_in_range;
-   range.chardata_for_range          = chardata_for_range;
-   range.font_size                   = font_size;
-   return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1);
-}
-
-STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer)
-{
-   float ipw = 1.0f / pw, iph = 1.0f / ph;
-   const stbtt_packedchar *b = chardata + char_index;
-
-   if (align_to_integer) {
-      float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f);
-      float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f);
-      q->x0 = x;
-      q->y0 = y;
-      q->x1 = x + b->xoff2 - b->xoff;
-      q->y1 = y + b->yoff2 - b->yoff;
-   } else {
-      q->x0 = *xpos + b->xoff;
-      q->y0 = *ypos + b->yoff;
-      q->x1 = *xpos + b->xoff2;
-      q->y1 = *ypos + b->yoff2;
-   }
-
-   q->s0 = b->x0 * ipw;
-   q->t0 = b->y0 * iph;
-   q->s1 = b->x1 * ipw;
-   q->t1 = b->y1 * iph;
-
-   *xpos += b->xadvance;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// sdf computation
-//
-
-#define STBTT_min(a,b)  ((a) < (b) ? (a) : (b))
-#define STBTT_max(a,b)  ((a) < (b) ? (b) : (a))
-
-static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2])
-{
-   float q0perp = q0[1]*ray[0] - q0[0]*ray[1];
-   float q1perp = q1[1]*ray[0] - q1[0]*ray[1];
-   float q2perp = q2[1]*ray[0] - q2[0]*ray[1];
-   float roperp = orig[1]*ray[0] - orig[0]*ray[1];
-
-   float a = q0perp - 2*q1perp + q2perp;
-   float b = q1perp - q0perp;
-   float c = q0perp - roperp;
-
-   float s0 = 0., s1 = 0.;
-   int num_s = 0;
-
-   if (a != 0.0) {
-      float discr = b*b - a*c;
-      if (discr > 0.0) {
-         float rcpna = -1 / a;
-         float d = (float) STBTT_sqrt(discr);
-         s0 = (b+d) * rcpna;
-         s1 = (b-d) * rcpna;
-         if (s0 >= 0.0 && s0 <= 1.0)
-            num_s = 1;
-         if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) {
-            if (num_s == 0) s0 = s1;
-            ++num_s;
-         }
-      }
-   } else {
-      // 2*b*s + c = 0
-      // s = -c / (2*b)
-      s0 = c / (-2 * b);
-      if (s0 >= 0.0 && s0 <= 1.0)
-         num_s = 1;
-   }
-
-   if (num_s == 0)
-      return 0;
-   else {
-      float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]);
-      float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2;
-
-      float q0d =   q0[0]*rayn_x +   q0[1]*rayn_y;
-      float q1d =   q1[0]*rayn_x +   q1[1]*rayn_y;
-      float q2d =   q2[0]*rayn_x +   q2[1]*rayn_y;
-      float rod = orig[0]*rayn_x + orig[1]*rayn_y;
-
-      float q10d = q1d - q0d;
-      float q20d = q2d - q0d;
-      float q0rd = q0d - rod;
-
-      hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d;
-      hits[0][1] = a*s0+b;
-
-      if (num_s > 1) {
-         hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d;
-         hits[1][1] = a*s1+b;
-         return 2;
-      } else {
-         return 1;
-      }
-   }
-}
-
-static int equal(float *a, float *b)
-{
-   return (a[0] == b[0] && a[1] == b[1]);
-}
-
-static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts)
-{
-   int i;
-   float orig[2], ray[2] = { 1, 0 };
-   float y_frac;
-   int winding = 0;
-
-   orig[0] = x;
-   orig[1] = y;
-
-   // make sure y never passes through a vertex of the shape
-   y_frac = (float) STBTT_fmod(y, 1.0f);
-   if (y_frac < 0.01f)
-      y += 0.01f;
-   else if (y_frac > 0.99f)
-      y -= 0.01f;
-   orig[1] = y;
-
-   // test a ray from (-infinity,y) to (x,y)
-   for (i=0; i < nverts; ++i) {
-      if (verts[i].type == STBTT_vline) {
-         int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y;
-         int x1 = (int) verts[i  ].x, y1 = (int) verts[i  ].y;
-         if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
-            float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
-            if (x_inter < x)
-               winding += (y0 < y1) ? 1 : -1;
-         }
-      }
-      if (verts[i].type == STBTT_vcurve) {
-         int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ;
-         int x1 = (int) verts[i  ].cx, y1 = (int) verts[i  ].cy;
-         int x2 = (int) verts[i  ].x , y2 = (int) verts[i  ].y ;
-         int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2));
-         int by = STBTT_max(y0,STBTT_max(y1,y2));
-         if (y > ay && y < by && x > ax) {
-            float q0[2],q1[2],q2[2];
-            float hits[2][2];
-            q0[0] = (float)x0;
-            q0[1] = (float)y0;
-            q1[0] = (float)x1;
-            q1[1] = (float)y1;
-            q2[0] = (float)x2;
-            q2[1] = (float)y2;
-            if (equal(q0,q1) || equal(q1,q2)) {
-               x0 = (int)verts[i-1].x;
-               y0 = (int)verts[i-1].y;
-               x1 = (int)verts[i  ].x;
-               y1 = (int)verts[i  ].y;
-               if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
-                  float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
-                  if (x_inter < x)
-                     winding += (y0 < y1) ? 1 : -1;
-               }
-            } else {
-               int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits);
-               if (num_hits >= 1)
-                  if (hits[0][0] < 0)
-                     winding += (hits[0][1] < 0 ? -1 : 1);
-               if (num_hits >= 2)
-                  if (hits[1][0] < 0)
-                     winding += (hits[1][1] < 0 ? -1 : 1);
-            }
-         }
-      }
-   }
-   return winding;
-}
-
-static float stbtt__cuberoot( float x )
-{
-   if (x<0)
-      return -(float) STBTT_pow(-x,1.0f/3.0f);
-   else
-      return  (float) STBTT_pow( x,1.0f/3.0f);
-}
-
-// x^3 + c*x^2 + b*x + a = 0
-static int stbtt__solve_cubic(float a, float b, float c, float* r)
-{
-	float s = -a / 3;
-	float p = b - a*a / 3;
-	float q = a * (2*a*a - 9*b) / 27 + c;
-   float p3 = p*p*p;
-	float d = q*q + 4*p3 / 27;
-	if (d >= 0) {
-		float z = (float) STBTT_sqrt(d);
-		float u = (-q + z) / 2;
-		float v = (-q - z) / 2;
-		u = stbtt__cuberoot(u);
-		v = stbtt__cuberoot(v);
-		r[0] = s + u + v;
-		return 1;
-	} else {
-	   float u = (float) STBTT_sqrt(-p/3);
-	   float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative
-	   float m = (float) STBTT_cos(v);
-      float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f;
-	   r[0] = s + u * 2 * m;
-	   r[1] = s - u * (m + n);
-	   r[2] = s - u * (m - n);
-
-      //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f);  // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe?
-      //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f);
-      //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f);
-   	return 3;
-   }
-}
-
-STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
-{
-   float scale_x = scale, scale_y = scale;
-   int ix0,iy0,ix1,iy1;
-   int w,h;
-   unsigned char *data;
-
-   // if one scale is 0, use same scale for both
-   if (scale_x == 0) scale_x = scale_y;
-   if (scale_y == 0) {
-      if (scale_x == 0) return NULL;  // if both scales are 0, return NULL
-      scale_y = scale_x;
-   }
-
-   stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1);
-
-   // if empty, return NULL
-   if (ix0 == ix1 || iy0 == iy1)
-      return NULL;
-
-   ix0 -= padding;
-   iy0 -= padding;
-   ix1 += padding;
-   iy1 += padding;
-
-   w = (ix1 - ix0);
-   h = (iy1 - iy0);
-
-   if (width ) *width  = w;
-   if (height) *height = h;
-   if (xoff  ) *xoff   = ix0;
-   if (yoff  ) *yoff   = iy0;
-
-   // invert for y-downwards bitmaps
-   scale_y = -scale_y;
-
-   {
-      int x,y,i,j;
-      float *precompute;
-      stbtt_vertex *verts;
-      int num_verts = stbtt_GetGlyphShape(info, glyph, &verts);
-      data = (unsigned char *) STBTT_malloc(w * h, info->userdata);
-      precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata);
-
-      for (i=0,j=num_verts-1; i < num_verts; j=i++) {
-         if (verts[i].type == STBTT_vline) {
-            float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
-            float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y;
-            float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0));
-            precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist;
-         } else if (verts[i].type == STBTT_vcurve) {
-            float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y;
-            float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y;
-            float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y;
-            float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
-            float len2 = bx*bx + by*by;
-            if (len2 != 0.0f)
-               precompute[i] = 1.0f / (bx*bx + by*by);
-            else
-               precompute[i] = 0.0f;
-         } else
-            precompute[i] = 0.0f;
-      }
-
-      for (y=iy0; y < iy1; ++y) {
-         for (x=ix0; x < ix1; ++x) {
-            float val;
-            float min_dist = 999999.0f;
-            float sx = (float) x + 0.5f;
-            float sy = (float) y + 0.5f;
-            float x_gspace = (sx / scale_x);
-            float y_gspace = (sy / scale_y);
-
-            int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path
-
-            for (i=0; i < num_verts; ++i) {
-               float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
-
-               // check against every point here rather than inside line/curve primitives -- @TODO: wrong if multiple 'moves' in a row produce a garbage point, and given culling, probably more efficient to do within line/curve
-               float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
-               if (dist2 < min_dist*min_dist)
-                  min_dist = (float) STBTT_sqrt(dist2);
-
-               if (verts[i].type == STBTT_vline) {
-                  float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y;
-
-                  // coarse culling against bbox
-                  //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist &&
-                  //    sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist)
-                  float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
-                  STBTT_assert(i != 0);
-                  if (dist < min_dist) {
-                     // check position along line
-                     // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0)
-                     // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy)
-                     float dx = x1-x0, dy = y1-y0;
-                     float px = x0-sx, py = y0-sy;
-                     // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy
-                     // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve
-                     float t = -(px*dx + py*dy) / (dx*dx + dy*dy);
-                     if (t >= 0.0f && t <= 1.0f)
-                        min_dist = dist;
-                  }
-               } else if (verts[i].type == STBTT_vcurve) {
-                  float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y;
-                  float x1 = verts[i  ].cx*scale_x, y1 = verts[i  ].cy*scale_y;
-                  float box_x0 = STBTT_min(STBTT_min(x0,x1),x2);
-                  float box_y0 = STBTT_min(STBTT_min(y0,y1),y2);
-                  float box_x1 = STBTT_max(STBTT_max(x0,x1),x2);
-                  float box_y1 = STBTT_max(STBTT_max(y0,y1),y2);
-                  // coarse culling against bbox to avoid computing cubic unnecessarily
-                  if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) {
-                     int num=0;
-                     float ax = x1-x0, ay = y1-y0;
-                     float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
-                     float mx = x0 - sx, my = y0 - sy;
-                     float res[3],px,py,t,it;
-                     float a_inv = precompute[i];
-                     if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula
-                        float a = 3*(ax*bx + ay*by);
-                        float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by);
-                        float c = mx*ax+my*ay;
-                        if (a == 0.0) { // if a is 0, it's linear
-                           if (b != 0.0) {
-                              res[num++] = -c/b;
-                           }
-                        } else {
-                           float discriminant = b*b - 4*a*c;
-                           if (discriminant < 0)
-                              num = 0;
-                           else {
-                              float root = (float) STBTT_sqrt(discriminant);
-                              res[0] = (-b - root)/(2*a);
-                              res[1] = (-b + root)/(2*a);
-                              num = 2; // don't bother distinguishing 1-solution case, as code below will still work
-                           }
-                        }
-                     } else {
-                        float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point
-                        float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv;
-                        float d = (mx*ax+my*ay) * a_inv;
-                        num = stbtt__solve_cubic(b, c, d, res);
-                     }
-                     if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) {
-                        t = res[0], it = 1.0f - t;
-                        px = it*it*x0 + 2*t*it*x1 + t*t*x2;
-                        py = it*it*y0 + 2*t*it*y1 + t*t*y2;
-                        dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
-                        if (dist2 < min_dist * min_dist)
-                           min_dist = (float) STBTT_sqrt(dist2);
-                     }
-                     if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) {
-                        t = res[1], it = 1.0f - t;
-                        px = it*it*x0 + 2*t*it*x1 + t*t*x2;
-                        py = it*it*y0 + 2*t*it*y1 + t*t*y2;
-                        dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
-                        if (dist2 < min_dist * min_dist)
-                           min_dist = (float) STBTT_sqrt(dist2);
-                     }
-                     if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) {
-                        t = res[2], it = 1.0f - t;
-                        px = it*it*x0 + 2*t*it*x1 + t*t*x2;
-                        py = it*it*y0 + 2*t*it*y1 + t*t*y2;
-                        dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
-                        if (dist2 < min_dist * min_dist)
-                           min_dist = (float) STBTT_sqrt(dist2);
-                     }
-                  }
-               }
-            }
-            if (winding == 0)
-               min_dist = -min_dist;  // if outside the shape, value is negative
-            val = onedge_value + pixel_dist_scale * min_dist;
-            if (val < 0)
-               val = 0;
-            else if (val > 255)
-               val = 255;
-            data[(y-iy0)*w+(x-ix0)] = (unsigned char) val;
-         }
-      }
-      STBTT_free(precompute, info->userdata);
-      STBTT_free(verts, info->userdata);
-   }
-   return data;
-}
-
-STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
-{
-   return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff);
-}
-
-STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata)
-{
-   STBTT_free(bitmap, userdata);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// font name matching -- recommended not to use this
-//
-
-// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string
-static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2)
-{
-   stbtt_int32 i=0;
-
-   // convert utf16 to utf8 and compare the results while converting
-   while (len2) {
-      stbtt_uint16 ch = s2[0]*256 + s2[1];
-      if (ch < 0x80) {
-         if (i >= len1) return -1;
-         if (s1[i++] != ch) return -1;
-      } else if (ch < 0x800) {
-         if (i+1 >= len1) return -1;
-         if (s1[i++] != 0xc0 + (ch >> 6)) return -1;
-         if (s1[i++] != 0x80 + (ch & 0x3f)) return -1;
-      } else if (ch >= 0xd800 && ch < 0xdc00) {
-         stbtt_uint32 c;
-         stbtt_uint16 ch2 = s2[2]*256 + s2[3];
-         if (i+3 >= len1) return -1;
-         c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;
-         if (s1[i++] != 0xf0 + (c >> 18)) return -1;
-         if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1;
-         if (s1[i++] != 0x80 + ((c >>  6) & 0x3f)) return -1;
-         if (s1[i++] != 0x80 + ((c      ) & 0x3f)) return -1;
-         s2 += 2; // plus another 2 below
-         len2 -= 2;
-      } else if (ch >= 0xdc00 && ch < 0xe000) {
-         return -1;
-      } else {
-         if (i+2 >= len1) return -1;
-         if (s1[i++] != 0xe0 + (ch >> 12)) return -1;
-         if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1;
-         if (s1[i++] != 0x80 + ((ch     ) & 0x3f)) return -1;
-      }
-      s2 += 2;
-      len2 -= 2;
-   }
-   return i;
-}
-
-static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2)
-{
-   return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2);
-}
-
-// returns results in whatever encoding you request... but note that 2-byte encodings
-// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare
-STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID)
-{
-   stbtt_int32 i,count,stringOffset;
-   stbtt_uint8 *fc = font->data;
-   stbtt_uint32 offset = font->fontstart;
-   stbtt_uint32 nm = stbtt__find_table(fc, offset, "name");
-   if (!nm) return NULL;
-
-   count = ttUSHORT(fc+nm+2);
-   stringOffset = nm + ttUSHORT(fc+nm+4);
-   for (i=0; i < count; ++i) {
-      stbtt_uint32 loc = nm + 6 + 12 * i;
-      if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2)
-          && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) {
-         *length = ttUSHORT(fc+loc+8);
-         return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10));
-      }
-   }
-   return NULL;
-}
-
-static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id)
-{
-   stbtt_int32 i;
-   stbtt_int32 count = ttUSHORT(fc+nm+2);
-   stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4);
-
-   for (i=0; i < count; ++i) {
-      stbtt_uint32 loc = nm + 6 + 12 * i;
-      stbtt_int32 id = ttUSHORT(fc+loc+6);
-      if (id == target_id) {
-         // find the encoding
-         stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4);
-
-         // is this a Unicode encoding?
-         if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) {
-            stbtt_int32 slen = ttUSHORT(fc+loc+8);
-            stbtt_int32 off = ttUSHORT(fc+loc+10);
-
-            // check if there's a prefix match
-            stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen);
-            if (matchlen >= 0) {
-               // check for target_id+1 immediately following, with same encoding & language
-               if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) {
-                  slen = ttUSHORT(fc+loc+12+8);
-                  off = ttUSHORT(fc+loc+12+10);
-                  if (slen == 0) {
-                     if (matchlen == nlen)
-                        return 1;
-                  } else if (matchlen < nlen && name[matchlen] == ' ') {
-                     ++matchlen;
-                     if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen))
-                        return 1;
-                  }
-               } else {
-                  // if nothing immediately following
-                  if (matchlen == nlen)
-                     return 1;
-               }
-            }
-         }
-
-         // @TODO handle other encodings
-      }
-   }
-   return 0;
-}
-
-static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags)
-{
-   stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name);
-   stbtt_uint32 nm,hd;
-   if (!stbtt__isfont(fc+offset)) return 0;
-
-   // check italics/bold/underline flags in macStyle...
-   if (flags) {
-      hd = stbtt__find_table(fc, offset, "head");
-      if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0;
-   }
-
-   nm = stbtt__find_table(fc, offset, "name");
-   if (!nm) return 0;
-
-   if (flags) {
-      // if we checked the macStyle flags, then just check the family and ignore the subfamily
-      if (stbtt__matchpair(fc, nm, name, nlen, 16, -1))  return 1;
-      if (stbtt__matchpair(fc, nm, name, nlen,  1, -1))  return 1;
-      if (stbtt__matchpair(fc, nm, name, nlen,  3, -1))  return 1;
-   } else {
-      if (stbtt__matchpair(fc, nm, name, nlen, 16, 17))  return 1;
-      if (stbtt__matchpair(fc, nm, name, nlen,  1,  2))  return 1;
-      if (stbtt__matchpair(fc, nm, name, nlen,  3, -1))  return 1;
-   }
-
-   return 0;
-}
-
-static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags)
-{
-   stbtt_int32 i;
-   for (i=0;;++i) {
-      stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i);
-      if (off < 0) return off;
-      if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags))
-         return off;
-   }
-}
-
-#if defined(__GNUC__) || defined(__clang__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wcast-qual"
-#endif
-
-STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,
-                                float pixel_height, unsigned char *pixels, int pw, int ph,
-                                int first_char, int num_chars, stbtt_bakedchar *chardata)
-{
-   return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata);
-}
-
-STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index)
-{
-   return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index);
-}
-
-STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data)
-{
-   return stbtt_GetNumberOfFonts_internal((unsigned char *) data);
-}
-
-STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset)
-{
-   return stbtt_InitFont_internal(info, (unsigned char *) data, offset);
-}
-
-STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags)
-{
-   return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags);
-}
-
-STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2)
-{
-   return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2);
-}
-
-#if defined(__GNUC__) || defined(__clang__)
-#pragma GCC diagnostic pop
-#endif
-
-#endif // STB_TRUETYPE_IMPLEMENTATION
-
-
-// FULL VERSION HISTORY
-//
-//   1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod
-//   1.18 (2018-01-29) add missing function
-//   1.17 (2017-07-23) make more arguments const; doc fix
-//   1.16 (2017-07-12) SDF support
-//   1.15 (2017-03-03) make more arguments const
-//   1.14 (2017-01-16) num-fonts-in-TTC function
-//   1.13 (2017-01-02) support OpenType fonts, certain Apple fonts
-//   1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
-//   1.11 (2016-04-02) fix unused-variable warning
-//   1.10 (2016-04-02) allow user-defined fabs() replacement
-//                     fix memory leak if fontsize=0.0
-//                     fix warning from duplicate typedef
-//   1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges
-//   1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
-//   1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
-//                     allow PackFontRanges to pack and render in separate phases;
-//                     fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);
-//                     fixed an assert() bug in the new rasterizer
-//                     replace assert() with STBTT_assert() in new rasterizer
-//   1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine)
-//                     also more precise AA rasterizer, except if shapes overlap
-//                     remove need for STBTT_sort
-//   1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC
-//   1.04 (2015-04-15) typo in example
-//   1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes
-//   1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++
-//   1.01 (2014-12-08) fix subpixel position when oversampling to exactly match
-//                        non-oversampled; STBTT_POINT_SIZE for packed case only
-//   1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling
-//   0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg)
-//   0.9  (2014-08-07) support certain mac/iOS fonts without an MS platformID
-//   0.8b (2014-07-07) fix a warning
-//   0.8  (2014-05-25) fix a few more warnings
-//   0.7  (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back
-//   0.6c (2012-07-24) improve documentation
-//   0.6b (2012-07-20) fix a few more warnings
-//   0.6  (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels,
-//                        stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty
-//   0.5  (2011-12-09) bugfixes:
-//                        subpixel glyph renderer computed wrong bounding box
-//                        first vertex of shape can be off-curve (FreeSans)
-//   0.4b (2011-12-03) fixed an error in the font baking example
-//   0.4  (2011-12-01) kerning, subpixel rendering (tor)
-//                    bugfixes for:
-//                        codepoint-to-glyph conversion using table fmt=12
-//                        codepoint-to-glyph conversion using table fmt=4
-//                        stbtt_GetBakedQuad with non-square texture (Zer)
-//                    updated Hello World! sample to use kerning and subpixel
-//                    fixed some warnings
-//   0.3  (2009-06-24) cmap fmt=12, compound shapes (MM)
-//                    userdata, malloc-from-userdata, non-zero fill (stb)
-//   0.2  (2009-03-11) Fix unsigned/signed char warnings
-//   0.1  (2009-03-09) First public release
-//
-
-/*
-------------------------------------------------------------------------------
-This software is available under 2 licenses -- choose whichever you prefer.
-------------------------------------------------------------------------------
-ALTERNATIVE A - MIT License
-Copyright (c) 2017 Sean Barrett
-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.
-------------------------------------------------------------------------------
-ALTERNATIVE B - Public Domain (www.unlicense.org)
-This is free and unencumbered software released into the public domain.
-Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
-software, either in source code form or as a compiled binary, for any purpose,
-commercial or non-commercial, and by any means.
-In jurisdictions that recognize copyright laws, the author or authors of this
-software dedicate any and all copyright interest in the software to the public
-domain. We make this dedication for the benefit of the public at large and to
-the detriment of our heirs and successors. We intend this dedication to be an
-overt act of relinquishment in perpetuity of all present and future rights to
-this software under copyright law.
-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 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.
-------------------------------------------------------------------------------
-*/
diff --git src/drivers/Pico/Fl_Pico_Copy_Surface.cxx src/drivers/Pico/Fl_Pico_Copy_Surface.cxx
deleted file mode 100644
index 8b13789..0000000
--- src/drivers/Pico/Fl_Pico_Copy_Surface.cxx
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git src/drivers/Pico/Fl_Pico_Graphics_Driver.H src/drivers/Pico/Fl_Pico_Graphics_Driver.H
deleted file mode 100644
index 93550f8..0000000
--- src/drivers/Pico/Fl_Pico_Graphics_Driver.H
+++ /dev/null
@@ -1,211 +0,0 @@
-//
-// Definition of the Pico minimal graphics driver
-// for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2016 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_Pico_Graphics_Driver.H
- \brief Definition of Pico minimal graphics driver.
- */
-
-#ifndef FL_PICO_GRAPHICS_DRIVER_H
-#define FL_PICO_GRAPHICS_DRIVER_H
-
-#include <FL/Fl_Graphics_Driver.H>
-
-
-/**
- \brief The Pico minimal graphics class.
-
- This class is implemented as a base class for minimal core drivers.
- */
-class Fl_Pico_Graphics_Driver : public Fl_Graphics_Driver {
-//  friend class Fl_Surface_Device;
-//  friend class Fl_Pixmap;
-//  friend class Fl_Bitmap;
-//  friend class Fl_RGB_Image;
-//  friend int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg);
-//public:
-//  // The following functions create the various graphics drivers that are required
-//  // for core operations. They must be implemented as members of Fl_Graphics_Driver,
-//  // but located in the device driver module that is linked to the core library
-//  static Fl_Graphics_Driver *newMainGraphicsDriver();
-//  //static Fl_Graphics_Driver *newOpenGLGraphicsDriver();
-//  //static Fl_Graphics_Driver *newPrinterGraphicsDriver();
-//  //static Fl_Graphics_Driver *new...;
-//public:
-//  /** A 2D coordinate transformation matrix */
-//  struct matrix {double a, b, c, d, x, y;};
-//  /** Features that a derived class may possess.  */
-//  typedef enum {
-//    NATIVE = 1, /**< native graphics driver for the platform */
-//    PRINTER = 2 /**< graphics driver for a printer drawing surface */
-//  } driver_feature;
-//
-//  int fl_clip_state_number;
-//protected:
-//  static const matrix m0;
-//  Fl_Font font_; // current font
-//  Fl_Fontsize size_; // current font size
-//  Fl_Color color_; // current color
-//  int sptr;
-//  static const int matrix_stack_size = FL_MATRIX_STACK_SIZE;
-//  matrix stack[FL_MATRIX_STACK_SIZE];
-//  matrix m;
-//  int n, p_size, gap_;
-//  XPOINT *p;
-//  int what;
-//  int rstackptr;
-//  static const int region_stack_max = FL_REGION_STACK_SIZE - 1;
-//  Fl_Region rstack[FL_REGION_STACK_SIZE];
-//  Fl_Font_Descriptor *font_descriptor_;
-//#ifndef FL_DOXYGEN
-//  enum {LINE, LOOP, POLYGON, POINT_};
-//  inline int vertex_no() { return n; }
-//  inline XPOINT *vertices() {return p;}
-//  inline int vertex_kind() {return what;}
-//#endif
-//  matrix *fl_matrix; /**< Points to the current coordinate transformation matrix */
-//
-//public:
-//  Fl_Graphics_Driver();
-//  virtual ~Fl_Graphics_Driver() { if (p) free(p); }
-//  virtual char can_do_alpha_blending() { return 0; }
-//  // --- implementation is in src/fl_rect.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_rect.cxx
-  virtual void point(int x, int y);
-  virtual void rect(int x, int y, int w, int h);
-//  virtual void focus_rect(int x, int y, int w, int h);
-  virtual void rectf(int x, int y, int w, int h);
-  virtual void line(int x, int y, int x1, int y1);
-  virtual void line(int x, int y, int x1, int y1, int x2, int y2);
-  virtual void xyline(int x, int y, int x1);
-  virtual void xyline(int x, int y, int x1, int y2);
-  virtual void xyline(int x, int y, int x1, int y2, int x3) ;
-  virtual void yxline(int x, int y, int y1) ;
-  virtual void yxline(int x, int y, int y1, int x2) ;
-  virtual void yxline(int x, int y, int y1, int x2, int y3) ;
-  virtual void loop(int x0, int y0, int x1, int y1, int x2, int y2) ;
-  virtual void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) ;
-  virtual void polygon(int x0, int y0, int x1, int y1, int x2, int y2) ;
-  virtual void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) ;
-//  // --- clipping
-  virtual void push_clip(int x, int y, int w, int h) ;
-  virtual int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) ;
-  virtual int not_clipped(int x, int y, int w, int h) ;
-  virtual void push_no_clip() ;
-  virtual void pop_clip() ;
-//  virtual Fl_Region clip_region();              // has default implementation
-//  virtual void clip_region(Fl_Region r);        // has default implementation
-//  virtual void restore_clip();
-//  // --- implementation is in src/fl_vertex.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_vertex.cxx
-//  virtual void push_matrix();
-//  virtual void pop_matrix();
-//  virtual void mult_matrix(double a, double b, double c, double d, double x, double y);
-//  virtual void rotate(double d);
-//  virtual void scale(double x, double y);
-//  virtual void scale(double x);
-//  virtual void translate(double x,double y);
-  virtual void begin_points();
-  virtual void begin_line();
-  virtual void begin_loop();
-  virtual void begin_polygon();
-  virtual void begin_complex_polygon() ;
-//  virtual double transform_x(double x, double y);
-//  virtual double transform_y(double x, double y);
-//  virtual double transform_dx(double x, double y);
-//  virtual double transform_dy(double x, double y);
-  virtual void transformed_vertex(double xf, double yf) ;
-  virtual void vertex(double x, double y) ;
-  virtual void end_points() ;
-  virtual void end_line() ;
-  virtual void end_loop() ;
-  virtual void end_polygon() ;
-  virtual void end_complex_polygon() ;
-  virtual void gap() ;
-  virtual void circle(double x, double y, double r) ;
-//  // --- implementation is in src/fl_arc.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_arc.cxx if needed
-//  virtual void arc(double x, double y, double r, double start, double end);
-//  // --- implementation is in src/fl_arci.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_arci.cxx
-  virtual void arc(int x, int y, int w, int h, double a1, double a2) ;
-  virtual void pie(int x, int y, int w, int h, double a1, double a2) ;
-//  // --- implementation is in src/fl_curve.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_curve.cxx if needed
-//  virtual void curve(double X0, double Y0, double X1, double Y1, double X2, double Y2, double X3, double Y3);
-//  // --- implementation is in src/fl_line_style.cxx which includes src/cfg_gfx/xxx_line_style.cxx
-  virtual void line_style(int style, int width=0, char* dashes=0) ;
-//  // --- implementation is in src/fl_color.cxx which includes src/cfg_gfx/xxx_color.cxx
-//  virtual void color(Fl_Color c) { color_ = c; }
-//  virtual Fl_Color color() { return color_; }
-  virtual void color(uchar r, uchar g, uchar b) ;
-//  // --- implementation is in src/fl_font.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_font.cxx
-  virtual void draw(const char *str, int n, int x, int y) ;
-//  virtual void draw(const char *str, int n, float x, float y) { draw(str, n, (int)(x+0.5), (int)(y+0.5));}
-//  virtual void draw(int angle, const char *str, int n, int x, int y) { draw(str, n, x, y); }
-//  virtual void rtl_draw(const char *str, int n, int x, int y) { draw(str, n, x, y); }
-//  /** Returns non-zero if the graphics driver possesses the \p feature */
-//  virtual int has_feature(driver_feature feature) { return 0; }
-//  virtual void font(Fl_Font face, Fl_Fontsize fsize) {font_ = face; size_ = fsize;}
-//  virtual Fl_Font font() {return font_; }
-//  virtual Fl_Fontsize size() {return size_; }
-  virtual double width(const char *str, int n);
-//  virtual double width(unsigned int c) { char ch = (char)c; return width(&ch, 1); }
-  virtual int height();
-  virtual int descent();
-//  virtual Fl_Font_Descriptor *font_descriptor() { return font_descriptor_;}
-//  virtual void font_descriptor(Fl_Font_Descriptor *d) { font_descriptor_ = d;}
-//  // --- implementation is in src/fl_image.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_font.cxx
-  virtual Fl_Bitmask create_bitmask(int w, int h, const uchar *array) ;
-//  virtual void cache(Fl_Pixmap *img) { return 0; }
-//  virtual void cache(Fl_Bitmap *img) { return 0; }
-//  virtual void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_) { }
-  virtual void delete_bitmask(Fl_Bitmask bm) ;
-//  virtual void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0) {}
-//  virtual void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0) {}
-//  virtual void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3) {}
-//  virtual void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1) {}
-//  /** \brief Draws an Fl_RGB_Image object to the device.
-//   *
-//   Specifies a bounding box for the image, with the origin (upper left-hand corner) of
-//   the image offset by the cx and cy arguments.
-//   */
-//  virtual void draw(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy) {}
-//  /** \brief Draws an Fl_Pixmap object to the device.
-//   *
-//   Specifies a bounding box for the image, with the origin (upper left-hand corner) of
-//   the image offset by the cx and cy arguments.
-//   */
-//  virtual void draw(Fl_Pixmap * pxm,int XP, int YP, int WP, int HP, int cx, int cy) {}
-//  /** \brief Draws an Fl_Bitmap object to the device.
-//   *
-//   Specifies a bounding box for the image, with the origin (upper left-hand corner) of
-//   the image offset by the cx and cy arguments.
-//   */
-//  virtual void draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) {}
-//  virtual void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
-//
-//  /** Sets the value of the driver-specific graphics context. */
-//  virtual void gc(void*) {}
-//  /** Returns the driver-specific graphics context, of NULL if there's none. */
-//  virtual void *gc(void) {return NULL;}
-//  /** Support for pixmap drawing */
-//  virtual uchar **mask_bitmap() { return 0; }
-//  /** Support for pixmap drawing */
-//  virtual void mask_bitmap(uchar **) {}
-//protected:
-//  // --- implementation is in src/fl_vertex.cxx which includes src/cfg_gfx/xxx_rect.cxx
-//  virtual void transformed_vertex0(COORD_T x, COORD_T y);
-//  virtual void fixloop();
-};
-
-#endif // FL_PICO_GRAPHICS_DRIVER_H
diff --git src/drivers/Pico/Fl_Pico_Graphics_Driver.cxx src/drivers/Pico/Fl_Pico_Graphics_Driver.cxx
deleted file mode 100644
index cf0928c..0000000
--- src/drivers/Pico/Fl_Pico_Graphics_Driver.cxx
+++ /dev/null
@@ -1,506 +0,0 @@
-//
-// Rectangle drawing routines for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2020 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-
-#include <config.h>
-#include "Fl_Pico_Graphics_Driver.H"
-#include <FL/fl_draw.H>
-#include <FL/math.h>
-
-
-static int sign(int x) { return (x>0)-(x<0); }
-
-
-void Fl_Pico_Graphics_Driver::point(int x, int y)
-{
-  // This is the one method that *must* be overridden in the final driver
-  // class. All other methods can be derived from this one method. The
-  // result should work, but will be slow and inefficient.
-}
-
-
-void Fl_Pico_Graphics_Driver::rect(int x, int y, int w, int h)
-{
-  int x1 = x+w-1, y1 = y+h-1;
-  xyline(x, y, x1);
-  xyline(x, y1, x1);
-  yxline(x, y, y1);
-  yxline(x1, y, y1);
-}
-
-
-void Fl_Pico_Graphics_Driver::rectf(int x, int y, int w, int h)
-{
-  int i = y, n = y+h, xn = x+w-1;
-  for ( ; i<n; i++) {
-    xyline(x, i, xn);
-  }
-}
-
-
-void Fl_Pico_Graphics_Driver::line(int x, int y, int x1, int y1)
-{
-  if (x==x1) {
-    return yxline(x, y, y1);
-  }
-  if (y==y1) {
-    return xyline(x, y, x1);
-  }
-  // Bresenham
-  int w = x1 - x, dx = abs(w);
-  int h = y1 - y, dy = abs(h);
-  int dx1 = sign(w), dy1 = sign(h), dx2, dy2;
-  int min, max;
-  if (dx < dy) {
-    min = dx; max = dy;
-    dx2 = 0;
-    dy2 = dy1;
-  } else {
-    min = dy; max = dx;
-    dx2 = dx1;
-    dy2 = 0;
-  }
-  int num = max/2;
-  for (int i=max+1; i>0; i--) {
-    point(x, y);
-    num += min;
-    if (num>=max) {
-      num -= max;
-      x += dx1;
-      y += dy1;
-    } else {
-      x += dx2;
-      y += dy2;
-    }
-  }
-}
-
-
-void Fl_Pico_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2)
-{
-  line(x, y, x1, y1);
-  line(x1, y1, x2, y2);
-}
-
-
-void Fl_Pico_Graphics_Driver::xyline(int x, int y, int x1)
-{
-  int i;
-  if (x1<x) {
-    int tmp = x; x = x1; x1 = tmp;
-  }
-  for (i=x; i<=x1; i++) {
-    point(i, y);
-  }
-}
-
-
-void Fl_Pico_Graphics_Driver::xyline(int x, int y, int x1, int y2)
-{
-  xyline(x, y, x1);
-  yxline(x1, y, y2);
-}
-
-
-void Fl_Pico_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3)
-{
-  xyline(x, y, x1);
-  yxline(x1, y, y2);
-  xyline(x1, y2, x3);
-}
-
-
-void Fl_Pico_Graphics_Driver::yxline(int x, int y, int y1)
-{
-  int i;
-  if (y1<y) {
-    int tmp = y; y = y1; y1 = tmp;
-  }
-  for (i=y; i<=y1; i++) {
-    point(x, i);
-  }
-}
-
-
-void Fl_Pico_Graphics_Driver::yxline(int x, int y, int y1, int x2)
-{
-  yxline(x, y, y1);
-  xyline(x, y1, x2);
-}
-
-
-void Fl_Pico_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3)
-{
-  yxline(x, y, y1);
-  xyline(x, y1, x2);
-  yxline(x2, y1, y3);
-}
-
-
-void Fl_Pico_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2)
-{
-  line(x0, y0, x1, y1);
-  line(x1, y1, x2, y2);
-  line(x2, y2, x0, y0);
-}
-
-
-void Fl_Pico_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3)
-{
-  line(x0, y0, x1, y1);
-  line(x1, y1, x2, y2);
-  line(x2, y2, x3, y3);
-  line(x3, y3, x0, y0);
-}
-
-
-void Fl_Pico_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2)
-{
-  // FIXME: fill
-  line(x0, y0, x1, y1);
-  line(x1, y1, x2, y2);
-  line(x2, y2, x0, y0);
-}
-
-
-void Fl_Pico_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3)
-{
-  // FIXME: fill
-  line(x0, y0, x1, y1);
-  line(x1, y1, x2, y2);
-  line(x2, y2, x3, y3);
-  line(x3, y3, x0, y0);
-}
-
-
-void Fl_Pico_Graphics_Driver::push_clip(int x, int y, int w, int h)
-{
-}
-
-
-int Fl_Pico_Graphics_Driver::clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H)
-{
-  X = x; Y = y; W = w; H = h;
-  return 0;
-}
-
-
-int Fl_Pico_Graphics_Driver::not_clipped(int x, int y, int w, int h)
-{
-  return 1;
-}
-
-
-void Fl_Pico_Graphics_Driver::push_no_clip()
-{
-}
-
-
-void Fl_Pico_Graphics_Driver::pop_clip()
-{
-}
-
-
-static double px, py; // FIXME: aaaah!
-static double pxf, pyf;
-static int pn;
-
-
-void Fl_Pico_Graphics_Driver::begin_points()
-{
-  what = POINT_;
-  pn = 0;
-}
-
-
-void Fl_Pico_Graphics_Driver::begin_complex_polygon()
-{
-  what = POLYGON;
-  pn = 0;
-}
-
-
-void Fl_Pico_Graphics_Driver::begin_line()
-{
-  what = LINE;
-  pn = 0;
-}
-
-
-void Fl_Pico_Graphics_Driver::begin_loop()
-{
-  what = LOOP;
-  pn = 0;
-}
-
-
-void Fl_Pico_Graphics_Driver::begin_polygon()
-{
-  what = POLYGON;
-  pn = 0;
-}
-
-
-void Fl_Pico_Graphics_Driver::transformed_vertex(double x, double y)
-{
-  if (pn>0) {
-    switch (what) {
-      case POINT_:  point(x, y); break;
-      case LINE:    line(px, py, x, y); break;
-      case LOOP:    line(px, py, x, y); break;
-      case POLYGON: line(px, py, x, y); break; // FIXME: fill!
-    }
-  }
-  if (pn==0 ) { pxf = x; pyf = y; }
-  px = x; py = y;
-  pn++;
-}
-
-
-void Fl_Pico_Graphics_Driver::vertex(double x, double y)
-{
-  transformed_vertex(x*m.a + y*m.c + m.x, x*m.b + y*m.d + m.y);
-}
-
-
-void Fl_Pico_Graphics_Driver::end_points()
-{
-  pn = 0;
-}
-
-
-void Fl_Pico_Graphics_Driver::end_line()
-{
-  pn = 0;
-}
-
-
-void Fl_Pico_Graphics_Driver::end_loop()
-{
-  line(px, py, pxf, pyf);
-  pn = 0;
-}
-
-
-void Fl_Pico_Graphics_Driver::end_polygon()
-{
-  line(px, py, pxf, pyf);  // FIXME: fill!
-  pn = 0;
-}
-
-
-void Fl_Pico_Graphics_Driver::end_complex_polygon()
-{
-  line(px, py, pxf, pyf);  // FIXME: fill!
-  pn = 0;
-}
-
-
-void Fl_Pico_Graphics_Driver::gap()
-{
-  pn = 0;
-}
-
-
-void Fl_Pico_Graphics_Driver::circle(double x, double y, double r)
-{
-  begin_loop();
-  double X = r;
-  double Y = 0;
-  fl_vertex(x+X,y+Y);
-
-  double rx = fabs(transform_dx(r, r));
-  double ry = fabs(transform_dy(r, r));
-
-  double circ = M_PI*0.5*(rx+ry);
-  int segs = circ * 360 / 1000;  // every line is about three pixels long
-  if (segs<16) segs = 16;
-
-  double A = 2*M_PI;
-  int i = segs;
-
-  if (i) {
-    double epsilon = A/i;                       // Arc length for equal-size steps
-    double cos_e = cos(epsilon);        // Rotation coefficients
-    double sin_e = sin(epsilon);
-    do {
-      double Xnew =  cos_e*X + sin_e*Y;
-      Y = -sin_e*X + cos_e*Y;
-      fl_vertex(x + (X=Xnew), y + Y);
-    } while (--i);
-  }
-  end_loop();
-}
-
-
-void Fl_Pico_Graphics_Driver::arc(int xi, int yi, int w, int h, double a1, double a2)
-{
-  if (a2<=a1) return;
-
-  double rx = w/2.0;
-  double ry = h/2.0;
-  double x = xi + rx;
-  double y = yi + ry;
-  double circ = M_PI*0.5*(rx+ry);
-  int i, segs = circ * (a2-a1) / 1000;  // every line is about three pixels long
-  if (segs<3) segs = 3;
-
-  int px, py;
-  a1 = a1/180*M_PI;
-  a2 = a2/180*M_PI;
-  double step = (a2-a1)/segs;
-
-  int nx = x + sin(a1)*rx;
-  int ny = y - cos(a1)*ry;
-  for (i=segs; i>0; i--) {
-    a1+=step;
-    px = nx; py = ny;
-    nx = x + sin(a1)*rx;
-    ny = y - cos(a1)*ry;
-    line(px, py, nx, ny);
-  }
-}
-
-
-void Fl_Pico_Graphics_Driver::pie(int x, int y, int w, int h, double a1, double a2)
-{
-  // FIXME: implement this
-}
-
-
-void Fl_Pico_Graphics_Driver::line_style(int style, int width, char* dashes)
-{
-}
-
-
-void Fl_Pico_Graphics_Driver::color(uchar r, uchar g, uchar b)
-{
-}
-
-
-Fl_Bitmask Fl_Pico_Graphics_Driver::create_bitmask(int w, int h, const uchar *array)
-{
-  return 0;
-}
-
-
-void Fl_Pico_Graphics_Driver::delete_bitmask(Fl_Bitmask bm)
-{
-}
-
-
-
-/*
-  |01234567|
- -+--------+
- 0|        |____
- 1|++++++++|font
- 2|++++++++|
- 3|++++++++|
- 4|++++++++|
- 5|++++++++|____
- 6|        |descent
- 7|        |
- -+--------+
- */
-
-
-static const char *font_data[128] = {
-  /*00*/0, /*01*/0, /*02*/0, /*03*/0,
-  /*04*/0, /*05*/0, /*06*/0, /*07*/0,
-  /*08*/0, /*09*/0, /*0A*/0, /*0B*/0,
-  /*0C*/0, /*0D*/0, /*0E*/0, /*0F*/0,
-  /*10*/0, /*11*/0, /*12*/0, /*13*/0,
-  /*14*/0, /*15*/0, /*16*/0, /*17*/0,
-  /*18*/0, /*19*/0, /*1A*/0, /*1B*/0,
-  /*1C*/0, /*1D*/0, /*1E*/0, /*1F*/0,
-  /* */0, /*!*/"\31\34\100\35\36", /*"*/"\31\22\100\51\42", /*#*/"\31\15\100\61\45\100\12\72\100\04\64",
-  /*$*/"\62\51\11\02\13\53\64\55\15\04\100\30\36", /*%*/"\21\11\02\13\23\32\21\100\15\51\100\34\43\53\64\55\45\34", /*&*/"\63\45\15\04\13\52\41\21\12\65", /*'*/"\31\22",
-  /*(*/"\51\32\23\24\35\56", /*)*/"\21\42\53\54\45\26", /***/"\31\33\15\100\33\55\100\02\33\62", /*+*/"\35\31\100\03\63",
-  /*,*/"\35\45\36", /*-*/"\13\53", /*.*/"\35\36", /* / */"\51\15",
-  /*0*/"\21\12\14\25\55\64\62\51\21\100\24\52", /*1*/"\22\41\45", /*2*/"\12\21\51\62\53\24\15\65", /*3*/"\12\21\51\62\53\64\55\25\14\100\53\33",
-  /*4*/"\55\51\04\64", /*5*/"\14\25\55\64\53\13\21\61", /*6*/"\62\51\21\12\14\25\55\64\53\13", /*7*/"\11\61\33\25",
-  /*8*/"\12\21\51\62\53\64\55\25\14\23\12\100\23\53", /*9*/"\14\25\55\64\62\51\21\12\23\63", /*:*/"\32\33\100\35\36", /*;*/"\32\33\100\25\35\26",
-  /*<*/"\62\13\64", /*=*/"\12\62\100\14\64", /*>*/"\12\63\14", /*?*/"\12\21\51\62\43\34\35\100\36\37",
-  /*@*/"\56\16\05\02\11\51\62\64\55\35\24\23\32\52\63", /*A*/"\05\31\65\100\14\54", /*B*/"\11\51\62\53\64\55\15\11\100\13\53", /*C*/"\62\51\11\02\04\15\55\64",
-  /*D*/"\11\51\62\64\55\15\11", /*E*/"\61\11\15\65\100\13\53", /*F*/"\61\11\15\100\13\53", /*G*/"\62\51\11\02\04\15\55\64\63\33",
-  /*H*/"\11\15\100\61\65\100\13\63", /*I*/"\21\41\100\25\45\100\35\31", /*J*/"\51\54\45\15\04", /*K*/"\11\15\100\14\61\100\65\33",
-  /*L*/"\11\15\65", /*M*/"\05\01\35\61\65", /*N*/"\05\01\65\61", /*O*/"\02\11\51\62\64\55\15\04\02",
-  /*P*/"\15\11\51\62\53\13", /*Q*/"\02\11\51\62\64\55\15\04\02\100\65\34", /*R*/"\15\11\51\62\53\13\100\33\65", /*S*/"\62\51\11\02\13\53\64\55\15\04",
-  /*T*/"\01\61\100\31\35", /*U*/"\61\64\55\15\04\01", /*V*/"\01\35\61", /*W*/"\01\15\31\55\61",
-  /*X*/"\01\65\100\05\61", /*Y*/"\01\33\35\100\33\61", /*Z*/"\01\61\05\65", /*[*/"\51\31\36\56",
-  /*\*/"\21\55", /*]*/"\21\41\46\26", /*^*/"\13\31\53", /*_*/"\06\76",
-  /*`*/"\31\42", /*a*/"\22\52\63\65\100\63\23\14\25\55\64", /*b*/"\11\15\100\14\25\55\64\63\52\22\13", /*c*/"\63\52\22\13\14\25\55\64",
-  /*d*/"\61\65\100\64\55\25\14\13\22\52\63", /*e*/"\64\63\52\22\13\14\25\55\100\64\14", /*f*/"\35\32\41\51\100\22\52", /*g*/"\62\65\56\26\100\63\52\22\13\14\25\55\64",
-  /*h*/"\11\15\100\65\63\52\22\13", /*i*/"\31\32\100\33\100\23\33\35\100\25\45", /*j*/"\31\32\100\33\35\26\16", /*k*/"\11\15\100\14\62\100\33\65",
-  /*l*/"\31\34\45\55", /*m*/"\05\02\100\03\12\22\33\35\100\33\42\52\63\65", /*n*/"\12\15\100\13\22\52\63\65", /*o*/"\22\13\14\25\55\64\63\52\22",
-  /*p*/"\16\12\100\13\22\52\63\64\55\25\14", /*q*/"\62\66\100\63\52\22\13\14\25\55\64", /*r*/"\22\25\100\23\32\42\53", /*s*/"\63\52\22\13\64\55\25\14",
-  /*t*/"\31\34\45\55\100\22\42", /*u*/"\12\14\25\55\64\62\100\64\65", /*v*/"\62\35\02", /*w*/"\02\15\32\55\62",
-  /*x*/"\62\15\100\65\12", /*y*/"\12\45\62\100\45\36\16", /*z*/"\12\62\15\65", /*{*/"\51\41\32\33\24\35\36\47\57\100\14\24",
-  /*|*/"\31\37", /*}*/"\21\31\42\43\54\64\100\54\45\46\37\27", /*~*/"\12\21\31\42\52\61", /*7F*/0
-};
-
-
-double Fl_Pico_Graphics_Driver::width(const char *str, int n) {
-  return size_*n*0.5;
-}
-
-
-int Fl_Pico_Graphics_Driver::descent() {
-  return (int)(size_ - size_*0.8);
-}
-
-
-int Fl_Pico_Graphics_Driver::height() {
-  return (int)(size_);
-}
-
-
-void Fl_Pico_Graphics_Driver::draw(const char *str, int n, int x, int y)
-{
-  int i;
-  for (i=0; i<n; i++) {
-    char c = str[i] & 0x7f;
-    const char *fd = font_data[(int)c];
-    if (fd) {
-      char rendering = 0;
-      float px=0.0f, py=0.0f;
-      for (;;) {
-        char cmd = *fd++;
-        if (cmd==0) {
-          if (rendering) {
-            end_line();
-            rendering = 0;
-          }
-          break;
-        } else if (cmd>63) {
-          if (cmd=='\100' && rendering) {
-            end_line();
-            rendering = 0;
-          }
-        } else {
-          if (!rendering) { begin_line(); rendering = 1; }
-          int vx = (cmd & '\70')>>3;
-          int vy = (cmd & '\07');
-          px = (int)(0.5+x+vx*size_*0.5/8.0);
-          py = (int)(0.5+y+vy*size_/8.0-0.8*size_);
-          vertex(px, py);
-        }
-      }
-    }
-    x += size_*0.5;
-  }
-}
diff --git src/drivers/Pico/Fl_Pico_Image_Surface.cxx src/drivers/Pico/Fl_Pico_Image_Surface.cxx
deleted file mode 100644
index 8b13789..0000000
--- src/drivers/Pico/Fl_Pico_Image_Surface.cxx
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git src/drivers/Pico/Fl_Pico_Screen_Driver.H src/drivers/Pico/Fl_Pico_Screen_Driver.H
deleted file mode 100644
index 7f03cb6..0000000
--- src/drivers/Pico/Fl_Pico_Screen_Driver.H
+++ /dev/null
@@ -1,58 +0,0 @@
-//
-// Definition of Pico Screen interface
-// for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2016 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_Pico_Screen_Driver.H
- \brief Definition of Pico Screen interface.
- */
-
-#ifndef FL_PICO_SCREEN_DRIVER_H
-#define FL_PICO_SCREEN_DRIVER_H
-
-#include "../../Fl_Screen_Driver.H"
-
-
-class FL_EXPORT Fl_Pico_Screen_Driver : public Fl_Screen_Driver
-{
-public:
-  Fl_Pico_Screen_Driver();
-  virtual ~Fl_Pico_Screen_Driver();
-  virtual void init();
-  virtual int x();
-  virtual int y();
-  virtual int w();
-  virtual int h();
-  virtual void screen_xywh(int &X, int &Y, int &W, int &H, int n);
-  virtual void screen_dpi(float &h, float &v, int n=0);
-  virtual void screen_work_area(int &X, int &Y, int &W, int &H, int n);
-  // --- audible output
-  virtual void beep(int type);
-  // --- global events
-  virtual void flush();
-  virtual int ready();
-  virtual void grab(Fl_Window* win);
-  // --- global colors
-  virtual void get_system_colors();
-  // --- global timers
-  virtual void add_timeout(double time, Fl_Timeout_Handler cb, void *argp);
-  virtual void repeat_timeout(double time, Fl_Timeout_Handler cb, void *argp);
-  virtual int has_timeout(Fl_Timeout_Handler cb, void *argp);
-  virtual void remove_timeout(Fl_Timeout_Handler cb, void *argp);
-};
-
-
-#endif // FL_PICO_SCREEN_DRIVER_H
diff --git src/drivers/Pico/Fl_Pico_Screen_Driver.cxx src/drivers/Pico/Fl_Pico_Screen_Driver.cxx
deleted file mode 100644
index 6156240..0000000
--- src/drivers/Pico/Fl_Pico_Screen_Driver.cxx
+++ /dev/null
@@ -1,132 +0,0 @@
-//
-// Definition of SDL Screen interface based on Pico
-//
-// Copyright 1998-2016 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-
-#include <config.h>
-#include "Fl_Pico_Screen_Driver.H"
-
-
-
-Fl_Pico_Screen_Driver::Fl_Pico_Screen_Driver()
-{
-}
-
-
-Fl_Pico_Screen_Driver::~Fl_Pico_Screen_Driver()
-{
-}
-
-
-void Fl_Pico_Screen_Driver::init()
-{
-  // nothing to do yet
-}
-
-
-int Fl_Pico_Screen_Driver::x()
-{
-  return 0;
-}
-
-
-int Fl_Pico_Screen_Driver::y()
-{
-  return 0;
-}
-
-
-int Fl_Pico_Screen_Driver::w()
-{
-  return 800;
-}
-
-
-int Fl_Pico_Screen_Driver::h()
-{
-  return 600;
-}
-
-
-void Fl_Pico_Screen_Driver::screen_xywh(int &X, int &Y, int &W, int &H, int n)
-{
-  X = x();
-  Y = y();
-  W = w();
-  H = h();
-}
-
-
-void Fl_Pico_Screen_Driver::screen_dpi(float &h, float &v, int n)
-{
-  h = 75.0;
-  v = 75.0;
-}
-
-
-void Fl_Pico_Screen_Driver::screen_work_area(int &X, int &Y, int &W, int &H, int n)
-{
-  X = x();
-  Y = y();
-  W = w();
-  H = h();
-}
-
-
-void Fl_Pico_Screen_Driver::beep(int type)
-{
-}
-
-
-void Fl_Pico_Screen_Driver::flush()
-{
-}
-
-
-int Fl_Pico_Screen_Driver::ready()
-{
-  return 1;
-}
-
-
-void Fl_Pico_Screen_Driver::grab(Fl_Window* win)
-{
-}
-
-
-void Fl_Pico_Screen_Driver::get_system_colors()
-{
-}
-
-
-void Fl_Pico_Screen_Driver::add_timeout(double time, Fl_Timeout_Handler cb, void *argp)
-{
-}
-
-
-void Fl_Pico_Screen_Driver::repeat_timeout(double time, Fl_Timeout_Handler cb, void *argp)
-{
-}
-
-
-int Fl_Pico_Screen_Driver::has_timeout(Fl_Timeout_Handler cb, void *argp)
-{
-  return 0;
-}
-
-
-void Fl_Pico_Screen_Driver::remove_timeout(Fl_Timeout_Handler cb, void *argp)
-{
-}
diff --git src/drivers/Pico/Fl_Pico_System_Driver.H src/drivers/Pico/Fl_Pico_System_Driver.H
deleted file mode 100644
index 5e3551b..0000000
--- src/drivers/Pico/Fl_Pico_System_Driver.H
+++ /dev/null
@@ -1,32 +0,0 @@
-//
-// Definition of Pico system driver
-// for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2016 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-#ifndef FL_PICO_SYSTEM_DRIVER_H
-#define FL_PICO_SYSTEM_DRIVER_H
-
-#include "../../Fl_System_Driver.H"
-
-class Fl_Pico_System_Driver : public Fl_System_Driver {
-public:
-  Fl_Pico_System_Driver() : Fl_System_Driver() {}
-  virtual void add_fd(int fd, int when, Fl_FD_Handler cb, void* = 0);
-  virtual void add_fd(int fd, Fl_FD_Handler cb, void* = 0);
-  virtual void remove_fd(int, int when);
-  virtual void remove_fd(int);
-};
-
-#endif /* FL_PICO_SYSTEM_DRIVER_H */
diff --git src/drivers/Pico/Fl_Pico_System_Driver.cxx src/drivers/Pico/Fl_Pico_System_Driver.cxx
deleted file mode 100644
index 1dfb262..0000000
--- src/drivers/Pico/Fl_Pico_System_Driver.cxx
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// Definition of Pico system driver
-// for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2016 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-#include "Fl_Pico_System_Driver.H"
-#include "../../flstring.h"
diff --git src/drivers/Pico/Fl_Pico_Window_Driver.H src/drivers/Pico/Fl_Pico_Window_Driver.H
deleted file mode 100644
index 9601852..0000000
--- src/drivers/Pico/Fl_Pico_Window_Driver.H
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// Definition of Pico Window interface
-// for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2016 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_Pico_Window_Driver.H
- \brief Definition of Pico Window interface.
- */
-
-#ifndef FL_PICO_WINDOW_DRIVER_H
-#define FL_PICO_WINDOW_DRIVER_H
-
-#include "../../Fl_Window_Driver.H"
-
-
-class FL_EXPORT Fl_Pico_Window_Driver : public Fl_Window_Driver
-{
-public:
-  Fl_Pico_Window_Driver(Fl_Window *win);
-  virtual ~Fl_Pico_Window_Driver();
-
-  // --- window data
-  virtual int decorated_w();
-  virtual int decorated_h();
-};
-
-
-#endif // FL_PICO_WINDOW_DRIVER_H
diff --git src/drivers/Pico/Fl_Pico_Window_Driver.cxx src/drivers/Pico/Fl_Pico_Window_Driver.cxx
deleted file mode 100644
index 7e8954c..0000000
--- src/drivers/Pico/Fl_Pico_Window_Driver.cxx
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-// Definition of SDL Window interface based on Pico
-//
-// Copyright 1998-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-
-#include <config.h>
-#include "Fl_Pico_Window_Driver.H"
-
-#include <FL/platform.H>
-#include <FL/Fl_Window.H>
-#include <FL/fl_draw.H>
-
-
-Fl_Pico_Window_Driver::Fl_Pico_Window_Driver(Fl_Window *win)
-: Fl_Window_Driver(win)
-{
-}
-
-
-Fl_Pico_Window_Driver::~Fl_Pico_Window_Driver()
-{
-}
-
-
-int Fl_Pico_Window_Driver::decorated_w()
-{
-  return w();
-}
-
-
-int Fl_Pico_Window_Driver::decorated_h()
-{
-  return h();
-}
diff --git src/drivers/PicoAndroid/Fl_PicoAndroid_Copy_Surface.cxx src/drivers/PicoAndroid/Fl_PicoAndroid_Copy_Surface.cxx
deleted file mode 100644
index 8b13789..0000000
--- src/drivers/PicoAndroid/Fl_PicoAndroid_Copy_Surface.cxx
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git src/drivers/PicoAndroid/Fl_PicoAndroid_Graphics_Driver.H src/drivers/PicoAndroid/Fl_PicoAndroid_Graphics_Driver.H
deleted file mode 100644
index 8c18fd3..0000000
--- src/drivers/PicoAndroid/Fl_PicoAndroid_Graphics_Driver.H
+++ /dev/null
@@ -1,119 +0,0 @@
-
-//
-// Definition of the Pico Android graphics driver
-// for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2016 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_PicoAndroid_Graphics_Driver.H
- \brief Definition of Pico minimal graphics driver.
- */
-
-#ifndef FL_PICOANDROID_GRAPHICS_DRIVER_H
-#define FL_PICOANDROID_GRAPHICS_DRIVER_H
-
-#include "../Pico/Fl_Pico_Graphics_Driver.H"
-
-
-/**
- \brief The Pico minimal SDL graphics class.
-
- This class is implemented as a base class for minimal core SDL drivers.
- */
-class Fl_PicoAndroid_Graphics_Driver : public Fl_Pico_Graphics_Driver {
-protected:
-  //  CGContextRef gc_;
-public:
-  //  virtual int has_feature(driver_feature mask) { return mask & NATIVE; }
-  //  virtual void gc(void *ctxt) {if (ctxt != gc_) global_gc(); gc_ = (CGContextRef)ctxt; }
-  //  virtual void *gc() {return gc_;}
-  //  char can_do_alpha_blending();
-  //
-  //  // --- bitmap stuff
-  //  Fl_Bitmask create_bitmask(int w, int h, const uchar *array);
-  //  void delete_bitmask(Fl_Bitmask bm);
-  //  void draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
-  //  void draw(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
-  //  void draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy);
-  //  void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0);
-  //  void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3);
-  //  void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0);
-  //  void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1);
-  //  void cache(Fl_Pixmap *img);
-  //  void cache(Fl_Bitmap *img);
-  //  void cache(Fl_RGB_Image *img);
-  //  void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_);
-  //  void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
-  //  void draw_CGImage(CGImageRef cgimg, int x, int y, int w, int h, int srcx, int srcy, int sw, int sh);
-  //protected:
-  //  // --- implementation is in src/fl_rect.cxx which includes src/cfg_gfx/quartz_rect.cxx
-  void point(int x, int y);
-  //  void rect(int x, int y, int w, int h);
-  void rectf(int x, int y, int w, int h);
-  void line(int x, int y, int x1, int y1);
-  //  void line(int x, int y, int x1, int y1, int x2, int y2);
-  //  void xyline(int x, int y, int x1);
-  //  void xyline(int x, int y, int x1, int y2);
-  //  void xyline(int x, int y, int x1, int y2, int x3);
-  //  void yxline(int x, int y, int y1);
-  //  void yxline(int x, int y, int y1, int x2);
-  //  void yxline(int x, int y, int y1, int x2, int y3);
-  //  void loop(int x0, int y0, int x1, int y1, int x2, int y2);
-  //  void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
-  //  void polygon(int x0, int y0, int x1, int y1, int x2, int y2);
-  //  void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
-  //  // --- clipping
-  //  void push_clip(int x, int y, int w, int h);
-  //  int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H);
-  //  int not_clipped(int x, int y, int w, int h);
-  //  void push_no_clip();
-  //  void pop_clip();
-  //  void restore_clip();
-  //  // --- implementation is in src/fl_vertex.cxx which includes src/cfg_gfx/xxx_rect.cxx
-  //  void begin_complex_polygon();
-  //  void transformed_vertex(double xf, double yf);
-  //  void vertex(double x, double y);
-  //  void end_points();
-  //  void end_line();
-  //  void end_loop();
-  //  void end_polygon();
-  //  void end_complex_polygon();
-  //  void gap();
-  //  void circle(double x, double y, double r);
-  //  // --- implementation is in src/fl_arc.cxx which includes src/cfg_gfx/xxx_arc.cxx if needed
-  //  // using void Fl_Graphics_Driver::arc(double x, double y, double r, double start, double end);
-  //  // --- implementation is in src/fl_arci.cxx which includes src/cfg_gfx/xxx_arci.cxx
-  //  void arc(int x, int y, int w, int h, double a1, double a2);
-  //  void pie(int x, int y, int w, int h, double a1, double a2);
-  //  // --- implementation is in src/fl_line_style.cxx which includes src/cfg_gfx/xxx_line_style.cxx
-  //  void line_style(int style, int width=0, char* dashes=0);
-  //  // --- implementation is in src/fl_color.cxx which includes src/cfg_gfx/xxx_color.cxx
-  //  void color(Fl_Color c);
-  //  Fl_Color color() { return color_; }
-  //  void color(uchar r, uchar g, uchar b);
-  //  // --- implementation is in src/fl_font.cxx which includes src/cfg_gfx/xxx_font.cxx
-  //  void draw(const char *str, int n, int x, int y);
-  //  void draw(const char *str, int n, float x, float y);
-  //  void draw(int angle, const char *str, int n, int x, int y);
-  //  void rtl_draw(const char *str, int n, int x, int y);
-  //  void font(Fl_Font face, Fl_Fontsize fsize);
-  //  double width(const char *str, int n);
-  //  double width(unsigned int c);
-  //  void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h);
-  //  int height();
-  //  int descent();
-};
-
-#endif // FL_PICOANDROID_GRAPHICS_DRIVER_H
diff --git src/drivers/PicoAndroid/Fl_PicoAndroid_Graphics_Driver.cxx src/drivers/PicoAndroid/Fl_PicoAndroid_Graphics_Driver.cxx
deleted file mode 100644
index 856c89d..0000000
--- src/drivers/PicoAndroid/Fl_PicoAndroid_Graphics_Driver.cxx
+++ /dev/null
@@ -1,97 +0,0 @@
-//
-// Rectangle drawing routines for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2016 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-
-#include <config.h>
-#include "Fl_PicoAndroid_Graphics_Driver.h"
-
-#include <jni.h>
-#include <errno.h>
-
-#include <EGL/egl.h>
-#include <GLES/gl.h>
-
-#include <android/log.h>
-#include <android_native_app_glue.h>
-
-#include <FL/Fl.H>
-
-#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
-
-
-/*
- By linking this module, the following static method will instantiate the
- PicoSDL Graphics driver as the main display driver.
- */
-Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver()
-{
-  return new Fl_PicoAndroid_Graphics_Driver();
-}
-
-
-void Fl_PicoAndroid_Graphics_Driver::rectf(int x, int y, int w, int h)
-{
-  GLfloat q3[] = {
-    x,     y,
-    x,     y+h-3,
-    x+w-3, y+h-3,
-    x+w-3, y
-  };
-
-  uchar r, g, b;
-  Fl::get_color(Fl_Graphics_Driver::color(), r, g, b);
-  glColor4ub(r, g, b, 255);
-
-  glEnableClientState(GL_VERTEX_ARRAY);
-  glVertexPointer(2, GL_FLOAT, 0, q3);
-  glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-  glDisableClientState(GL_VERTEX_ARRAY);
-}
-
-
-void Fl_PicoAndroid_Graphics_Driver::line(int x, int y, int x1, int y1)
-{
-  GLfloat q3[] = {
-    x,   y,
-    x1, y1
-  };
-
-  uchar r, g, b;
-  Fl::get_color(Fl_Graphics_Driver::color(), r, g, b);
-  glColor4ub(r, g, b, 255);
-
-  glEnableClientState(GL_VERTEX_ARRAY);
-  glVertexPointer(2, GL_FLOAT, 0, q3);
-  glDrawArrays(GL_LINES, 0, 2);
-  glDisableClientState(GL_VERTEX_ARRAY);
-}
-
-
-void Fl_PicoAndroid_Graphics_Driver::point(int x, int y)
-{
-  GLfloat q3[] = {
-    x, y
-  };
-
-  uchar r, g, b;
-  Fl::get_color(Fl_Graphics_Driver::color(), r, g, b);
-  glColor4ub(r, g, b, 255);
-
-  glEnableClientState(GL_VERTEX_ARRAY);
-  glVertexPointer(2, GL_FLOAT, 0, q3);
-  glDrawArrays(GL_POINTS, 0, 1);
-  glDisableClientState(GL_VERTEX_ARRAY);
-}
diff --git src/drivers/PicoAndroid/Fl_PicoAndroid_Image_Surface.cxx src/drivers/PicoAndroid/Fl_PicoAndroid_Image_Surface.cxx
deleted file mode 100644
index 8b13789..0000000
--- src/drivers/PicoAndroid/Fl_PicoAndroid_Image_Surface.cxx
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git src/drivers/PicoAndroid/Fl_PicoAndroid_Screen_Driver.H src/drivers/PicoAndroid/Fl_PicoAndroid_Screen_Driver.H
deleted file mode 100644
index 1163296..0000000
--- src/drivers/PicoAndroid/Fl_PicoAndroid_Screen_Driver.H
+++ /dev/null
@@ -1,73 +0,0 @@
-//
-// Definition of Android Screen interface based on Pico
-// for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2016 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_PicoAndroid_Screen_Driver.H
- \brief Definition of SDL Screen interface based on Pico.
- */
-
-#ifndef FL_PICOANDROID_SCREEN_DRIVER_H
-#define FL_PICOANDROID_SCREEN_DRIVER_H
-
-#include "../Pico/Fl_Pico_Screen_Driver.H"
-
-#include <jni.h>
-#include <errno.h>
-
-#include <EGL/egl.h>
-#include <GLES/gl.h>
-
-#include <android/sensor.h>
-#include <android/log.h>
-#include <android_native_app_glue.h>
-
-
-class Fl_PicoAndroid_Window_Driver;
-
-
-class FL_EXPORT Fl_PicoAndroid_Screen_Driver : public Fl_Pico_Screen_Driver
-{
-  friend class Fl_PicoAndroid_Window_Driver;
-
-  struct android_app* pApp;
-  EGLDisplay pDisplay;
-  EGLSurface pSurface;
-  EGLContext pContext;
-  int32_t pWidth;
-  int32_t pHeight;
-
-  static void handleAppCmdCB(struct android_app* app, int32_t cmd);
-  void handleAppCmd(struct android_app* app, int32_t cmd);
-  static int32_t handleInputEventCB(struct android_app* app, AInputEvent* event);
-  int32_t handleInputEvent(struct android_app* app, AInputEvent* event);
-  void initDisplay();
-  void termDisplay();
-
-public:
-  void drawFrame();
-
-public:
-  Fl_PicoAndroid_Screen_Driver();
-  virtual ~Fl_PicoAndroid_Screen_Driver();
-  virtual double wait(double time_to_wait);
-
-public:
-  void android_main(struct android_app* state);
-};
-
-
-#endif // FL_PICOANDROID_SCREEN_DRIVER_H
diff --git src/drivers/PicoAndroid/Fl_PicoAndroid_Screen_Driver.cxx src/drivers/PicoAndroid/Fl_PicoAndroid_Screen_Driver.cxx
deleted file mode 100644
index 5e96125..0000000
--- src/drivers/PicoAndroid/Fl_PicoAndroid_Screen_Driver.cxx
+++ /dev/null
@@ -1,562 +0,0 @@
-//
-// Definition of Android Screen interface based on Pico
-//
-// Copyright 1998-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-// http://developer.android.com/ndk/reference/group___native_activity.html
-
-
-#include <config.h>
-#include "Fl_PicoAndroid_Screen_Driver.H"
-
-#include <android/window.h>
-
-#include <FL/platform.H>
-#include <FL/Fl.H>
-#include <FL/Fl_Window.H>
-#include <FL/Fl_Double_Window.H>
-#include "../../Fl_Window_Driver.H"
-#include <FL/Fl_Image_Surface.H>
-#include <FL/Fl_Graphics_Driver.H>
-#include <FL/fl_draw.H>
-
-
-#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
-#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))
-
-
-
-void Fl_PicoAndroid_Screen_Driver::initDisplay()
-{
-  // initialize OpenGL ES and EGL
-
-  /*
-   * Here specify the attributes of the desired configuration.
-   * Below, we select an EGLConfig with at least 8 bits per color
-   * component compatible with on-screen windows
-   */
-  const EGLint attribs[] = {
-    EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
-    EGL_BLUE_SIZE, 8,
-    EGL_GREEN_SIZE, 8,
-    EGL_RED_SIZE, 8,
-    EGL_NONE
-  };
-  EGLint w, h, dummy, format;
-  EGLint numConfigs;
-  EGLConfig config;
-  EGLSurface surface;
-  EGLContext context;
-
-  EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-
-  eglInitialize(display, 0, 0);
-
-  /* Here, the application chooses the configuration it desires. In this
-   * sample, we have a very simplified selection process, where we pick
-   * the first EGLConfig that matches our criteria */
-  eglChooseConfig(display, attribs, &config, 1, &numConfigs);
-
-  /* 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. */
-  eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
-
-  ANativeWindow_setBuffersGeometry(pApp->window, 0, 0, format);
-
-  surface = eglCreateWindowSurface(display, config, pApp->window, NULL);
-  context = eglCreateContext(display, config, NULL, NULL);
-
-  if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
-    LOGW("Unable to eglMakeCurrent");
-    return;
-  }
-
-  eglQuerySurface(display, surface, EGL_WIDTH, &w);
-  eglQuerySurface(display, surface, EGL_HEIGHT, &h);
-
-  this->pDisplay = display;
-  pContext = context;
-  pSurface = surface;
-  pWidth = w;
-  pHeight = h;
-
-  // Initialize GL state.
-  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
-  glEnable(GL_CULL_FACE);
-  glShadeModel(GL_SMOOTH);
-  glDisable(GL_DEPTH_TEST);
-
-  glViewport(0, 100, w, h-200);
-
-  // make adjustments for screen ratio
-  float ratio = 3.0 * (float) w / h;
-  glMatrixMode(GL_PROJECTION);        // set matrix to projection mode
-  glLoadIdentity();                        // reset the matrix to its default state
-  // glFrustumf(-ratio, ratio, -3, 3, 3, 30);  // apply the projection matrix
-  glOrthof(0, w/3, h/3, 0, -30, 30);  // apply the projection matrix
-  glLineWidth(3);
-}
-
-
-void Fl_PicoAndroid_Screen_Driver::termDisplay()
-{
-  if (pDisplay != EGL_NO_DISPLAY) {
-    eglMakeCurrent(pDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-    if (pContext != EGL_NO_CONTEXT) {
-      eglDestroyContext(pDisplay, pContext);
-    }
-    if (pSurface != EGL_NO_SURFACE) {
-      eglDestroySurface(pDisplay, pSurface);
-    }
-    eglTerminate(pDisplay);
-  }
-  pDisplay = EGL_NO_DISPLAY;
-  pContext = EGL_NO_CONTEXT;
-  pSurface = EGL_NO_SURFACE;
-}
-
-
-void Fl_PicoAndroid_Screen_Driver::drawFrame()
-{
-  if (pDisplay == NULL) {
-    return;
-  }
-  eglSwapBuffers(pDisplay, pSurface);
-//  LOGI("Swapping buffers");
-}
-
-
-void Fl_PicoAndroid_Screen_Driver::handleAppCmdCB(struct android_app* app, int32_t cmd)
-{
-  Fl_PicoAndroid_Screen_Driver *This = (Fl_PicoAndroid_Screen_Driver*)(app->userData);
-  This->handleAppCmd(app, cmd);
-}
-
-
-void Fl_PicoAndroid_Screen_Driver::handleAppCmd(struct android_app* app, int32_t cmd)
-{
-  LOGI("CMD %d", cmd);
-//  struct engine* engine = (struct engine*)app->userData;
-  switch (cmd) {
-    case APP_CMD_SAVE_STATE:
-      // The system has asked us to save our current state.  Do so.
-//      engine->app->savedState = malloc(sizeof(struct saved_state));
-//      *((struct saved_state*)engine->app->savedState) = engine->state;
-//      engine->app->savedStateSize = sizeof(struct saved_state);
-      break;
-    case APP_CMD_INIT_WINDOW:
-      // The window is being shown, get it ready.
-      if (pApp->window != NULL) {
-        // the flag below allow for easy development and should be removed when
-        // distributing a final app
-        ANativeActivity_setWindowFlags(pApp->activity, AWINDOW_FLAG_KEEP_SCREEN_ON, 0);
-        initDisplay();
-        drawFrame();
-      }
-      break;
-    case APP_CMD_TERM_WINDOW:
-      // The window is being hidden or closed, clean it up.
-      termDisplay();
-      break;
-    case APP_CMD_GAINED_FOCUS:
-      // When our app gains focus, we start monitoring the accelerometer.
-//      if (engine->accelerometerSensor != NULL) {
-//        ASensorEventQueue_enableSensor(engine->sensorEventQueue,
-//                                       engine->accelerometerSensor);
-//        // We'd like to get 60 events per second (in us).
-//        ASensorEventQueue_setEventRate(engine->sensorEventQueue,
-//                                       engine->accelerometerSensor, (1000L/60)*1000);
-//      }
-      break;
-    case APP_CMD_LOST_FOCUS:
-      // When our app loses focus, we stop monitoring the accelerometer.
-      // This is to avoid consuming battery while not being used.
-//      if (engine->accelerometerSensor != NULL) {
-//        ASensorEventQueue_disableSensor(engine->sensorEventQueue,
-//                                        engine->accelerometerSensor);
-//      }
-//      // Also stop animating.
-//      engine->animating = 0;
-//      engine_draw_frame(engine);
-      break;
-  }
-}
-
-
-int32_t Fl_PicoAndroid_Screen_Driver::handleInputEventCB(struct android_app* app, AInputEvent* event)
-{
-  Fl_PicoAndroid_Screen_Driver *This = (Fl_PicoAndroid_Screen_Driver*)(app->userData);
-  This->handleInputEvent(app, event);
-}
-
-
-int32_t Fl_PicoAndroid_Screen_Driver::handleInputEvent(struct android_app* app, AInputEvent* event)
-{
-  if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
-//    fl_lock_function();
-    int x = AMotionEvent_getX(event, 0);
-    int y = AMotionEvent_getY(event, 0);
-    int action = AKeyEvent_getAction(event);
-    Fl_Window *window = Fl::first_window();
-    switch (action) {
-      case AMOTION_EVENT_ACTION_DOWN:
-        Fl::e_is_click = 1;
-        Fl::e_x = Fl::e_x_root = x/3;
-        Fl::e_y = Fl::e_y_root = (y-100)/3;
-        if (!window) break;
-        Fl::e_keysym = FL_Button+FL_LEFT_MOUSE;
-        Fl::e_state = FL_BUTTON1;
-        Fl::handle(FL_PUSH, window);
-        break;
-      case AMOTION_EVENT_ACTION_MOVE:
-        Fl::e_is_click = 1;
-        Fl::e_x = Fl::e_x_root = x/3;
-        Fl::e_y = Fl::e_y_root = (y-100)/3;
-        if (!window) break;
-        Fl::e_keysym = FL_Button+FL_LEFT_MOUSE;
-        Fl::e_state = FL_BUTTON1;
-        Fl::handle(FL_DRAG, window);
-        break;
-      case AMOTION_EVENT_ACTION_UP:
-      case AMOTION_EVENT_ACTION_CANCEL:
-        Fl::e_is_click = 1;
-        Fl::e_x = Fl::e_x_root = x/3;
-        Fl::e_y = Fl::e_y_root = (y-100)/3;
-        if (!window) break;
-        Fl::e_keysym = FL_Button+FL_LEFT_MOUSE;
-        Fl::e_state = 0;
-        Fl::handle(FL_RELEASE, window);
-        break;
-//      case AMOTION_EVENT_ACTION_HOVER_MOVE:
-//        Fl::e_is_click = 1;
-//        Fl::e_x = Fl::e_x_root = x/3;
-//        Fl::e_y = (y-100)/3;
-//        if (!window) break;
-//        Fl::e_keysym = 0;
-//        Fl::e_state = 0;
-//        Fl::handle(FL_MOVE, window);
-//        break;
-    }
-//    AMOTION_EVENT_ACTION_MASK
-//    LOGI("Motion at %d, %d", x, y);
-//    fl_unlock_function();
-    Fl_X::first->w->redraw();
-    return 1;
-  }
-  return 0;
-}
-
-
-extern int main(int argc, const char **argv);
-
-void android_main(struct android_app* state)
-{
-//  LOGI("Android Main call");
-  Fl_PicoAndroid_Screen_Driver *This = (Fl_PicoAndroid_Screen_Driver*)Fl::screen_driver();
-  This->android_main(state);
-  static const char *argv[1] = { "native-activity" };
-  main(1, argv);
-}
-
-/**
- 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 Fl_PicoAndroid_Screen_Driver::android_main(struct android_app* state)
-{
-  app_dummy();
-
-  pApp = state;
-  pApp->userData = this;
-  pApp->onAppCmd = handleAppCmdCB;
-  pApp->onInputEvent = handleInputEventCB;
-
-
-#if 0
-  struct engine engine;
-
-  // Make sure glue isn't stripped.
-  app_dummy();
-
-  memset(&engine, 0, sizeof(engine));
-  state->userData = &engine;
-  state->onAppCmd = engine_handle_cmd;
-  state->onInputEvent = engine_handle_input;
-  engine.app = state;
-
-  // Prepare to monitor accelerometer
-  engine.sensorManager = ASensorManager_getInstance();
-  engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
-                                                               ASENSOR_TYPE_ACCELEROMETER);
-  engine.sensorEventQueue = ASensorManager_createEventQueue(engine.sensorManager,
-                                                            state->looper, LOOPER_ID_USER, NULL, NULL);
-
-  if (state->savedState != NULL) {
-    // We are starting with a previous saved state; restore from it.
-    engine.state = *(struct saved_state*)state->savedState;
-  }
-
-  // loop waiting for stuff to do.
-
-  while (1) {
-    // Read all pending events.
-    int ident;
-    int events;
-    struct android_poll_source* source;
-
-    // If not animating, we will block forever waiting for events.
-    // If animating, we loop until all events are read, then continue
-    // to draw the next frame of animation.
-    while ((ident=ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events,
-                                  (void**)&source)) >= 0) {
-
-      // Process this event.
-      if (source != NULL) {
-        source->process(state, source);
-      }
-
-      // If a sensor has data, process it now.
-      if (ident == LOOPER_ID_USER) {
-        if (engine.accelerometerSensor != NULL) {
-          ASensorEvent event;
-          while (ASensorEventQueue_getEvents(engine.sensorEventQueue,
-                                             &event, 1) > 0) {
-            LOGI("accelerometer: x=%f y=%f z=%f",
-                 event.acceleration.x, event.acceleration.y,
-                 event.acceleration.z);
-          }
-        }
-      }
-
-      // Check if we are exiting.
-      if (state->destroyRequested != 0) {
-        engine_term_display(&engine);
-        return;
-      }
-    }
-
-    if (engine.animating) {
-      // Done with events; draw next animation frame.
-      engine.state.angle += .01f;
-      if (engine.state.angle > 1) {
-        engine.state.angle = 0;
-      }
-
-      // Drawing is throttled to the screen update rate, so there
-      // is no need to do timing here.
-      engine_draw_frame(&engine);
-    }
-  }
-#endif
-}
-
-
-Fl_Screen_Driver* Fl_Screen_Driver::newScreenDriver()
-{
-  return new Fl_PicoAndroid_Screen_Driver();
-}
-
-
-Fl_PicoAndroid_Screen_Driver::Fl_PicoAndroid_Screen_Driver()
-{
-  pDisplay = EGL_NO_DISPLAY;
-  pContext = EGL_NO_CONTEXT;
-  pSurface = EGL_NO_SURFACE;
-}
-
-Fl_PicoAndroid_Screen_Driver::~Fl_PicoAndroid_Screen_Driver()
-{
-}
-
-
-double Fl_PicoAndroid_Screen_Driver::wait(double time_to_wait)
-{
-  Fl::flush();
-    // Read all pending events.
-    int ident;
-    int events;
-    struct android_poll_source* source;
-
-    // If not animating, we will block forever waiting for events.
-    // If animating, we loop until all events are read, then continue
-    // to draw the next frame of animation.
-    // int ALooper_pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData)
-    if ((ident=ALooper_pollAll(0, NULL, &events, (void**)&source)) >= 0) {
-
-      // Process this event.
-      if (source != NULL) {
-        source->process(pApp, source);
-      }
-
-      // If a sensor has data, process it now.
-//      if (ident == LOOPER_ID_USER) {
-//        if (engine.accelerometerSensor != NULL) {
-//          ASensorEvent event;
-//          while (ASensorEventQueue_getEvents(engine.sensorEventQueue,
-//                                             &event, 1) > 0) {
-//            LOGI("accelerometer: x=%f y=%f z=%f",
-//                 event.acceleration.x, event.acceleration.y,
-//                 event.acceleration.z);
-//          }
-//        }
-//      }
-
-      // Check if we are exiting.
-//      if (state->destroyRequested != 0) {
-//        engine_term_display(&engine);
-//        return;
-//      }
-    }
-
-//    if (engine.animating) {
-//      // Done with events; draw next animation frame.
-//      engine.state.angle += .01f;
-//      if (engine.state.angle > 1) {
-//        engine.state.angle = 0;
-//      }
-//
-//      // Drawing is throttled to the screen update rate, so there
-//      // is no need to do timing here.
-//      engine_draw_frame(&engine);
-//    }
-//  }
-  return 0.0;
-}
-
-
-
-
-/*
- The following code should not be here!
- All this must be refactored into the driver system!
- */
-
-Fl_Fontdesc* fl_fonts = NULL;
-
-/*
-
- The following symbols are not found if we naively compile the core modules and
- no specific platform implementations. This list is a hint at all the functions
- and methods that probably need to be refactored into the driver system.
-
- Undefined symbols for architecture x86_64:
- */
-
-#if !defined(FL_DOXYGEN)        // *FIXME* silence Doxygen warnings
-
-void fl_set_spot(int, int, int, int, int, int, Fl_Window*) { }
-void fl_reset_spot() { }
-const char *fl_filename_name(char const*) { return 0; }
-
-//Fl_Screen_Driver *Fl_Screen_Driver::newScreenDriver() { return 0; }
-//Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver() { return 0; }
-//void Fl_Graphics_Driver::global_gc() { }
-int Fl::dnd() { return 0; }
-void Fl::copy(char const*, int, int, char const*) { }
-void Fl::paste(Fl_Widget&, int, char const*) { }
-void Fl::get_mouse(int&, int&) { }
-int Fl_X::set_cursor(Fl_Cursor) { return 0; }
-int Fl_X::set_cursor(Fl_RGB_Image const*, int, int) { return 0; }
-
-//void Fl_Window::size_range_() { }
-//void Fl_Window::fullscreen_x() { }
-
-void Fl_Window::make_current()
-{
-  fl_window = i->xid;
-  current_ = this;
-}
-
-//void Fl_Window::fullscreen_off_x(int, int, int, int) { }
-
-Window fl_xid(const Fl_Window* w)
-{
-  Fl_X *temp = Fl_X::i(w);
-  return temp ? temp->xid : 0;
-}
-
-void Fl_Window::show() {
-  if (!shown()) {
-    Fl_X::make(this);
-  }
-}
-
-Fl_X* Fl_X::make(Fl_Window *w)
-{
-  return w->driver()->makeWindow();
-}
-
-void Fl_Window::label(char const*, char const*) { }
-void Fl_Window::resize(int, int, int, int) { }
-Fl_Window *Fl_Window::current_;
-char fl_show_iconic;
-Window fl_window;
-//void Fl_Image_Surface::translate(int x, int y) { }
-//void Fl_Image_Surface::untranslate() { }
-
-void Fl::add_fd(int, int, Fl_FD_Handler, void*)
-{
-}
-
-void Fl::add_fd(int, Fl_FD_Handler, void*)
-{
-}
-
-void Fl::remove_fd(int)
-{
-}
-
-// these pointers are set by the Fl::lock() function:
-static void nothing() {}
-void (*fl_lock_function)() = nothing;
-void (*fl_unlock_function)() = nothing;
-
-Fl_Font_Descriptor::~Fl_Font_Descriptor()
-{
-}
-
-#endif // !defined(FL_DOXYGEN)
-
-#if 0
-
-ld: error: ./obj/local/armeabi-v7a/objs/native-activity/src/drivers/PicoAndroid/Fl_PicoAndroid_Screen_Driver.o: multiple definition of 'Fl_Window::make_current()'
-ld: ./obj/local/armeabi-v7a/objs/native-activity/src/Fl_Window.o: previous definition here
-
-ld: error: ./obj/local/armeabi-v7a/objs/native-activity/src/drivers/PicoAndroid/Fl_PicoAndroid_Screen_Driver.o: multiple definition of 'Fl_Window::current_'
-ld: ./obj/local/armeabi-v7a/objs/native-activity/src/Fl_Window.o: previous definition here
-
-ld: error: ./obj/local/armeabi-v7a/objs/native-activity/src/drivers/PicoAndroid/Fl_PicoAndroid_Screen_Driver.o: multiple definition of 'Fl_Window::show()'
-ld: ./obj/local/armeabi-v7a/objs/native-activity/src/Fl_Window.o: previous definition here
-
-ld: error: ./obj/local/armeabi-v7a/objs/native-activity/src/drivers/PicoAndroid/Fl_PicoAndroid_Screen_Driver.o: multiple definition of 'Fl_Window::label(char const*, char const*)'
-ld: ./obj/local/armeabi-v7a/objs/native-activity/src/Fl_Window.o: previous definition here
-
-ld: error: ./obj/local/armeabi-v7a/objs/native-activity/src/drivers/PicoAndroid/Fl_PicoAndroid_Screen_Driver.o: multiple definition of 'Fl_Window::resize(int, int, int, int)'
-ld: ./obj/local/armeabi-v7a/objs/native-activity/src/Fl_Window.o: previous definition here
-
-jni/../../src/Fl.cxx:1520: error: undefined reference to 'Fl_Graphics_Driver::add_rectangle_to_region(void*, int, int, int, int)'
-jni/../../src/Fl_Printer.cxx:115: error: undefined reference to 'Fl_Paged_Device::newPrinterDriver()'
-jni/../../src/Fl_Window.cxx:312: error: undefined reference to 'Fl_Window_Driver::default_icons(Fl_RGB_Image const**, int)'
-jni/../../src/fl_shortcut.cxx:330: error: undefined reference to 'fl_local_ctrl'
-jni/../../src/fl_shortcut.cxx:330: error: undefined reference to 'fl_local_alt'
-jni/../../src/fl_shortcut.cxx:330: error: undefined reference to 'fl_local_shift'
-jni/../../src/fl_shortcut.cxx:330: error: undefined reference to 'fl_local_meta'
-
-drivers/PicoAndroid/Fl_PicoAndroid_Window_Driver.o:Fl_PicoAndroid_Window_Driver.cxx:vtable for Fl_PicoAndroid_Window_Driver: error: undefined reference to 'Fl_PicoAndroid_Window_Driver::flush_double()'
-drivers/PicoAndroid/Fl_PicoAndroid_Window_Driver.o:Fl_PicoAndroid_Window_Driver.cxx:vtable for Fl_PicoAndroid_Window_Driver: error: undefined reference to 'Fl_PicoAndroid_Window_Driver::flush_overlay()'
-
-#endif
diff --git src/drivers/PicoAndroid/Fl_PicoAndroid_System_Driver.H src/drivers/PicoAndroid/Fl_PicoAndroid_System_Driver.H
deleted file mode 100644
index 8b13789..0000000
--- src/drivers/PicoAndroid/Fl_PicoAndroid_System_Driver.H
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git src/drivers/PicoAndroid/Fl_PicoAndroid_System_Driver.cxx src/drivers/PicoAndroid/Fl_PicoAndroid_System_Driver.cxx
deleted file mode 100644
index 8b13789..0000000
--- src/drivers/PicoAndroid/Fl_PicoAndroid_System_Driver.cxx
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git src/drivers/PicoAndroid/Fl_PicoAndroid_Window_Driver.H src/drivers/PicoAndroid/Fl_PicoAndroid_Window_Driver.H
deleted file mode 100644
index 813c2fb..0000000
--- src/drivers/PicoAndroid/Fl_PicoAndroid_Window_Driver.H
+++ /dev/null
@@ -1,55 +0,0 @@
-//
-// Definition of Android Window interface
-// for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2016 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_PicoAndroid_Window_Driver.H
- \brief Definition of SDL Window interface.
- */
-
-#ifndef FL_PICOANDROID_WINDOW_DRIVER_H
-#define FL_PICOANDROID_WINDOW_DRIVER_H
-
-#include "../Pico/Fl_Pico_Window_Driver.H"
-
-#include <jni.h>
-#include <android_native_app_glue.h>
-
-
-class FL_EXPORT Fl_PicoAndroid_Window_Driver : public Fl_Pico_Window_Driver
-{
-  ANativeWindow *pNativeWindow;
-public:
-  Fl_PicoAndroid_Window_Driver(Fl_Window *win);
-  virtual ~Fl_PicoAndroid_Window_Driver();
-
-  virtual Fl_X *makeWindow();
-
-  // --- window data
-//  virtual int decorated_w() = 0;
-//  virtual int decorated_h() = 0;
-
-  // --- window management
-//  virtual void take_focus();
-  virtual void flush();
-  virtual void flush_double();
-  virtual void flush_overlay();
-//  virtual void draw_begin();
-//  virtual void draw_end();
-};
-
-
-#endif // FL_PICOSDL_WINDOW_DRIVER_H
diff --git src/drivers/PicoAndroid/Fl_PicoAndroid_Window_Driver.cxx src/drivers/PicoAndroid/Fl_PicoAndroid_Window_Driver.cxx
deleted file mode 100644
index 67b8334..0000000
--- src/drivers/PicoAndroid/Fl_PicoAndroid_Window_Driver.cxx
+++ /dev/null
@@ -1,122 +0,0 @@
-//
-// Definition of Android Window interface based on SDL
-//
-// Copyright 1998-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-
-#include <config.h>
-#include "Fl_PicoAndroid_Window_Driver.H"
-
-#include "Fl_PicoAndroid_Screen_Driver.H"
-
-#include <jni.h>
-#include <errno.h>
-
-#include <android/sensor.h>
-#include <android/log.h>
-#include <android_native_app_glue.h>
-
-#include <FL/platform.H>
-#include <FL/Fl.H>
-#include <FL/Fl_Window.H>
-#include "../../Fl_Window_Driver.H"
-#include <FL/fl_draw.H>
-
-
-Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *win)
-{
-  return new Fl_PicoAndroid_Window_Driver(win);
-}
-
-
-Fl_PicoAndroid_Window_Driver::Fl_PicoAndroid_Window_Driver(Fl_Window *win)
-: Fl_Pico_Window_Driver(win)
-{
-}
-
-
-Fl_PicoAndroid_Window_Driver::~Fl_PicoAndroid_Window_Driver()
-{
-}
-
-
-Fl_X *Fl_PicoAndroid_Window_Driver::makeWindow()
-{
-  Fl_PicoAndroid_Screen_Driver *scr = (Fl_PicoAndroid_Screen_Driver*)Fl::screen_driver();
-
-  Fl_Group::current(0);
-  if (parent() && !Fl_X::i(pWindow->window())) {
-    pWindow->set_visible();
-    return 0L;
-  }
-  Window parent;
-  if (pWindow->parent()) {
-    parent = fl_xid(pWindow->window());
-  } else {
-    parent = 0;
-  }
-  Fl_X *x = new Fl_X;
-  other_xid = 0;
-  x->w = pWindow;
-  x->region = 0;
-  if (!pWindow->force_position()) {
-//    pNativeWindow = SDL_CreateWindow(pWindow->label(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w(), h(), 0);
-  } else {
-//    pNativeWindow = SDL_CreateWindow(pWindow->label(), x(), y(), w(), h(), 0);
-  }
-  pNativeWindow = scr->pApp->window;
-//  x->xid = SDL_CreateRenderer(pNativeWindow, -1, SDL_RENDERER_ACCELERATED);
-  x->next = Fl_X::first;
-  wait_for_expose_value = 0;
-  pWindow->i = x;
-  Fl_X::first = x;
-
-  pWindow->set_visible();
-  pWindow->redraw();
-  pWindow->flush();
-  int old_event = Fl::e_number;
-  pWindow->handle(Fl::e_number = FL_SHOW);
-  Fl::e_number = old_event;
-
-  return x;
-}
-
-
-void Fl_PicoAndroid_Window_Driver::flush()
-{
-  glClearColor(0, 0, 0, 1);
-  glClear(GL_COLOR_BUFFER_BIT);
-  Fl_X *i = Fl_X::i(pWindow);
-  if (!i) return;
-  fl_clip_region(i->region);
-  i->region = 0;
-  pWindow->draw();
-  Fl_PicoAndroid_Screen_Driver *scr = (Fl_PicoAndroid_Screen_Driver*)Fl::screen_driver();
-  scr->drawFrame();
-}
-
-
-#if 0
-void Fl_PicoAndroid_Window_Driver::flush()
-{
-  Fl_PicoAndroid_Screen_Driver *scr = (Fl_PicoAndroid_Screen_Driver*)Fl::screen_driver();
-//  LOGI("Flush...");
-  glClearColor(0, 0, 0, 1);
-  glClear(GL_COLOR_BUFFER_BIT);
-  pWindow->flush();
-//  fl_color(FL_RED);
-//  fl_rectf(10, 10, 300, 400);
-  scr->drawFrame();
-}
-#endif
diff --git src/drivers/PicoSDL/Fl_PicoSDL_Copy_Surface.cxx src/drivers/PicoSDL/Fl_PicoSDL_Copy_Surface.cxx
deleted file mode 100644
index 8b13789..0000000
--- src/drivers/PicoSDL/Fl_PicoSDL_Copy_Surface.cxx
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git src/drivers/PicoSDL/Fl_PicoSDL_Graphics_Driver.H src/drivers/PicoSDL/Fl_PicoSDL_Graphics_Driver.H
deleted file mode 100644
index eb89442..0000000
--- src/drivers/PicoSDL/Fl_PicoSDL_Graphics_Driver.H
+++ /dev/null
@@ -1,118 +0,0 @@
-
-//
-// Definition of the Pico minimal SDL graphics driver
-// for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2016 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_PicoSDL_Graphics_Driver.H
- \brief Definition of Pico minimal graphics driver.
- */
-
-#ifndef FL_PICOSDL_GRAPHICS_DRIVER_H
-#define FL_PICOSDL_GRAPHICS_DRIVER_H
-
-#include "../Pico/Fl_Pico_Graphics_Driver.H"
-
-
-/**
- \brief The Pico minimal SDL graphics class.
-
- This class is implemented as a base class for minimal core SDL drivers.
- */
-class Fl_PicoSDL_Graphics_Driver : public Fl_Pico_Graphics_Driver {
-protected:
-  //  CGContextRef gc_;
-public:
-  //  virtual int has_feature(driver_feature mask) { return mask & NATIVE; }
-  //  virtual void *gc() {return gc_;}
-  //  char can_do_alpha_blending();
-  //
-  //  // --- bitmap stuff
-  //  Fl_Bitmask create_bitmask(int w, int h, const uchar *array);
-  //  void delete_bitmask(Fl_Bitmask bm);
-  //  void draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
-  //  void draw(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
-  //  void draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy);
-  //  void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0);
-  //  void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3);
-  //  void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0);
-  //  void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1);
-  //  void cache(Fl_Pixmap *img);
-  //  void cache(Fl_Bitmap *img);
-  //  void cache(Fl_RGB_Image *img);
-  //  void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_);
-  //  void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
-  //  void draw_CGImage(CGImageRef cgimg, int x, int y, int w, int h, int srcx, int srcy, int sw, int sh);
-  //protected:
-  //  // --- implementation is in src/fl_rect.cxx which includes src/cfg_gfx/quartz_rect.cxx
-  void point(int x, int y);
-  //  void rect(int x, int y, int w, int h);
-  void rectf(int x, int y, int w, int h);
-  void line(int x, int y, int x1, int y1);
-  //  void line(int x, int y, int x1, int y1, int x2, int y2);
-  void xyline(int x, int y, int x1) { line(x, y, x1, y); }
-  //  void xyline(int x, int y, int x1, int y2);
-  //  void xyline(int x, int y, int x1, int y2, int x3);
-  void yxline(int x, int y, int y1) { line(x, y, x, y1); }
-  //  void yxline(int x, int y, int y1, int x2);
-  //  void yxline(int x, int y, int y1, int x2, int y3);
-  //  void loop(int x0, int y0, int x1, int y1, int x2, int y2);
-  //  void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
-  //  void polygon(int x0, int y0, int x1, int y1, int x2, int y2);
-  //  void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
-  //  // --- clipping
-  //  void push_clip(int x, int y, int w, int h);
-  //  int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H);
-  //  int not_clipped(int x, int y, int w, int h);
-  //  void push_no_clip();
-  //  void pop_clip();
-  //  void restore_clip();
-  //  // --- implementation is in src/fl_vertex.cxx which includes src/cfg_gfx/xxx_rect.cxx
-  //  void begin_complex_polygon();
-  //  void transformed_vertex(double xf, double yf);
-  //  void vertex(double x, double y);
-  //  void end_points();
-  //  void end_line();
-  //  void end_loop();
-  //  void end_polygon();
-  //  void end_complex_polygon();
-  //  void gap();
-  //  void circle(double x, double y, double r);
-  //  // --- implementation is in src/fl_arc.cxx which includes src/cfg_gfx/xxx_arc.cxx if needed
-  //  // using void Fl_Graphics_Driver::arc(double x, double y, double r, double start, double end);
-  //  // --- implementation is in src/fl_arci.cxx which includes src/cfg_gfx/xxx_arci.cxx
-  //  void arc(int x, int y, int w, int h, double a1, double a2);
-  //  void pie(int x, int y, int w, int h, double a1, double a2);
-  //  // --- implementation is in src/fl_line_style.cxx which includes src/cfg_gfx/xxx_line_style.cxx
-  //  void line_style(int style, int width=0, char* dashes=0);
-  //  // --- implementation is in src/fl_color.cxx which includes src/cfg_gfx/xxx_color.cxx
-  //  void color(Fl_Color c);
-  //  Fl_Color color() { return color_; }
-  //  void color(uchar r, uchar g, uchar b);
-  //  // --- implementation is in src/fl_font.cxx which includes src/cfg_gfx/xxx_font.cxx
-  //  void draw(const char *str, int n, int x, int y);
-  //  void draw(const char *str, int n, float x, float y);
-  //  void draw(int angle, const char *str, int n, int x, int y);
-  //  void rtl_draw(const char *str, int n, int x, int y);
-  //  void font(Fl_Font face, Fl_Fontsize fsize);
-  //  double width(const char *str, int n);
-  //  double width(unsigned int c);
-  //  void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h);
-  //  int height();
-  //  int descent();
-};
-
-#endif // FL_PICOSDL_GRAPHICS_DRIVER_H
diff --git src/drivers/PicoSDL/Fl_PicoSDL_Graphics_Driver.cxx src/drivers/PicoSDL/Fl_PicoSDL_Graphics_Driver.cxx
deleted file mode 100644
index 0257e1f..0000000
--- src/drivers/PicoSDL/Fl_PicoSDL_Graphics_Driver.cxx
+++ /dev/null
@@ -1,68 +0,0 @@
-//
-// Rectangle drawing routines for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-
-#include <config.h>
-#include "Fl_PicoSDL_Graphics_Driver.H"
-
-#include "Fl_PicoSDL_Screen_Driver.H"
-#include <FL/platform.H>
-#include "../../Fl_Window_Driver.H"
-
-#include <FL/Fl.H>
-#define __APPLE__
-#include <SDL2/SDL.h>
-#undef __APPLE__
-
-extern Window fl_window;
-
-
-/*
- By linking this module, the following static method will instantiate the
- PicoSDL Graphics driver as the main display driver.
- */
-Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver()
-{
-  return new Fl_PicoSDL_Graphics_Driver();
-}
-
-
-void Fl_PicoSDL_Graphics_Driver::rectf(int x, int y, int w, int h)
-{
-  uchar r, g, b;
-  Fl::get_color(Fl_Graphics_Driver::color(), r, g, b);
-  SDL_SetRenderDrawColor((SDL_Renderer*)fl_window, r, g, b, SDL_ALPHA_OPAQUE);
-  SDL_Rect rect = {x, y, w, h};
-  SDL_RenderFillRect((SDL_Renderer*)fl_window, &rect);
-}
-
-
-void Fl_PicoSDL_Graphics_Driver::line(int x, int y, int x1, int y1)
-{
-  uchar r, g, b;
-  Fl::get_color(Fl_Graphics_Driver::color(), r, g, b);
-  SDL_SetRenderDrawColor((SDL_Renderer*)fl_window, r, g, b, SDL_ALPHA_OPAQUE);
-  SDL_RenderDrawLine((SDL_Renderer*)fl_window, x, y, x1, y1);
-}
-
-
-void Fl_PicoSDL_Graphics_Driver::point(int x, int y)
-{
-  uchar r, g, b;
-  Fl::get_color(Fl_Graphics_Driver::color(), r, g, b);
-  SDL_SetRenderDrawColor((SDL_Renderer*)fl_window, r, g, b, SDL_ALPHA_OPAQUE);
-  SDL_RenderDrawPoint((SDL_Renderer*)fl_window, x, y);
-}
diff --git src/drivers/PicoSDL/Fl_PicoSDL_Image_Surface.cxx src/drivers/PicoSDL/Fl_PicoSDL_Image_Surface.cxx
deleted file mode 100644
index 8b13789..0000000
--- src/drivers/PicoSDL/Fl_PicoSDL_Image_Surface.cxx
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git src/drivers/PicoSDL/Fl_PicoSDL_Screen_Driver.H src/drivers/PicoSDL/Fl_PicoSDL_Screen_Driver.H
deleted file mode 100644
index 54b47a1..0000000
--- src/drivers/PicoSDL/Fl_PicoSDL_Screen_Driver.H
+++ /dev/null
@@ -1,38 +0,0 @@
-//
-// Definition of SDL Screen interface based on Pico
-// for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2016 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_PicoSDL_Screen_Driver.H
- \brief Definition of SDL Screen interface based on Pico.
- */
-
-#ifndef FL_PICOSDL_SCREEN_DRIVER_H
-#define FL_PICOSDL_SCREEN_DRIVER_H
-
-#include "../Pico/Fl_Pico_Screen_Driver.H"
-
-
-class FL_EXPORT Fl_PicoSDL_Screen_Driver : public Fl_Pico_Screen_Driver
-{
-public:
-  Fl_PicoSDL_Screen_Driver();
-  virtual ~Fl_PicoSDL_Screen_Driver();
-  virtual double wait(double time_to_wait);
-};
-
-
-#endif // FL_PICOSDL_SCREEN_DRIVER_H
diff --git src/drivers/PicoSDL/Fl_PicoSDL_Screen_Driver.cxx src/drivers/PicoSDL/Fl_PicoSDL_Screen_Driver.cxx
deleted file mode 100644
index 58759a7..0000000
--- src/drivers/PicoSDL/Fl_PicoSDL_Screen_Driver.cxx
+++ /dev/null
@@ -1,135 +0,0 @@
-//
-// Definition of SDL Screen interface based on Pico
-//
-// Copyright 1998-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-
-#include <config.h>
-#include "Fl_PicoSDL_Screen_Driver.H"
-
-#include <FL/platform.H>
-#include "../../Fl_Window_Driver.H"
-
-#define __APPLE__
-#include <SDL2/SDL.h>
-#undef __APPLE__
-
-
-// FIXME: does that have to be here?
-Window fl_window;
-
-
-Fl_Screen_Driver* Fl_Screen_Driver::newScreenDriver()
-{
-  return new Fl_PicoSDL_Screen_Driver();
-}
-
-
-Fl_PicoSDL_Screen_Driver::Fl_PicoSDL_Screen_Driver()
-{
-}
-
-
-Fl_PicoSDL_Screen_Driver::~Fl_PicoSDL_Screen_Driver()
-{
-}
-
-
-double Fl_PicoSDL_Screen_Driver::wait(double time_to_wait)
-{
-  Fl::flush();
-  SDL_Event e;
-  Fl_Window *window = Fl::first_window();
-  if (SDL_PollEvent(&e)) {
-    switch (e.type) {
-      case SDL_QUIT:
-        exit(0);
-      case SDL_WINDOWEVENT:
-        switch (e.window.event) {
-          case SDL_WINDOWEVENT_EXPOSED:
-          case SDL_WINDOWEVENT_SHOWN:
-          {
-            if ( !window ) break;;
-            Fl_Window_Driver *wd = window->driver();
-            Fl_X *i = Fl_X::i(Fl::first_window());
-            wd->wait_for_expose_value = 0;
-            if ( i->region ) {
-              fl_graphics_driver->XDestroyRegion(i->region);
-              i->region = 0;
-            }
-            window->clear_damage(FL_DAMAGE_ALL);
-            wd->flush();
-            window->clear_damage();
-            wd->wait_for_expose_value = 0;
-          }
-            break;
-        }
-      case SDL_MOUSEBUTTONDOWN:
-        if (!window) break;
-        Fl::e_is_click = e.button.clicks;
-        Fl::e_x = e.button.x;
-        Fl::e_y = e.button.y;
-        Fl::e_x_root = e.button.x + window->x();
-        Fl::e_y_root = e.button.y + window->y();
-        switch (e.button.button) {
-          case SDL_BUTTON_LEFT:   Fl::e_keysym = FL_Button+FL_LEFT_MOUSE;   Fl::e_state |= FL_BUTTON1; break;
-          case SDL_BUTTON_MIDDLE: Fl::e_keysym = FL_Button+FL_MIDDLE_MOUSE; Fl::e_state |= FL_BUTTON2; break;
-          case SDL_BUTTON_RIGHT:  Fl::e_keysym = FL_Button+FL_RIGHT_MOUSE;  Fl::e_state |= FL_BUTTON3; break;
-        }
-        Fl::handle(FL_PUSH, window);
-        break;
-      case SDL_MOUSEBUTTONUP:
-        if (!window) break;
-        Fl::e_is_click = e.button.clicks;
-        Fl::e_x = e.button.x;
-        Fl::e_y = e.button.y;
-        Fl::e_x_root = e.button.x + window->x();
-        Fl::e_y_root = e.button.y + window->y();
-        switch (e.button.button) {
-          case SDL_BUTTON_LEFT:   Fl::e_keysym = FL_Button+FL_LEFT_MOUSE;   Fl::e_state &= ~FL_BUTTON1; break;
-          case SDL_BUTTON_MIDDLE: Fl::e_keysym = FL_Button+FL_MIDDLE_MOUSE; Fl::e_state &= ~FL_BUTTON2; break;
-          case SDL_BUTTON_RIGHT:  Fl::e_keysym = FL_Button+FL_RIGHT_MOUSE;  Fl::e_state &= ~FL_BUTTON3; break;
-        }
-        Fl::handle(FL_RELEASE, window);
-        break;
-      case SDL_MOUSEMOTION: // SDL_BUTTON_LMASK
-        if (!window) break;
-        Fl::e_is_click = e.motion.state;
-        Fl::e_x = e.motion.x;
-        Fl::e_y = e.motion.y;
-        Fl::e_x_root = e.motion.x + window->x();
-        Fl::e_y_root = e.motion.y + window->y();
-        if (e.motion.state & SDL_BUTTON_LMASK) Fl::e_state |= FL_BUTTON1; else Fl::e_state &= ~FL_BUTTON1;
-        if (e.motion.state & SDL_BUTTON_MMASK) Fl::e_state |= FL_BUTTON2; else Fl::e_state &= ~FL_BUTTON2;
-        if (e.motion.state & SDL_BUTTON_RMASK) Fl::e_state |= FL_BUTTON3; else Fl::e_state &= ~FL_BUTTON3;
-        if ((e.motion.state & (SDL_BUTTON_LMASK|SDL_BUTTON_MMASK|SDL_BUTTON_RMASK)) == 0 )
-          Fl::handle(FL_MOVE, window);
-        else
-          Fl::handle(FL_DRAG, window);
-        break;
-      case SDL_MOUSEWHEEL:
-        break;
-      case SDL_KEYDOWN: // full keyboard support is a lot more complex
-      case SDL_KEYUP:
-        if (e.type==SDL_KEYDOWN) Fl::e_number = FL_KEYDOWN; else Fl::e_number = FL_KEYUP;
-        if (!window) break;
-        if (e.key.keysym.sym==SDLK_ESCAPE) {
-          Fl::e_keysym = FL_Escape;
-          Fl::handle(Fl::e_number, window);
-        }
-        break;
-    }
-  }
-  return 0.0;
-}
diff --git src/drivers/PicoSDL/Fl_PicoSDL_System_Driver.H src/drivers/PicoSDL/Fl_PicoSDL_System_Driver.H
deleted file mode 100644
index 8b13789..0000000
--- src/drivers/PicoSDL/Fl_PicoSDL_System_Driver.H
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git src/drivers/PicoSDL/Fl_PicoSDL_System_Driver.cxx src/drivers/PicoSDL/Fl_PicoSDL_System_Driver.cxx
deleted file mode 100644
index d6d60b3..0000000
--- src/drivers/PicoSDL/Fl_PicoSDL_System_Driver.cxx
+++ /dev/null
@@ -1,30 +0,0 @@
-//
-// System routines for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2016 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-
-#include <config.h>
-#include "../../Fl_System_Driver.H"
-//#include "Fl_PicoSDL_System_Driver.h"
-
-
-/*
- By linking this module, the following static method will instantiate the
- PicoSDL Graphics driver as the main display driver.
- */
-Fl_System_Driver *Fl_System_Driver::newSystemDriver()
-{
-  return new Fl_System_Driver();
-}
diff --git src/drivers/PicoSDL/Fl_PicoSDL_Window_Driver.H src/drivers/PicoSDL/Fl_PicoSDL_Window_Driver.H
deleted file mode 100644
index 8714285..0000000
--- src/drivers/PicoSDL/Fl_PicoSDL_Window_Driver.H
+++ /dev/null
@@ -1,51 +0,0 @@
-//
-// Definition of SDL Window interface
-// for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2016 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_PicoSDL_Window_Driver.H
- \brief Definition of SDL Window interface.
- */
-
-#ifndef FL_PICOSDL_WINDOW_DRIVER_H
-#define FL_PICOSDL_WINDOW_DRIVER_H
-
-#include "../Pico/Fl_Pico_Window_Driver.H"
-
-#define __APPLE__
-#include <SDL2/SDL.h>
-#undef __APPLE__
-
-
-class FL_EXPORT Fl_PicoSDL_Window_Driver : public Fl_Pico_Window_Driver
-{
-  SDL_Window *pNativeWindow;
-  SDL_Texture *pNativeTexture;
-public:
-  Fl_PicoSDL_Window_Driver(Fl_Window *win);
-  virtual ~Fl_PicoSDL_Window_Driver();
-
-  virtual void show();
-  virtual Fl_X *makeWindow();
-  virtual void make_current();
-  virtual void draw_end();
-
-  // --- window management
-//  virtual void flush();
-};
-
-
-#endif // FL_PICOSDL_WINDOW_DRIVER_H
diff --git src/drivers/PicoSDL/Fl_PicoSDL_Window_Driver.cxx src/drivers/PicoSDL/Fl_PicoSDL_Window_Driver.cxx
deleted file mode 100644
index f101437..0000000
--- src/drivers/PicoSDL/Fl_PicoSDL_Window_Driver.cxx
+++ /dev/null
@@ -1,104 +0,0 @@
-//
-// Definition of SDL Window interface based on SDL
-//
-// Copyright 1998-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
-//
-//     https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-//     https://www.fltk.org/bugs.php
-//
-
-
-#include <config.h>
-#include "Fl_PicoSDL_Window_Driver.H"
-
-#include <FL/platform.H>
-#include <FL/Fl.H>
-#include <FL/Fl_Window.H>
-
-
-Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *win)
-{
-  return new Fl_PicoSDL_Window_Driver(win);
-}
-
-
-Fl_PicoSDL_Window_Driver::Fl_PicoSDL_Window_Driver(Fl_Window *win)
-: Fl_Pico_Window_Driver(win)
-{
-}
-
-
-Fl_PicoSDL_Window_Driver::~Fl_PicoSDL_Window_Driver()
-{
-}
-
-
-Fl_X *Fl_PicoSDL_Window_Driver::makeWindow()
-{
-  Fl_Group::current(0);
-  if (parent() && !Fl_X::i(pWindow->window())) {
-    pWindow->set_visible();
-    return 0L;
-  }
-  Window parent;
-  if (this->parent()) {
-    parent = fl_xid(pWindow->window());
-  } else {
-    parent = 0;
-  }
-  Fl_X *x = new Fl_X;
-  other_xid = 0;
-  x->w = pWindow;
-  x->region = 0;
-  if (!pWindow->force_position()) {
-    pNativeWindow = SDL_CreateWindow(pWindow->label(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w(), h(), 0);
-  } else {
-    pNativeWindow = SDL_CreateWindow(pWindow->label(), pWindow->x(), pWindow->y(), pWindow->w(), pWindow->h(), 0);
-  }
-  x->xid = SDL_CreateRenderer(pNativeWindow, -1, SDL_RENDERER_ACCELERATED);
-  pNativeTexture = SDL_CreateTexture((SDL_Renderer*)x->xid, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_TARGET, w(), h());
-  x->next = Fl_X::first;
-  wait_for_expose_value = 0;
-  pWindow->i = x;
-  Fl_X::first = x;
-
-  pWindow->set_visible();
-  pWindow->redraw();
-  pWindow->flush();
-  int old_event = Fl::e_number;
-  pWindow->handle(Fl::e_number = FL_SHOW);
-  Fl::e_number = old_event;
-
-  return x;
-}
-
-
-void Fl_PicoSDL_Window_Driver::draw_end()
-{
-  Fl_X *i = Fl_X::i(pWindow);
-  SDL_SetRenderTarget((SDL_Renderer*)pWindow->i->xid, 0L);
-  //SDL_RenderClear((SDL_Renderer*)i->xid);
-  SDL_RenderCopy((SDL_Renderer*)i->xid, pNativeTexture, 0L, 0L);
-  SDL_RenderPresent((SDL_Renderer*)i->xid);
-}
-
-
-void Fl_PicoSDL_Window_Driver::make_current()
-{
-  fl_window = pWindow->i->xid;
-  SDL_SetRenderTarget((SDL_Renderer*)pWindow->i->xid, pNativeTexture);
-}
-
-
-void Fl_PicoSDL_Window_Driver::show() {
-  if (!shown()) {
-    makeWindow();
-  }
-}
diff --git test/CMakeLists.txt test/CMakeLists.txt
index 9169fc7..9197eba 100644
--- test/CMakeLists.txt
+++ test/CMakeLists.txt
@@ -56,34 +56,30 @@ include_directories(
 set (extra_tests)
 
 #######################################################################
-# Add the ANDROID_OK option if the example can be compiled for Android
-# as well as for other platforms.
 
-if (NOT ANDROID)
-
-CREATE_EXAMPLE (adjuster adjuster.cxx fltk ANDROID_OK)
-CREATE_EXAMPLE (arc arc.cxx fltk ANDROID_OK)
-CREATE_EXAMPLE (animated animated.cxx fltk ANDROID_OK)
-CREATE_EXAMPLE (ask ask.cxx fltk ANDROID_OK)
-CREATE_EXAMPLE (bitmap bitmap.cxx fltk ANDROID_OK)
+CREATE_EXAMPLE (adjuster adjuster.cxx fltk)
+CREATE_EXAMPLE (arc arc.cxx fltk)
+CREATE_EXAMPLE (animated animated.cxx fltk)
+CREATE_EXAMPLE (ask ask.cxx fltk)
+CREATE_EXAMPLE (bitmap bitmap.cxx fltk)
 CREATE_EXAMPLE (blocks "blocks.cxx;blocks.plist;blocks.icns" "fltk;${AUDIOLIBS}")
-CREATE_EXAMPLE (boxtype boxtype.cxx fltk ANDROID_OK)
-CREATE_EXAMPLE (browser browser.cxx fltk ANDROID_OK)
-CREATE_EXAMPLE (button button.cxx fltk ANDROID_OK)
-CREATE_EXAMPLE (buttons buttons.cxx fltk ANDROID_OK)
-CREATE_EXAMPLE (checkers "checkers.cxx;checkers_pieces.fl;checkers.icns" "fltk_images;fltk" ANDROID_OK)
+CREATE_EXAMPLE (boxtype boxtype.cxx fltk)
+CREATE_EXAMPLE (browser browser.cxx fltk)
+CREATE_EXAMPLE (button button.cxx fltk)
+CREATE_EXAMPLE (buttons buttons.cxx fltk)
+CREATE_EXAMPLE (checkers "checkers.cxx;checkers_pieces.fl;checkers.icns" "fltk_images;fltk")
 CREATE_EXAMPLE (clipboard clipboard.cxx "fltk_images;fltk")
-CREATE_EXAMPLE (clock clock.cxx fltk ANDROID_OK)
+CREATE_EXAMPLE (clock clock.cxx fltk)
 CREATE_EXAMPLE (colbrowser colbrowser.cxx fltk)
-CREATE_EXAMPLE (color_chooser color_chooser.cxx fltk ANDROID_OK)
+CREATE_EXAMPLE (color_chooser color_chooser.cxx fltk)
 CREATE_EXAMPLE (coordinates coordinates.cxx fltk)
-CREATE_EXAMPLE (cursor cursor.cxx fltk ANDROID_OK)
-CREATE_EXAMPLE (curve curve.cxx fltk ANDROID_OK)
+CREATE_EXAMPLE (cursor cursor.cxx fltk)
+CREATE_EXAMPLE (curve curve.cxx fltk)
 CREATE_EXAMPLE (demo demo.cxx fltk)
 CREATE_EXAMPLE (device device.cxx "fltk_images;fltk")
-CREATE_EXAMPLE (doublebuffer doublebuffer.cxx fltk ANDROID_OK)
-CREATE_EXAMPLE (editor "editor.cxx;editor.plist" fltk ANDROID_OK)
-CREATE_EXAMPLE (fast_slow fast_slow.fl fltk ANDROID_OK)
+CREATE_EXAMPLE (doublebuffer doublebuffer.cxx fltk)
+CREATE_EXAMPLE (editor "editor.cxx;editor.plist" fltk)
+CREATE_EXAMPLE (fast_slow fast_slow.fl fltk)
 CREATE_EXAMPLE (file_chooser file_chooser.cxx "fltk_images;fltk")
 CREATE_EXAMPLE (fltk-versions fltk-versions.cxx fltk)
 CREATE_EXAMPLE (fonts fonts.cxx fltk)
@@ -238,8 +234,6 @@ if (OPTION_BUILD_SHARED_LIBS)
 
 endif (OPTION_BUILD_SHARED_LIBS)
 
-endif (NOT ANDROID)
-
 #####################################################
 # We need some support files for the demo programs
 #####################################################
Direct Link to Message ]
 
     
Previous Message ]Next Message ]
 
 

Comments are owned by the poster. All other content is copyright 1998-2024 by Bill Spitzak and others. This project is hosted by The FLTK Team. Please report site problems to 'erco@seriss.com'.