Android: Draws Fl_Bitmap.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12807 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
parent
5040bbff1f
commit
3b7e1a5ec6
@ -72,6 +72,12 @@ typedef opaque GLContext; /**< an OpenGL graphics context, into which all OpenGL
|
||||
typedef intptr_t fl_intptr_t;
|
||||
typedef uintptr_t fl_uintptr_t;
|
||||
|
||||
#elif defined(__ANDROID__)
|
||||
|
||||
#include <sys/stat.h>
|
||||
typedef intptr_t fl_intptr_t;
|
||||
typedef uintptr_t fl_uintptr_t;
|
||||
|
||||
#else /* ! _WIN64 */
|
||||
|
||||
typedef long fl_intptr_t;
|
||||
@ -125,10 +131,10 @@ typedef unsigned long Fl_Offscreen;
|
||||
typedef unsigned long Fl_Bitmask;
|
||||
typedef int FL_SOCKET;
|
||||
typedef struct __GLXcontextRec *GLContext;
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
|
||||
|
||||
#elif defined(FL_PORTING)
|
||||
# pragma message "FL_PORTING: define OS-dependent types"
|
||||
typedef void* Fl_Offscreen;
|
||||
|
||||
@ -89,7 +89,44 @@ int main(int argc, char **argv)
|
||||
|
||||
#elif 1
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Double_Window.H>
|
||||
#include <FL/Fl_Adjuster.H>
|
||||
#include <FL/Fl_Box.H>
|
||||
|
||||
void adjcb(Fl_Widget *o, void *v) {
|
||||
Fl_Adjuster *a = (Fl_Adjuster*)o;
|
||||
Fl_Box *b = (Fl_Box *)v;
|
||||
a->format((char *)(b->label()));
|
||||
b->redraw();
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv) {
|
||||
Fl_Double_Window window(320,100,argv[0]);
|
||||
|
||||
char buf1[100];
|
||||
Fl_Box b1(FL_DOWN_BOX,20,30,80,25,buf1);
|
||||
b1.color(FL_WHITE);
|
||||
Fl_Adjuster a1(20+80,30,3*25,25);
|
||||
a1.callback(adjcb,&b1);
|
||||
adjcb(&a1,&b1);
|
||||
|
||||
char buf2[100];
|
||||
Fl_Box b2(FL_DOWN_BOX,20+80+4*25,30,80,25,buf2);
|
||||
b2.color(FL_WHITE);
|
||||
Fl_Adjuster a2(b2.x()+b2.w(),10,25,3*25);
|
||||
a2.callback(adjcb,&b2);
|
||||
adjcb(&a2,&b2);
|
||||
|
||||
window.resizable(window);
|
||||
window.end();
|
||||
window.show(argc, argv);
|
||||
return Fl::run();
|
||||
}
|
||||
|
||||
|
||||
#elif 0
|
||||
|
||||
|
||||
#include <FL/Fl.H>
|
||||
@ -411,7 +448,7 @@ int xmain(int argc, char **argv)
|
||||
|
||||
test/CubeMain.cxx test/line_style.cxx
|
||||
test/CubeView.cxx test/list_visuals.cxx
|
||||
* test/adjuster.cxx : - missing bitmap drawing
|
||||
* test/adjuster.cxx : + 'adjuster' works
|
||||
test/mandelbrot.cxx
|
||||
test/animated.cxx test/menubar.cxx
|
||||
* test/arc.cxx : + 'arc' works as expected
|
||||
@ -420,7 +457,7 @@ test/ask.cxx
|
||||
* test/minimum.cxx : + 'minimum' works
|
||||
test/bitmap.cxx test/native-filechooser.cxx
|
||||
test/blocks.cxx test/navigation.cxx
|
||||
* test/boxtype.cxx : + 'boxtype': works
|
||||
* test/boxtype.cxx : + 'boxtype' works
|
||||
test/offscreen.cxx
|
||||
test/browser.cxx test/output.cxx
|
||||
test/button.cxx test/overlay.cxx
|
||||
@ -456,6 +493,6 @@ test/image.cxx test/unittest_viewport.cxx
|
||||
test/input.cxx test/unittests.cxx
|
||||
test/input_choice.cxx test/utf8.cxx
|
||||
test/keyboard.cxx test/windowfocus.cxx
|
||||
* test/label.cxx : - pixmap, keyboard events
|
||||
* test/label.cxx : - pixmap
|
||||
|
||||
*/
|
||||
@ -118,6 +118,10 @@ public:
|
||||
// --- matrix based drawing
|
||||
// virtual void line_unscaled(float x, float y, float x1, float y1) override;
|
||||
|
||||
// --- image drawing
|
||||
|
||||
virtual void draw_unscaled(Fl_Bitmap *pxm, float s, int XP, int YP, int WP, int HP, int cx, int cy) override;
|
||||
virtual fl_uintptr_t cache(Fl_Bitmap *img) override;
|
||||
|
||||
#if 0
|
||||
virtual int has_feature(driver_feature mask) { return mask & NATIVE; }
|
||||
@ -128,7 +132,6 @@ public:
|
||||
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);
|
||||
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);
|
||||
|
||||
@ -904,264 +904,42 @@ void Fl_Android_Graphics_Driver::ellipse_unscaled(double xt, double yt, double r
|
||||
}
|
||||
|
||||
|
||||
#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()
|
||||
void Fl_Android_Graphics_Driver::draw_unscaled(Fl_Bitmap *bm, float s, int XP, int YP, int WP, int HP, int cx, int cy)
|
||||
{
|
||||
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())
|
||||
int X, Y, W, H;
|
||||
if (Fl_Graphics_Driver::prepare(bm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) {
|
||||
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);
|
||||
if (*Fl_Graphics_Driver::id(bm)) {
|
||||
Fl_Android_Bytemap *cache = (Fl_Android_Bytemap*)*Fl_Graphics_Driver::id(bm);
|
||||
for (const auto &it: pClippingRegion.overlapping(Fl_Rect_Region(X, Y, W, H))) {
|
||||
render_bytemap(XP, YP, cache, it->clipped_rect());
|
||||
}
|
||||
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));
|
||||
fl_uintptr_t Fl_Android_Graphics_Driver::cache(Fl_Bitmap *bm)
|
||||
{
|
||||
int w = bm->w(), h = bm->h();
|
||||
int rowBytes = (w+7)>>3;
|
||||
|
||||
Fl_Android_Bytemap *cache = new Fl_Android_Bytemap(w, h);
|
||||
for (int yy=0; yy<w; yy++) {
|
||||
const uchar *src = bm->array + yy*rowBytes;
|
||||
uchar *dst = cache->pBytes + yy*cache->pStride;
|
||||
uchar d;
|
||||
for (int xx=0; xx<w; xx++) {
|
||||
if ((xx&7)==0) d = *src++;
|
||||
if (d&1) *dst = 0xff; else *dst = 0;
|
||||
dst++;
|
||||
d >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return (fl_uintptr_t)cache;
|
||||
}
|
||||
|
||||
void Fl_GDI_Graphics_Driver::set_current_() {
|
||||
restore_clip();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
*/
|
||||
|
||||
//
|
||||
// End of "$Id$".
|
||||
//
|
||||
|
||||
@ -36,11 +36,13 @@ class Fl_Android_Bytemap
|
||||
{
|
||||
public:
|
||||
Fl_Android_Bytemap();
|
||||
Fl_Android_Bytemap(int w, int h);
|
||||
~Fl_Android_Bytemap();
|
||||
|
||||
public:
|
||||
int pWidth, pHeight, pStride, pXOffset, pYOffset, pAdvance;
|
||||
unsigned char *pBytes;
|
||||
int pWidth = 0, pHeight = 0, pStride = 0;
|
||||
int pXOffset = 0, pYOffset = 0, pAdvance = 0;
|
||||
unsigned char *pBytes = nullptr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -68,11 +68,19 @@ static const char *old_font_names[] = {
|
||||
/**
|
||||
* Create an empty Bytemap.
|
||||
*/
|
||||
Fl_Android_Bytemap::Fl_Android_Bytemap() :
|
||||
pBytes(nullptr)
|
||||
Fl_Android_Bytemap::Fl_Android_Bytemap()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an empty Bytemap.
|
||||
*/
|
||||
Fl_Android_Bytemap::Fl_Android_Bytemap(int w, int h)
|
||||
{
|
||||
pWidth = w; pStride = w; pHeight = h;
|
||||
pBytes = (unsigned char *)malloc(w*h);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the Bytemap and its allocated resources.
|
||||
*/
|
||||
|
||||
Loading…
Reference in New Issue
Block a user