Adding crude Android native screen driver

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12695 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Matthias Melcher 2018-03-02 16:34:43 +00:00
parent 9e29ea8a00
commit b19efed409
13 changed files with 9345 additions and 0 deletions

38
FL/android.H Normal file
View File

@ -0,0 +1,38 @@
//
// "$Id: android.H 12643 2018-01-31 22:49:52Z AlbrechtS $"
//
// 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:
//
// http://www.fltk.org/COPYING.php
//
// Please report all bugs and problems on the following page:
//
// http://www.fltk.org/str.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
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;
//
// End of "$Id: android.H 12643 2018-01-31 22:49:52Z AlbrechtS $".
//

View File

@ -45,6 +45,8 @@ class Fl_Window;
# elif defined(FL_PORTING)
# pragma message "FL_PORTING: write a header file based on this file, win32.H, or mac.H to define the FLTK core internals"
# include "porting.H"
# elif defined(__ANDROID__)
# include "android.H"
# else // X11
# include <FL/fl_types.h>
# include <FL/Enumerations.H>

View File

@ -0,0 +1,252 @@
//
// "$Id: Fl_Android_Graphics_Driver.H 12656 2018-02-09 16:59:34Z manolo $"
//
// Definition of classes Fl_Graphics_Driver, Fl_Surface_Device, Fl_Display_Device
// for the Fast Light Tool Kit (FLTK).
//
// Copyright 2010-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:
//
// http://www.fltk.org/COPYING.php
//
// Please report all bugs and problems on the following page:
//
// http://www.fltk.org/str.php
//
/**
\file Fl_GDI_Graphics_Driver.H
\brief Definition of Windows GDI graphics driver.
*/
#ifndef FL_GDI_GRAPHICS_DRIVER_H
#define FL_GDI_GRAPHICS_DRIVER_H
#include <FL/Fl_Graphics_Driver.H>
//#include <windows.h>
#include <limits.h>
#if 0
// clipping
// 1: rect
// Draw only the part of any element that fits inside the rect
// 2: region
// A rect that contains the entire region
// A sorted list of rows that contains fitting parts of the region
// A sorted list of rects for each row
class AFl_Rect
{
int pX1, pY1, pX2, pY2;
public:
const int int_max = INT_MAX;
const int int_min = INT_MIN;
AFl_Rect(int x1, y1, x2, y2) : pX1(x1), pY1(y1), pX2(x2), pY2(y2) { }
AFl_Rect() : pX1(int_min), pY1(int_min), pX2(int_max), pY2(int_max) { }
void x1(int x) { pX1 = x; }
void y1(int y) { pY1 = y; }
void x2(int x) { pX2 = x; }
void y2(int y) { pY2 = y; }
void w(int w) { pX2 = x1+w; }
void h(int h) { pY2 = y1+w; }
int x1() { return pX1; }
int y1() { return pY1; }
int x2() { return pX2; }
int y2() { return pY2; }
int w() { return pX2-pX1; }
int h() { return pY2-pY1; }
};
class AFl_Row
{
int nRect, NRect;
AFl_Rect *pRect;
AFl_rect pBounds;
public:
AFl_Row(int y1, int y2) : nRect(0), NRect(0), pRect(0), pY1(y1), pY2(y2) { }
~AFl_Row() { /* TODO: delete all rects */ }
void y1(int y) { pY1 = y; }
void y2(int y) { pY2 = y; }
AFl_Rect *first(int &i) { i=0; return (pRect && nRect>i) ? nRect[i] : 0L; }
AFl_Rect *next(int &i) { i++; return (pRect && nRect>i) ? nRect[i] : 0L; }
void add(AFl_Rect *r) { /* TODO: implement! */ }
void subtract(AFl_Rect *r) { /* TODO: implement! */ }
void clear() { /* TODO: implement! */ }
};
class AFl_Region
{
int nRow, NRow;
AFl_Row *pRow;
AFl_rect pBounds;
public:
AFl_Region() : nRow(0), NRow(0), pRow(0) { }
~AFl_Region() { /* TODO: delete all rows */ }
}
#endif
/**
\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_Scalable_Graphics_Driver {
#if 0
private:
BOOL alpha_blend_(int x, int y, int w, int h, HDC src_gc, int srcx, int srcy, int srcw, int srch);
int depth; // to support translation
POINT *origins; // to support translation
void set_current_();
protected:
HDC gc_;
int numcount;
int counts[20];
uchar **mask_bitmap_;
uchar **mask_bitmap() {return mask_bitmap_;}
void mask_bitmap(uchar **value) { mask_bitmap_ = value; }
int p_size;
POINT *p;
public:
Fl_GDI_Graphics_Driver() {mask_bitmap_ = NULL; gc_ = NULL; p_size = 0; p = NULL; depth = -1; origins = NULL;}
virtual ~Fl_GDI_Graphics_Driver() { if (p) free(p); delete[] origins;}
virtual int has_feature(driver_feature mask) { return mask & NATIVE; }
char can_do_alpha_blending();
virtual void gc(void *ctxt) { gc_ = (HDC)ctxt; global_gc(); }
virtual void *gc() {return gc_;}
// --- bitmap stuff
Fl_Bitmask create_bitmask(int w, int h, const uchar *array);
void delete_bitmask(Fl_Bitmask bm);
#endif
virtual void draw_unscaled(const char* str, int n, int x, int y);
#if 0
virtual void draw_unscaled(int angle, const char *str, int n, int x, int y);
virtual void rtl_draw_unscaled(const char* str, int n, int x, int y);
virtual void font_unscaled(Fl_Font face, Fl_Fontsize size);
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 *pxm, float s, int XP, int YP, int WP, int HP, int cx, int cy);
void draw_unscaled(Fl_RGB_Image *img, float s, int XP, int YP, int WP, int HP, int cx, int cy);
int draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP);
virtual void draw_image_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0);
virtual void draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3);
virtual void draw_image_mono_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0);
virtual void draw_image_mono_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1);
fl_uintptr_t cache(Fl_Pixmap *img, int w, int h, const char *const*array);
virtual void uncache_pixmap(fl_uintptr_t p);
fl_uintptr_t cache(Fl_Bitmap *img, int w, int h, const uchar *array);
void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_);
virtual double width_unscaled(const char *str, int n);
virtual double width_unscaled(unsigned int c);
void text_extents_unscaled(const char*, int n, int& dx, int& dy, int& w, int& h);
int height_unscaled();
int descent_unscaled();
Fl_Fontsize size_unscaled();
#if ! defined(FL_DOXYGEN)
void copy_offscreen_with_alpha(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy);
#endif
virtual void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
void add_rectangle_to_region(Fl_Region r, int x, int y, int w, int h);
Fl_Region XRectangleRegion(int x, int y, int w, int h);
void XDestroyRegion(Fl_Region r);
void translate_all(int x, int y);
void untranslate_all(void);
static HRGN scale_region(HRGN r, float f, Fl_GDI_Graphics_Driver *dr);
virtual void scale(float f);
protected:
void transformed_vertex0(float x, float y);
void fixloop();
// --- implementation is in src/fl_rect.cxx which includes src/cfg_gfx/gdi_rect.cxx
virtual void point_unscaled(float x, float y);
void rect_unscaled(float x, float y, float w, float h);
void focus_rect(int x, int y, int w, int h);
#endif
void rectf_unscaled(float x, float y, float w, float h);
#if 0
virtual void line_unscaled(float x, float y, float x1, float y1);
virtual void line_unscaled(float x, float y, float x1, float y1, float x2, float y2);
#endif
virtual void xyline_unscaled(float x, float y, float x1);
virtual void yxline_unscaled(float x, float y, float y1);
#if 0
virtual void loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2);
virtual void loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2);
virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float 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();
virtual Fl_Region scale_clip(float f);
// --- implementation is in src/fl_vertex.cxx which includes src/cfg_gfx/xxx_rect.cxx
void begin_complex_polygon();
void end_points();
void end_line();
void end_loop();
void end_polygon();
void end_complex_polygon();
void gap();
virtual void ellipse_unscaled(double xt, double yt, double rx, double ry);
// --- 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
virtual void arc_unscaled(float x, float y, float w, float h, double a1, double a2);
virtual void pie_unscaled(float x, float y, float w, float h, double a1, double a2);
// --- implementation is in src/fl_line_style.cxx which includes src/cfg_gfx/xxx_line_style.cxx
virtual void line_style_unscaled(int style, float width, char* dashes);
// --- implementation is in src/fl_color.cxx which includes src/cfg_gfx/xxx_color.cxx
void color(Fl_Color c);
void color(uchar r, uchar g, uchar b);
Fl_Color color() { return color_; }
void set_color(Fl_Color i, unsigned int c);
void free_color(Fl_Color i, int overlay);
void set_spot(int font, int size, int X, int Y, int W, int H, Fl_Window *win);
void reset_spot();
virtual Fl_Font set_fonts(const char *name);
virtual int get_font_sizes(Fl_Font fnum, int*& sizep);
virtual const char* get_font_name(Fl_Font fnum, int* ap);
virtual const char *font_name(int num);
virtual void font_name(int num, const char *name);
void global_gc();
virtual void overlay_rect(int x, int y, int w , int h);
#endif
};
/**
The graphics driver used when printing on Windows.
This class is implemented only on the Windows platform.
It is extremely similar to Fl_GDI_Graphics_Driver.
*/
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);
int draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP);
#endif
};
#endif // FL_GDI_GRAPHICS_DRIVER_H
//
// End of "$Id: Fl_Android_Graphics_Driver.H 12656 2018-02-09 16:59:34Z manolo $".
//

View File

@ -0,0 +1,492 @@
//
// "$Id: Fl_Android_Graphics_Driver.cxx 12655 2018-02-09 14:39:42Z AlbrechtS $"
//
// 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:
//
// http://www.fltk.org/COPYING.php
//
// Please report all bugs and problems on the following page:
//
// http://www.fltk.org/str.php
//
#include "../../config_lib.h"
#include "Fl_Android_Graphics_Driver.h"
#include <FL/Fl.H>
#include <FL/platform.H>
#include <errno.h>
#include "Fl_Android_Screen_Driver.H"
#include <android/log.h>
extern ANativeWindow_Buffer* gAGraphicsBuffer;
#define LOG_TAG "libplasma"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
/*
* 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();
}
static uint16_t make565(int red, int green, int blue)
{
return (uint16_t)( ((red << 8) & 0xf800) |
((green << 3) & 0x07e0) |
((blue >> 3) & 0x001f) );
}
extern unsigned fl_cmap[256];
static uint16_t 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_unscaled(float x, float y, float w, float h) {
if (w<=0 || h<=0) return;
// TODO: clip the rectangle to the window outline
// TODO: clip the rectangle to all parts of the window region
// TODo: clip the rectangle to all parts of the current clipping region
uint16_t cc = make565(color());
uint32_t ss = gAGraphicsBuffer->stride;
uint16_t *bits = (uint16_t*)gAGraphicsBuffer->bits;
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 = yy; iy<hh; ++iy) {
uint16_t *d = bits + iy*ss + xx;
for (uint32_t ix = ww; ix>0; --ix) {
*d++ = cc;
}
}
}
void Fl_Android_Graphics_Driver::xyline_unscaled(float x, float y, float x1)
{
uint16_t cc = make565(color());
float w;
if (x1>x) {
w = x1-x;
} else {
w = x-x1;
x = x1;
}
uint32_t ss = gAGraphicsBuffer->stride;
uint16_t *bits = (uint16_t*)gAGraphicsBuffer->bits;
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;
for (uint32_t ix = ww; ix>0; --ix) {
*d++ = cc;
}
}
void Fl_Android_Graphics_Driver::yxline_unscaled(float x, float y, float y1)
{
uint16_t cc = make565(color());
float h;
if (y1>y) {
h = y1-y;
} else {
h = y-y1;
y = y1;
}
uint32_t ss = gAGraphicsBuffer->stride;
uint16_t *bits = (uint16_t*)gAGraphicsBuffer->bits;
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;
for (uint32_t iy = hh; iy>0; --iy) {
*d = cc;
d += ss;
}
}
// -- fun with text rendering
#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
#include "stb_truetype.h"
unsigned char ttf_buffer[1<<25];
static int render_letter(int xx, int yy, uint32_t c)
{
static bool once = 0;
static stbtt_fontinfo font;
unsigned char *bitmap;
int w,h,i,j, size = 30;
int dx, dy;
LOGE("Render letter %c", c);
if (once==0) {
once = 1;
FILE *f = fopen("/system/fonts/DroidSans.ttf", "rb");
if (f==NULL) {
LOGE("ERROR reading font %d!", errno);
return 0;
}
fread(ttf_buffer, 1, 1<<25, f);
stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));
}
#if 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;
}
#endif
bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, size), c, &w, &h, &dx, &dy);
// rrrr.rggg.gggb.bbbb
xx += dx; yy += dy;
uint16_t cc = make565(fl_color()), cc12 = (cc&0xf7de)>>1, cc14 = (cc12&0xf7de)>>1, cc34 = cc12+cc14;
uint32_t ss = gAGraphicsBuffer->stride;
uint16_t *bits = (uint16_t*)gAGraphicsBuffer->bits;
uint32_t ww = w;
uint32_t hh = h;
unsigned char *s = bitmap;
for (uint32_t iy = 0; iy<hh; ++iy) {
uint16_t *d = bits + (yy+iy)*ss + xx;
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&0xe79c)>>2;
*d = nn14 + cc34;
} else if (v<100) { // 25%
uint16_t nn = *d, nn12 = (nn&0xf7de)>>1, nn14 = (nn12&0xf7de)>>1, nn34 = nn12+nn14;
*d = nn34 + cc14;
} else { // 50%
uint16_t nn = *d, nn12 = (nn&0xf7de)>>1;
*d = nn12 + cc12;
}
#else
// pure black and white
if (*s++ > 128)
*d = cc;
#endif
d++;
}
}
stbtt_FreeBitmap(bitmap, 0L);
int advance,lsb;
stbtt_GetCodepointHMetrics(&font, c, &advance, &lsb);
float scale = stbtt_ScaleForPixelHeight(&font, size);
return xx+advance*scale;
}
void Fl_Android_Graphics_Driver::draw_unscaled(const char* str, int n, int x, int y)
{
if (str) {
x = x+16*(-n/2);
for (int i=0; i<n; i++)
x = render_letter(x, y+5, str[i]);
}
}
#if 0
// Code used to switch output to an off-screen window. See macros in
// win32.H which save the old state in local variables.
typedef struct { BYTE a; BYTE b; BYTE c; BYTE d; } FL_BLENDFUNCTION;
typedef BOOL (WINAPI* fl_alpha_blend_func)
(HDC,int,int,int,int,HDC,int,int,int,int,FL_BLENDFUNCTION);
static fl_alpha_blend_func fl_alpha_blend = NULL;
static FL_BLENDFUNCTION blendfunc = { 0, 0, 255, 1};
/* Reference to the current device context
For back-compatibility only. The preferred procedure to get this reference is
Fl_Surface_Device::surface()->driver()->gc().
*/
HDC fl_gc = 0;
void Fl_GDI_Graphics_Driver::global_gc()
{
fl_gc = (HDC)gc();
}
/*
* This function checks if the version of Windows that we
* curently run on supports alpha blending for bitmap transfers
* and finds the required function if so.
*/
char Fl_GDI_Graphics_Driver::can_do_alpha_blending() {
static char been_here = 0;
static char can_do = 0;
// do this test only once
if (been_here) return can_do;
been_here = 1;
// load the library that implements alpha blending
HMODULE hMod = LoadLibrary("MSIMG32.DLL");
// give up if that doesn't exist (Win95?)
if (!hMod) return 0;
// now find the blending function inside that dll
fl_alpha_blend = (fl_alpha_blend_func)GetProcAddress(hMod, "AlphaBlend");
// give up if we can't find it (Win95)
if (!fl_alpha_blend) return 0;
// we have the call, but does our display support alpha blending?
// get the desktop's device context
HDC dc = GetDC(0L);
if (!dc) return 0;
// check the device capabilities flags. However GetDeviceCaps
// does not return anything useful, so we have to do it manually:
HBITMAP bm = CreateCompatibleBitmap(dc, 1, 1);
HDC new_gc = CreateCompatibleDC(dc);
int save = SaveDC(new_gc);
SelectObject(new_gc, bm);
/*COLORREF set = */ SetPixel(new_gc, 0, 0, 0x01010101);
BOOL alpha_ok = fl_alpha_blend(dc, 0, 0, 1, 1, new_gc, 0, 0, 1, 1, blendfunc);
RestoreDC(new_gc, save);
DeleteDC(new_gc);
DeleteObject(bm);
ReleaseDC(0L, dc);
if (alpha_ok) can_do = 1;
return can_do;
}
HDC fl_makeDC(HBITMAP bitmap) {
HDC new_gc = CreateCompatibleDC((HDC)Fl_Graphics_Driver::default_driver().gc());
SetTextAlign(new_gc, TA_BASELINE|TA_LEFT);
SetBkMode(new_gc, TRANSPARENT);
#if USE_COLORMAP
if (fl_palette) SelectPalette(new_gc, fl_palette, FALSE);
#endif
SelectObject(new_gc, bitmap);
return new_gc;
}
void Fl_GDI_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen bitmap, int srcx, int srcy) {
HDC new_gc = CreateCompatibleDC(gc_);
int save = SaveDC(new_gc);
SelectObject(new_gc, bitmap);
BitBlt(gc_, x*scale_, y*scale_, w*scale_, h*scale_, new_gc, srcx*scale_, srcy*scale_, SRCCOPY);
RestoreDC(new_gc, save);
DeleteDC(new_gc);
}
BOOL Fl_GDI_Graphics_Driver::alpha_blend_(int x, int y, int w, int h, HDC src_gc, int srcx, int srcy, int srcw, int srch) {
return fl_alpha_blend(gc_, x, y, w, h, src_gc, srcx, srcy, srcw, srch, blendfunc);
}
#if ! defined(FL_DOXYGEN)
void Fl_GDI_Graphics_Driver::copy_offscreen_with_alpha(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy) {
HDC new_gc = CreateCompatibleDC(gc_);
int save = SaveDC(new_gc);
SelectObject(new_gc, bitmap);
BOOL alpha_ok = 0;
// first try to alpha blend
if ( can_do_alpha_blending() ) {
alpha_ok = alpha_blend_(x, y, w, h, new_gc, srcx, srcy, w, h);
}
// if that failed (it shouldn't), still copy the bitmap over, but now alpha is 1
if (!alpha_ok) {
BitBlt(gc_, x, y, w, h, new_gc, srcx, srcy, SRCCOPY);
}
RestoreDC(new_gc, save);
DeleteDC(new_gc);
}
void Fl_GDI_Graphics_Driver::translate_all(int x, int y) {
const int stack_height = 10;
if (depth == -1) {
origins = new POINT[stack_height];
depth = 0;
}
if (depth >= stack_height) {
Fl::warning("Fl_Copy/Image_Surface: translate stack overflow!");
depth = stack_height - 1;
}
GetWindowOrgEx((HDC)gc(), origins+depth);
SetWindowOrgEx((HDC)gc(), origins[depth].x - x*scale_, origins[depth].y - y*scale_, NULL);
depth++;
}
void Fl_GDI_Graphics_Driver::untranslate_all() {
if (depth > 0) depth--;
SetWindowOrgEx((HDC)gc(), origins[depth].x, origins[depth].y, NULL);
}
#endif
void Fl_GDI_Graphics_Driver::add_rectangle_to_region(Fl_Region r, int X, int Y, int W, int H) {
Fl_Region R = XRectangleRegion(X, Y, W, H);
CombineRgn(r, r, R, RGN_OR);
XDestroyRegion(R);
}
void Fl_GDI_Graphics_Driver::transformed_vertex0(float x, float y) {
if (!n || x != p[n-1].x || y != p[n-1].y) {
if (n >= p_size) {
p_size = p ? 2*p_size : 16;
p = (POINT*)realloc((void*)p, p_size*sizeof(*p));
}
p[n].x = x;
p[n].y = y;
n++;
}
}
void Fl_GDI_Graphics_Driver::fixloop() { // remove equal points from closed path
while (n>2 && p[n-1].x == p[0].x && p[n-1].y == p[0].y) n--;
}
Fl_Region Fl_GDI_Graphics_Driver::XRectangleRegion(int x, int y, int w, int h) {
if (Fl_Surface_Device::surface() == Fl_Display_Device::display_device()) return CreateRectRgn(x,y,x+w,y+h);
// because rotation may apply, the rectangle becomes a polygon in device coords
POINT pt[4] = { {x, y}, {x + w, y}, {x + w, y + h}, {x, y + h} };
LPtoDP((HDC)fl_graphics_driver->gc(), pt, 4);
return CreatePolygonRgn(pt, 4, ALTERNATE);
}
void Fl_GDI_Graphics_Driver::XDestroyRegion(Fl_Region r) {
DeleteObject(r);
}
typedef BOOL(WINAPI* flTypeImmAssociateContextEx)(HWND, HIMC, DWORD);
extern flTypeImmAssociateContextEx flImmAssociateContextEx;
typedef HIMC(WINAPI* flTypeImmGetContext)(HWND);
extern flTypeImmGetContext flImmGetContext;
typedef BOOL(WINAPI* flTypeImmSetCompositionWindow)(HIMC, LPCOMPOSITIONFORM);
extern flTypeImmSetCompositionWindow flImmSetCompositionWindow;
typedef BOOL(WINAPI* flTypeImmReleaseContext)(HWND, HIMC);
extern flTypeImmReleaseContext flImmReleaseContext;
void Fl_GDI_Graphics_Driver::reset_spot()
{
}
void Fl_GDI_Graphics_Driver::set_spot(int font, int size, int X, int Y, int W, int H, Fl_Window *win)
{
if (!win) return;
Fl_Window* tw = win;
while (tw->parent()) tw = tw->window(); // find top level window
if (!tw->shown())
return;
HIMC himc = flImmGetContext(fl_xid(tw));
if (himc) {
COMPOSITIONFORM cfs;
cfs.dwStyle = CFS_POINT;
cfs.ptCurrentPos.x = X;
cfs.ptCurrentPos.y = Y - tw->labelsize();
MapWindowPoints(fl_xid(win), fl_xid(tw), &cfs.ptCurrentPos, 1);
flImmSetCompositionWindow(himc, &cfs);
flImmReleaseContext(fl_xid(tw), himc);
}
}
void Fl_GDI_Graphics_Driver::scale(float f) {
if (f != scale_) {
size_ = 0;
scale_ = f;
//fprintf(LOG,"set scale to %f\n",f);fflush(LOG);
}
}
/* Rescale region r with factor f and returns the scaled region.
Region r is returned unchanged if r is null or f is 1.
The input region is deleted if dr is null.
*/
HRGN Fl_GDI_Graphics_Driver::scale_region(HRGN r, float f, Fl_GDI_Graphics_Driver *dr) {
if (r && f != 1) {
DWORD size = GetRegionData(r, 0, NULL);
RGNDATA *pdata = (RGNDATA*)malloc(size);
GetRegionData(r, size, pdata);
if (!dr) DeleteObject(r);
POINT pt = {0, 0};
if (dr && dr->depth >= 1) { // account for translation
GetWindowOrgEx((HDC)dr->gc(), &pt);
pt.x *= (f - 1);
pt.y *= (f - 1);
}
RECT *rects = (RECT*)&(pdata->Buffer);
int delta = (f > 1.75 ? 1 : 0) - int(f/2);
for (DWORD i = 0; i < pdata->rdh.nCount; i++) {
int x = rects[i].left * f + pt.x;
int y = rects[i].top * f + pt.y;
RECT R2;
R2.left = x + delta;
R2.top = y + delta;
R2.right = int(rects[i].right * f) + pt.x - x + R2.left;
R2.bottom = int(rects[i].bottom * f) + pt.y - y + R2.top;
rects[i] = R2;
}
r = ExtCreateRegion(NULL, size, pdata);
free(pdata);
}
return r;
}
Fl_Region Fl_GDI_Graphics_Driver::scale_clip(float f) {
HRGN r = rstack[rstackptr];
HRGN r2 = scale_region(r, f, this);
return (r == r2 ? NULL : (rstack[rstackptr] = r2, r));
}
void Fl_GDI_Graphics_Driver::set_current_() {
restore_clip();
}
#endif
//
// End of "$Id: Fl_Android_Graphics_Driver.cxx 12655 2018-02-09 14:39:42Z AlbrechtS $".
//

View File

@ -0,0 +1,121 @@
//
// "$Id: Fl_Android_Image_Surface_Driver.cxx 12653 2018-02-09 13:48:22Z manolo $"
//
// Draw-to-image code 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:
//
// http://www.fltk.org/COPYING.php
//
// Please report all bugs and problems on the following page:
//
// http://www.fltk.org/str.php
//
#include "../../config_lib.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();
void set_current();
void translate(int x, int y);
void untranslate();
Fl_RGB_Image *image();
POINT origin;
#endif
};
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
//
// End of "$Id: Fl_Android_Image_Surface_Driver.cxx 12653 2018-02-09 13:48:22Z manolo $".
//

View File

@ -0,0 +1,477 @@
//
// "$Id: Fl_Android_Screen_Driver.H 12655 2018-02-09 14:39:42Z AlbrechtS $"
//
// Definition of Windows screen interface
// for the Fast Light Tool Kit (FLTK).
//
// Copyright 2010-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:
//
// http://www.fltk.org/COPYING.php
//
// Please report all bugs and problems on the following page:
//
// http://www.fltk.org/str.php
//
/**
\file Fl_WinAPI_Screen_Driver.H
\brief Definition of Windows screen interface.
*/
#ifndef FL_WINAPI_SCREEN_DRIVER_H
#define FL_WINAPI_SCREEN_DRIVER_H
#include <FL/Fl_Screen_Driver.H>
//#include <windows.h>
class Fl_Window;
class FL_EXPORT Fl_Android_Screen_Driver : public Fl_Screen_Driver
{
#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
public:
Fl_Android_Screen_Driver() : Fl_Screen_Driver() { }
#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();
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);
int screen_num_unscaled(int x, int y);
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 double wait(double time_to_wait);
virtual int ready();
virtual void grab(Fl_Window* win);
// --- global colors
virtual void get_system_colors();
virtual const char *get_system_scheme();
// --- 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);
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);
virtual int get_mouse(int &x, int &y);
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
};
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef _ANDROID_NATIVE_APP_GLUE_H
#define _ANDROID_NATIVE_APP_GLUE_H
#include <poll.h>
#include <pthread.h>
#include <sched.h>
#include <android/configuration.h>
#include <android/looper.h>
#include <android/native_activity.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* The native activity interface provided by <android/native_activity.h>
* is based on a set of application-provided callbacks that will be called
* by the Activity's main thread when certain events occur.
*
* This means that each one of this callbacks _should_ _not_ block, or they
* risk having the system force-close the application. This programming
* model is direct, lightweight, but constraining.
*
* The 'android_native_app_glue' static library is used to provide a different
* execution model where the application can implement its own main event
* loop in a different thread instead. Here's how it works:
*
* 1/ The application must provide a function named "android_main()" that
* will be called when the activity is created, in a new thread that is
* distinct from the activity's main thread.
*
* 2/ android_main() receives a pointer to a valid "android_app" structure
* that contains references to other important objects, e.g. the
* ANativeActivity obejct instance the application is running in.
*
* 3/ the "android_app" object holds an ALooper instance that already
* listens to two important things:
*
* - activity lifecycle events (e.g. "pause", "resume"). See APP_CMD_XXX
* declarations below.
*
* - input events coming from the AInputQueue attached to the activity.
*
* Each of these correspond to an ALooper identifier returned by
* ALooper_pollOnce with values of LOOPER_ID_MAIN and LOOPER_ID_INPUT,
* respectively.
*
* Your application can use the same ALooper to listen to additional
* file-descriptors. They can either be callback based, or with return
* identifiers starting with LOOPER_ID_USER.
*
* 4/ Whenever you receive a LOOPER_ID_MAIN or LOOPER_ID_INPUT event,
* the returned data will point to an android_poll_source structure. You
* can call the process() function on it, and fill in android_app->onAppCmd
* and android_app->onInputEvent to be called for your own processing
* of the event.
*
* Alternatively, you can call the low-level functions to read and process
* the data directly... look at the process_cmd() and process_input()
* implementations in the glue to see how to do this.
*
* See the sample named "native-activity" that comes with the NDK with a
* full usage example. Also look at the JavaDoc of NativeActivity.
*/
struct android_app;
/**
* Data associated with an ALooper fd that will be returned as the "outData"
* when that source has data ready.
*/
struct android_poll_source {
// The identifier of this source. May be LOOPER_ID_MAIN or
// LOOPER_ID_INPUT.
int32_t id;
// The android_app this ident is associated with.
struct android_app* app;
// Function to call to perform the standard processing of data from
// this source.
void (*process)(struct android_app* app, struct android_poll_source* source);
};
/**
* This is the interface for the standard glue code of a threaded
* application. In this model, the application's code is running
* in its own thread separate from the main thread of the process.
* It is not required that this thread be associated with the Java
* VM, although it will need to be in order to make JNI calls any
* Java objects.
*/
struct android_app {
// The application can place a pointer to its own state object
// here if it likes.
void* userData;
// Fill this in with the function to process main app commands (APP_CMD_*)
void (*onAppCmd)(struct android_app* app, int32_t cmd);
// Fill this in with the function to process input events. At this point
// the event has already been pre-dispatched, and it will be finished upon
// return. Return 1 if you have handled the event, 0 for any default
// dispatching.
int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event);
// The ANativeActivity object instance that this app is running in.
ANativeActivity* activity;
// The current configuration the app is running in.
AConfiguration* config;
// This is the last instance's saved state, as provided at creation time.
// It is NULL if there was no state. You can use this as you need; the
// memory will remain around until you call android_app_exec_cmd() for
// APP_CMD_RESUME, at which point it will be freed and savedState set to NULL.
// These variables should only be changed when processing a APP_CMD_SAVE_STATE,
// at which point they will be initialized to NULL and you can malloc your
// state and place the information here. In that case the memory will be
// freed for you later.
void* savedState;
size_t savedStateSize;
// The ALooper associated with the app's thread.
ALooper* looper;
// When non-NULL, this is the input queue from which the app will
// receive user input events.
AInputQueue* inputQueue;
// When non-NULL, this is the window surface that the app can draw in.
ANativeWindow* window;
// Current content rectangle of the window; this is the area where the
// window's content should be placed to be seen by the user.
ARect contentRect;
// Current state of the app's activity. May be either APP_CMD_START,
// APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below.
int activityState;
// This is non-zero when the application's NativeActivity is being
// destroyed and waiting for the app thread to complete.
int destroyRequested;
// -------------------------------------------------
// Below are "private" implementation of the glue code.
pthread_mutex_t mutex;
pthread_cond_t cond;
int msgread;
int msgwrite;
pthread_t thread;
struct android_poll_source cmdPollSource;
struct android_poll_source inputPollSource;
int running;
int stateSaved;
int destroyed;
int redrawNeeded;
AInputQueue* pendingInputQueue;
ANativeWindow* pendingWindow;
ARect pendingContentRect;
};
enum {
/**
* Looper data ID of commands coming from the app's main thread, which
* is returned as an identifier from ALooper_pollOnce(). The data for this
* identifier is a pointer to an android_poll_source structure.
* These can be retrieved and processed with android_app_read_cmd()
* and android_app_exec_cmd().
*/
LOOPER_ID_MAIN = 1,
/**
* Looper data ID of events coming from the AInputQueue of the
* application's window, which is returned as an identifier from
* ALooper_pollOnce(). The data for this identifier is a pointer to an
* android_poll_source structure. These can be read via the inputQueue
* object of android_app.
*/
LOOPER_ID_INPUT = 2,
/**
* Start of user-defined ALooper identifiers.
*/
LOOPER_ID_USER = 3,
};
enum {
/**
* Command from main thread: the AInputQueue has changed. Upon processing
* this command, android_app->inputQueue will be updated to the new queue
* (or NULL).
*/
APP_CMD_INPUT_CHANGED,
/**
* Command from main thread: a new ANativeWindow is ready for use. Upon
* receiving this command, android_app->window will contain the new window
* surface.
*/
APP_CMD_INIT_WINDOW,
/**
* Command from main thread: the existing ANativeWindow needs to be
* terminated. Upon receiving this command, android_app->window still
* contains the existing window; after calling android_app_exec_cmd
* it will be set to NULL.
*/
APP_CMD_TERM_WINDOW,
/**
* Command from main thread: the current ANativeWindow has been resized.
* Please redraw with its new size.
*/
APP_CMD_WINDOW_RESIZED,
/**
* Command from main thread: the system needs that the current ANativeWindow
* be redrawn. You should redraw the window before handing this to
* android_app_exec_cmd() in order to avoid transient drawing glitches.
*/
APP_CMD_WINDOW_REDRAW_NEEDED,
/**
* Command from main thread: the content area of the window has changed,
* such as from the soft input window being shown or hidden. You can
* find the new content rect in android_app::contentRect.
*/
APP_CMD_CONTENT_RECT_CHANGED,
/**
* Command from main thread: the app's activity window has gained
* input focus.
*/
APP_CMD_GAINED_FOCUS,
/**
* Command from main thread: the app's activity window has lost
* input focus.
*/
APP_CMD_LOST_FOCUS,
/**
* Command from main thread: the current device configuration has changed.
*/
APP_CMD_CONFIG_CHANGED,
/**
* Command from main thread: the system is running low on memory.
* Try to reduce your memory use.
*/
APP_CMD_LOW_MEMORY,
/**
* Command from main thread: the app's activity has been started.
*/
APP_CMD_START,
/**
* Command from main thread: the app's activity has been resumed.
*/
APP_CMD_RESUME,
/**
* Command from main thread: the app should generate a new saved state
* for itself, to restore from later if needed. If you have saved state,
* allocate it with malloc and place it in android_app.savedState with
* the size in android_app.savedStateSize. The will be freed for you
* later.
*/
APP_CMD_SAVE_STATE,
/**
* Command from main thread: the app's activity has been paused.
*/
APP_CMD_PAUSE,
/**
* Command from main thread: the app's activity has been stopped.
*/
APP_CMD_STOP,
/**
* Command from main thread: the app's activity is being destroyed,
* and waiting for the app thread to clean up and exit before proceeding.
*/
APP_CMD_DESTROY,
};
/**
* Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next
* app command message.
*/
int8_t android_app_read_cmd(struct android_app* android_app);
/**
* Call with the command returned by android_app_read_cmd() to do the
* initial pre-processing of the given command. You can perform your own
* actions for the command after calling this function.
*/
void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd);
/**
* Call with the command returned by android_app_read_cmd() to do the
* final post-processing of the given command. You must have done your own
* actions for the command before calling this function.
*/
void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd);
/**
* Dummy function that used to be used to prevent the linker from stripping app
* glue code. No longer necessary, since __attribute__((visibility("default")))
* does this for us.
*/
__attribute__((
deprecated("Calls to app_dummy are no longer necessary. See "
"https://github.com/android-ndk/ndk/issues/381."))) void
app_dummy();
/**
* This is the function that application code must implement, representing
* the main entry to the app.
*/
extern void android_main(struct android_app* app);
#ifdef __cplusplus
}
#endif
#endif /* _ANDROID_NATIVE_APP_GLUE_H */
#endif // FL_WINAPI_SCREEN_DRIVER_H
//
// End of "$Id: Fl_Android_Screen_Driver.H 12655 2018-02-09 14:39:42Z AlbrechtS $".
//

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,129 @@
//
// "$Id: Fl_Android_System_Driver.H 12655 2018-02-09 14:39:42Z AlbrechtS $"
//
// Definition of Windows system driver for the Fast Light Tool Kit (FLTK).
//
// Copyright 2010-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:
//
// http://www.fltk.org/COPYING.php
//
// Please report all bugs and problems on the following page:
//
// http://www.fltk.org/str.php
//
/**
\file Fl_WinAPI_System_Driver.H
\brief Definition of Windows system driver.
*/
#ifndef FL_WINAPI_SYSTEM_DRIVER_H
#define FL_WINAPI_SYSTEM_DRIVER_H
#include <FL/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(char *var) {return ::putenv(var);} // *FIXME* needs string conversion
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);
// 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 **) );
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);
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
};
#endif // FL_WINAPI_SYSTEM_DRIVER_H
//
// End of "$Id: Fl_Android_System_Driver.H 12655 2018-02-09 14:39:42Z AlbrechtS $".
//

View File

@ -0,0 +1,947 @@
//
// "$Id: Fl_Android_System_Driver.cxx 12655 2018-02-09 14:39:42Z AlbrechtS $"
//
// Definition of Apple Darwin system driver.
//
// 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:
//
// http://www.fltk.org/COPYING.php
//
// Please report all bugs and problems on the following page:
//
// http://www.fltk.org/str.php
//
#include "../../config_lib.h"
#include "Fl_Android_System_Driver.H"
#include <FL/Fl.H>
#include <FL/fl_utf8.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::filename_list(const char *d, dirent ***list, int (*sort)(struct dirent **, struct dirent **) ) {
// 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);
}
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 = 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)
{
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);
}
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]);
}
}
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) {
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
//
// End of "$Id: Fl_Android_System_Driver.cxx 12655 2018-02-09 14:39:42Z AlbrechtS $".
//

View File

@ -0,0 +1,144 @@
//
// "$Id: Fl_Android_Window_Driver.H 12668 2018-02-16 16:24:32Z manolo $"
//
// Definition of Apple Cocoa window driver
// for the Fast Light Tool Kit (FLTK).
//
// Copyright 2010-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:
//
// http://www.fltk.org/COPYING.php
//
// Please report all bugs and problems on the following page:
//
// http://www.fltk.org/str.php
//
/**
\file Fl_WinAPI_Window_Driver.H
\brief Definition of Windows window driver.
*/
#ifndef FL_WINAPI_WINDOW_DRIVER_H
#define FL_WINAPI_WINDOW_DRIVER_H
#include <FL/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 *todelete_; ///< auxiliary bitmap image
};
class FL_EXPORT Fl_Android_Window_Driver : public Fl_Window_Driver
{
static Fl_Window *sCurrent;
#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:
Fl_Android_Window_Driver(Fl_Window *w) : Fl_Window_Driver(w) {}
~Fl_Android_Window_Driver() {}
static inline Fl_Android_Window_Driver* driver(Fl_Window *w) {
return (Fl_Android_Window_Driver*)w->driver();
}
#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 make_current() { sCurrent = this; }
#endif
virtual void show();
#if 0
virtual void label(const char *name,const char *iname);
virtual void resize(int X,int Y,int W,int H);
virtual void hide();
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);
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);
static void resize_after_screen_change(void *data);
#endif
};
#endif // FL_WINAPI_WINDOW_DRIVER_H
//
// End of "$Id: Fl_Android_Window_Driver.H 12668 2018-02-16 16:24:32Z manolo $".
//

View File

@ -0,0 +1,732 @@
//
// "$Id: Fl_Android_Window_Driver.cxx 12641 2018-01-31 21:17:17Z AlbrechtS $"
//
// Definition of Apple Cocoa window driver.
//
// 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:
//
// http://www.fltk.org/COPYING.php
//
// Please report all bugs and problems on the following page:
//
// http://www.fltk.org/str.php
//
#include "../../config_lib.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 "Fl_Android_Window_Driver.H"
#include "Fl_Android_Screen_Driver.H"
#include "Fl_Android_Graphics_Driver.H"
#if 0
#include <windows.h>
#include <math.h> // for ceil()
#if USE_COLORMAP
extern HPALETTE fl_select_palette(void); // in fl_color_win32.cxx
#endif
#endif
Fl_Window *Fl_Android_Window_Driver::sCurrent = 0L;
Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w)
{
return new Fl_Android_Window_Driver(w);
}
void Fl_Window_Driver::default_icons(Fl_RGB_Image const**, int) {
}
Window fl_window = 0;
void Fl_Android_Window_Driver::show()
{
if (!shown()) {
// make window
fl_open_display();
pWindow->set_visible();
Fl_X *x = new Fl_X;
x->w = pWindow;
i(x);
x->next = Fl_X::first;
Fl_X::first = x;
} else {
// bring window to front
}
}
#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_->todelete_;
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_->todelete_ = bitmap;
}
void Fl_WinAPI_Window_Driver::shape(const Fl_Image* img) {
if (shape_data_) {
if (shape_data_->todelete_) { delete shape_data_->todelete_; }
}
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,Y,W,H; 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, Y, W, H; 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_USE_CAIRO
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) // FIXME - silence Doxygen warning
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) // FIXME - silence Doxygen warning
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);
}
int Fl_WinAPI_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)
{
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;
}
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
//
// End of "$Id: Fl_Android_Window_Driver.cxx 12641 2018-01-31 21:17:17Z AlbrechtS $".
//

View File

@ -0,0 +1,52 @@
//
// "$Id: Fl_Font.H 12650 2018-02-07 15:34:44Z manolo $"
//
// 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:
//
// http://www.fltk.org/COPYING.php
//
// Please report all bugs and problems on the following page:
//
// http://www.fltk.org/str.php
//
// Two internal fltk data structures:
//
// Fl_Fontdesc: an entry into the fl_font() table. There is one of these
// for each fltk font number.
//
#ifndef FL_FONT_
#define FL_FONT_
#include <config.h>
#if 0
class Fl_GDI_Font_Descriptor : public Fl_Font_Descriptor {
public:
HFONT fid;
int *width[64];
TEXTMETRIC metr;
int angle;
FL_EXPORT Fl_GDI_Font_Descriptor(const char* fontname, Fl_Fontsize size);
# if HAVE_GL
char glok[64];
# endif // HAVE_GL
FL_EXPORT ~Fl_GDI_Font_Descriptor();
};
#endif
extern FL_EXPORT Fl_Fontdesc *fl_fonts; // the table
#endif
//
// End of "$Id: Fl_Font.H 12650 2018-02-07 15:34:44Z manolo $".
//

File diff suppressed because it is too large Load Diff