Android: Drawing RGB image data (and probaly rgba and grayscale as well). Testing unsing test/color_chooser.cxx

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12817 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Matthias Melcher 2018-03-31 21:29:33 +00:00
parent e4916d617e
commit 936fbd096f
7 changed files with 323 additions and 215 deletions

View File

@ -10,8 +10,9 @@ CONTENTS
--------
1 Building FLTK with Android Studio 3
2 Extensions and limitation of FLTK on Android
3 DOCUMENT HISTORY
2 Building Apps on an Android device with C4Droid
3 Extensions and limitation of FLTK on Android
4 DOCUMENT HISTORY
BUILDING FLTK SAMPLE WITH ANDROID STUDIO 3
@ -33,12 +34,33 @@ device, you are ready to install FLTK.
- click "run"; the project should compile and run out of the box
Building Apps on an Android device with C4Droid
-----------------------------------------------
WORK IN PROGRESS:
C4Droid is a minimal IDE that comes with gcc/g++ and runs directly on your
Android device. C4Droid supports Native Activities, SDL, SDL2, and even Qt.
FLTK uses the Native Activity mechanism, so why not write FLTK apps right
on your phone?
- compile and test the Android test app in ide/HelloAndroid
- create /sdcard/include/ and /sdcard/lib/ on your Android device
- copy (fltk)/FL/ and its content into /sdcard/include/
- copy (fltk)/ide/AndroidStudio3/FL/abi-version.h to /sdcard/include/FL/
- copy (fltk)/ide/AndroidStudio3/./app/.externalNativeBuild/cmake/debug/arm64-v8a/fltk/lib/libfltk.a
to /sdcard/lib/
- ... change Native Activity settings in c4Droid preferences
- ... remove native glue
- ... add include and library path, add library
- ... add support for (which?) STL library
Extensions and limitation of FLTK on Android
--------------------------------------------
Android support for FLTK is in a very early stage. As of March 2018, very basic
rendering works, text rendering work, clipping works, window layering works,
and mouse clicks (touch events) are detected.
Android support for FLTK is in an early stage. As of March 2018, most
rendering works, fonts work, bitmaps and pixmaps work, clipping works, window
layering works, and mouse clicks and keyboard events are handled
When loading fonts:
- font names starting with a $ will have the system font path inserted
@ -53,6 +75,7 @@ Limitations:
DOCUMENT HISTORY
----------------
Mar 29 2018 - matt: many graphics functions ahve been implemented, keyboard
Mar 17 2018 - matt: added Android extensions for fonts
Mar 12 2018 - matt: started list of limitation that serevs as information to the
user as much as a todo list for core developers

View File

@ -96,6 +96,8 @@
<sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/.DS_Store" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/.DS_Store" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/check-manifest" />

View File

@ -15,195 +15,159 @@
*
*/
#if 0
#elif 1
#if 1
//
// "$Id: color_chooser.cxx 12655 2018-02-09 14:39:42Z AlbrechtS $"
//
// Color chooser test program 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 <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Hor_Value_Slider.H>
#include <FL/Fl_Toggle_Button.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Choice.H>
#include <FL/Fl_Pixmap.H>
#include <FL/Fl_Button.H>
#include <FL/fl_show_colormap.H>
#include <FL/Fl_Color_Chooser.H>
#include <FL/Fl_Image.H>
#include <FL/platform.H>
#include <FL/fl_draw.H>
#include "/Users/matt/dev/fltk-1.4.svn/test/pixmaps/blast.xpm"
#include <stdlib.h>
#include <stdio.h>
#if !defined(_WIN32) && !defined(__APPLE__) && !defined(FL_PORTING) && !defined(__ANDROID__)
#include "list_visuals.cxx"
#endif
Fl_Toggle_Button *imageb, *imageovertextb, *imagenexttotextb, *imagebackdropb;
Fl_Toggle_Button *leftb,*rightb,*topb,*bottomb,*insideb,*clipb,*wrapb;
Fl_Box *text;
Fl_Input *input;
Fl_Hor_Value_Slider *fonts;
Fl_Hor_Value_Slider *sizes;
Fl_Double_Window *window;
Fl_Pixmap *img;
int width = 100;
int height = 100;
uchar *image;
Fl_Box *hint;
void button_cb(Fl_Widget *,void *) {
int i = 0;
if (leftb->value()) i |= FL_ALIGN_LEFT;
if (rightb->value()) i |= FL_ALIGN_RIGHT;
if (topb->value()) i |= FL_ALIGN_TOP;
if (bottomb->value()) i |= FL_ALIGN_BOTTOM;
if (insideb->value()) i |= FL_ALIGN_INSIDE;
if (clipb->value()) i |= FL_ALIGN_CLIP;
if (wrapb->value()) i |= FL_ALIGN_WRAP;
if (imageovertextb->value()) i |= FL_ALIGN_TEXT_OVER_IMAGE;
if (imagenexttotextb->value()) i |= FL_ALIGN_IMAGE_NEXT_TO_TEXT;
if (imagebackdropb->value()) i |= FL_ALIGN_IMAGE_BACKDROP;
text->align(i);
window->redraw();
}
void image_cb(Fl_Widget *,void *) {
if (imageb->value())
text->image(img);
else
text->image(0);
window->redraw();
}
void font_cb(Fl_Widget *,void *) {
text->labelfont(int(fonts->value()));
window->redraw();
}
void size_cb(Fl_Widget *,void *) {
text->labelsize(int(sizes->value()));
window->redraw();
}
void input_cb(Fl_Widget *,void *) {
text->label(input->value());
window->redraw();
}
void normal_cb(Fl_Widget *,void *) {
text->labeltype(FL_NORMAL_LABEL);
window->redraw();
}
void symbol_cb(Fl_Widget *,void *) {
text->labeltype(FL_SYMBOL_LABEL);
if (input->value()[0] != '@') {
input->static_value("@->");
text->label("@->");
void make_image() {
image = new uchar[3*width*height];
uchar *p = image;
for (int y = 0; y < height; y++) {
double Y = double(y)/(height-1);
for (int x = 0; x < width; x++) {
double X = double(x)/(width-1);
*p++ = uchar(255*((1-X)*(1-Y))); // red in upper-left
*p++ = uchar(255*((1-X)*Y)); // green in lower-left
*p++ = uchar(255*(X*Y)); // blue in lower-right
}
}
window->redraw();
}
void shadow_cb(Fl_Widget *,void *) {
text->labeltype(FL_SHADOW_LABEL);
window->redraw();
class Pens : public Fl_Box {
void draw();
public:
Pens(int X, int Y, int W, int H, const char* L)
: Fl_Box(X,Y,W,H,L) {}
};
void Pens::draw() {
// use every color in the gray ramp:
for (int i = 0; i < 3*8; i++) {
fl_color((Fl_Color)(FL_GRAY_RAMP+i));
fl_line(x()+i, y(), x()+i, y()+h());
}
}
void embossed_cb(Fl_Widget *,void *) {
text->labeltype(FL_EMBOSSED_LABEL);
window->redraw();
Fl_Color c = FL_GRAY;
#define fullcolor_cell (FL_FREE_COLOR)
void cb1(Fl_Widget *, void *v) {
c = fl_show_colormap(c);
Fl_Box* b = (Fl_Box*)v;
b->color(c);
hint->labelcolor(fl_contrast(FL_BLACK,c));
b->parent()->redraw();
}
void engraved_cb(Fl_Widget *,void *) {
text->labeltype(FL_ENGRAVED_LABEL);
window->redraw();
void cb2(Fl_Widget *, void *v) {
uchar r,g,b;
Fl::get_color(c,r,g,b);
if (!fl_color_chooser("New color:",r,g,b,3)) return;
c = fullcolor_cell;
Fl::set_color(fullcolor_cell,r,g,b);
Fl_Box* bx = (Fl_Box*)v;
bx->color(fullcolor_cell);
hint->labelcolor(fl_contrast(FL_BLACK,fullcolor_cell));
bx->parent()->redraw();
}
Fl_Menu_Item choices[] = {
{"FL_NORMAL_LABEL",0,normal_cb},
{"FL_SYMBOL_LABEL",0,symbol_cb},
{"FL_SHADOW_LABEL",0,shadow_cb},
{"FL_ENGRAVED_LABEL",0,engraved_cb},
{"FL_EMBOSSED_LABEL",0,embossed_cb},
{0}};
int main(int argc, char **argv) {
img = new Fl_Pixmap(blast_xpm);
window = new Fl_Double_Window(440,420);
input = new Fl_Input(70,375,350,25,"Label:");
input->static_value("The quick brown fox jumped over the lazy dog.");
input->when(FL_WHEN_CHANGED);
input->callback(input_cb);
input->tooltip("label text");
sizes= new Fl_Hor_Value_Slider(70,350,350,25,"Size:");
sizes->align(FL_ALIGN_LEFT);
sizes->bounds(1,64);
sizes->step(1);
sizes->value(14);
sizes->callback(size_cb);
fonts=new Fl_Hor_Value_Slider(70,325,350,25,"Font:");
fonts->align(FL_ALIGN_LEFT);
fonts->bounds(0,15);
fonts->step(1);
fonts->value(0);
fonts->callback(font_cb);
Fl_Group *g = new Fl_Group(70,275,350,50);
imageb = new Fl_Toggle_Button(70,275,50,25,"image");
imageb->callback(image_cb);
imageb->tooltip("show image");
imageovertextb = new Fl_Toggle_Button(120,275,50,25,"T o I");
imageovertextb->callback(button_cb);
imageovertextb->tooltip("FL_ALIGN_TEXT_OVER_IMAGE");
imagenexttotextb = new Fl_Toggle_Button(170,275,50,25,"I | T");
imagenexttotextb->callback(button_cb);
imagenexttotextb->tooltip("FL_ALIGN_IMAGE_NEXT_TO_TEXT");
imagebackdropb = new Fl_Toggle_Button(220,275,50,25,"back");
imagebackdropb->callback(button_cb);
imagebackdropb->tooltip("FL_ALIGN_IMAGE_BACKDROP");
leftb = new Fl_Toggle_Button(70,300,50,25,"left");
leftb->callback(button_cb);
leftb->tooltip("FL_ALIGN_LEFT");
rightb = new Fl_Toggle_Button(120,300,50,25,"right");
rightb->callback(button_cb);
rightb->tooltip("FL_ALIGN_RIGHT");
topb = new Fl_Toggle_Button(170,300,50,25,"top");
topb->callback(button_cb);
topb->tooltip("FL_ALIGN_TOP");
bottomb = new Fl_Toggle_Button(220,300,50,25,"bottom");
bottomb->callback(button_cb);
bottomb->tooltip("FL_ALIGN_BOTTOM");
insideb = new Fl_Toggle_Button(270,300,50,25,"inside");
insideb->callback(button_cb);
insideb->tooltip("FL_ALIGN_INSIDE");
wrapb = new Fl_Toggle_Button(320,300,50,25,"wrap");
wrapb->callback(button_cb);
wrapb->tooltip("FL_ALIGN_WRAP");
clipb = new Fl_Toggle_Button(370,300,50,25,"clip");
clipb->callback(button_cb);
clipb->tooltip("FL_ALIGN_CLIP");
g->resizable(insideb);
g->end();
Fl_Choice *c = new Fl_Choice(70,250,200,25);
c->menu(choices);
text = new Fl_Box(FL_FRAME_BOX,120,75,200,100,input->value());
text->align(FL_ALIGN_CENTER);
window->resizable(text);
window->end();
window->show(argc,argv);
int main(int argc, char ** argv) {
Fl::set_color(fullcolor_cell,145,159,170);
Fl_Window window(400,400);
Fl_Box box(30,30,340,340);
box.box(FL_THIN_DOWN_BOX);
c = fullcolor_cell;
box.color(c);
Fl_Box hintbox(40,40,320,30,"Pick background color with buttons:");
hintbox.align(FL_ALIGN_INSIDE);
hint = &hintbox;
Fl_Button b1(120,80,180,30,"fl_show_colormap()");
b1.callback(cb1,&box);
Fl_Button b2(120,120,180,30,"fl_color_chooser()");
b2.callback(cb2,&box);
Fl_Box image_box(160,190,width,height,0);
make_image();
(new Fl_RGB_Image(image, width, height))->label(&image_box);
Fl_Box b(160,310,120,30,"Example of fl_draw_image()");
Pens p(60,180,3*8,120,"lines");
p.align(FL_ALIGN_TOP);
int i = 1;
if (!Fl::args(argc,argv,i) || i < argc-1) {
printf("usage: %s <switches> visual-number\n"
" - : default visual\n"
" r : call Fl::visual(FL_RGB)\n"
" c : call Fl::own_colormap()\n",argv[0]);
#if !defined(_WIN32) && !defined(__APPLE__) && !defined(FL_PORTING) && !defined(__ANDROID__)
printf(" # : use this visual with an empty colormap:\n");
list_visuals();
#endif
puts(Fl::help);
exit(1);
}
if (i!=argc) {
if (argv[i][0] == 'r') {
if (!Fl::visual(FL_RGB)) printf("Fl::visual(FL_RGB) returned false.\n");
} else if (argv[i][0] == 'c') {
Fl::own_colormap();
} else if (argv[i][0] != '-') {
#if !defined(_WIN32) && !defined(__APPLE__) && !defined(FL_PORTING) && !defined(__ANDROID__)
int visid = atoi(argv[i]);
fl_open_display();
XVisualInfo templt; int num;
templt.visualid = visid;
fl_visual = XGetVisualInfo(fl_display, VisualIDMask, &templt, &num);
if (!fl_visual) Fl::fatal("No visual with id %d",visid);
fl_colormap = XCreateColormap(fl_display, RootWindow(fl_display,fl_screen),
fl_visual->visual, AllocNone);
fl_xpixel(FL_BLACK); // make sure black is allocated
#else
Fl::fatal("Visual id's not supported on Windows or MacOS.");
#endif
}
}
window.show(argc,argv);
return Fl::run();
}
//
// End of "$Id: color_chooser.cxx 12655 2018-02-09 14:39:42Z AlbrechtS $".
//
#else
@ -359,7 +323,8 @@ test/cairo_test.cxx test/pixmap.cxx
test/checkers.cxx test/pixmap_browser.cxx
test/clock.cxx test/resizebox.cxx
test/colbrowser.cxx test/rotated_text.cxx
test/color_chooser.cxx test/scroll.cxx
* test/color_chooser.cxx: - can't draw 'on the fly' yet
test/scroll.cxx
test/connect.cxx test/shape.cxx
test/cube.cxx test/subwindow.cxx
test/cursor.cxx test/sudoku.cxx
@ -386,6 +351,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
* test/label.cxx : + 'label' works
*/

View File

@ -53,24 +53,23 @@ protected:
// - excluded by #if/#endif means that we have not implemneted this yet
// - methods marked with // super: use the implemnetation of the super class
// - virtual ... override functions are implemented for Android
#if 0
private:
// some platforms may need to reimplement this
virtual void set_current_();
// This is called from the surface device, see: end_current_()
// super: virtual void set_current_();
protected:
float scale_; // scale between user and graphical coordinates: graphical = user * scale_
/** Sets the current value of the scaling factor */
virtual void scale(float f) { scale_ = f; }
// super: virtual void scale(float f) { scale_ = f; } // we do not support any scaling at this point
protected:
virtual void global_gc();
#endif
// set fl_gc, which we do not use in the Android port at this point
// super: virtual void global_gc();
/** Support function for Fl_Pixmap drawing */
virtual fl_uintptr_t cache(Fl_Pixmap *img) override;
/** Support function for Fl_Bitmap drawing */
virtual fl_uintptr_t cache(Fl_Bitmap *img) override;
#if 0
/** Support function for Fl_RGB_Image drawing */
virtual void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_) { }
virtual void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_) override;
#if 0
// --- implementation is in src/drivers/xxx/Fl_xxx_Graphics_Driver_image.cxx
/** see fl_draw_image(const uchar* buf, int X,int Y,int W,int H, int D, int L) */
virtual void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0) {}
@ -80,13 +79,9 @@ protected:
virtual void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3) {}
/** see fl_draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D) */
virtual void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1) {}
/** \brief Draws an Fl_RGB_Image object using this graphics driver.
*
Specifies a bounding box for the image, with the origin (upper left-hand corner) of
the image offset by the cx and cy arguments.
*/
virtual void draw(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy) {}
#endif
/** \brief Draws an Fl_RGB_Image object using this graphics driver. */
virtual void draw(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy) override;
/** \brief Draws an Fl_Pixmap object using this graphics driver.
*
Specifies a bounding box for the image, with the origin (upper left-hand corner) of
@ -106,14 +101,9 @@ protected:
virtual Fl_Bitmask create_bitmask(int w, int h, const uchar *array) {return 0; }
/** Support function for image drawing */
virtual void delete_bitmask(Fl_Bitmask bm) {}
/** For internal library use only */
static void change_image_size(Fl_Image *img, int W, int H) {
img->w(W);
img->h(H);
}
// Support function for image drawing
virtual void uncache_pixmap(fl_uintptr_t p);
#endif
// Support function for image drawing
virtual void uncache_pixmap(fl_uintptr_t p) override;
public:
/** Constructor, C++11 initialises member variables in-line */
Fl_Android_Graphics_Driver();
@ -267,16 +257,19 @@ public:
/** Support for PostScript drawing */
virtual float scale_font_for_PostScript(Fl_Font_Descriptor *desc, int s) override { return float(s); }
// default implementation may be enough
#if 0
/** Support for PostScript drawing */
virtual float scale_bitmap_for_PostScript() { return 2; }
virtual void set_spot(int font, int size, int X, int Y, int W, int H, Fl_Window *win);
virtual void reset_spot();
/** Support for PostScript drawing - no documentation found on this call*/
// super: virtual float scale_bitmap_for_PostScript() { return 2; }
// super: virtual void set_spot(int font, int size, int X, int Y, int W, int H, Fl_Window *win);
// super: virtual void reset_spot();
// each platform implements these 3 functions its own way
virtual void add_rectangle_to_region(Fl_Region r, int x, int y, int w, int h);
virtual Fl_Region XRectangleRegion(int x, int y, int w, int h);
virtual void XDestroyRegion(Fl_Region r);
#endif
/* TODO: Android: we can implement this to have a redraw region based on Fl::damage
* calls. Currently, we do not implement damage regions, but we can probably
* implement this using our clipping regions. This may become neccesary when
* we allow desktop-style window movement.
*/
// super: virtual void add_rectangle_to_region(Fl_Region r, int x, int y, int w, int h);
// super: virtual Fl_Region XRectangleRegion(int x, int y, int w, int h);
// super: virtual void XDestroyRegion(Fl_Region r);
/** Support for Fl::get_font_name() */
virtual const char* get_font_name(Fl_Font fnum, int* ap) override;
/** Support for Fl::get_font_sizes() */
@ -291,13 +284,12 @@ public:
virtual const char *font_name(int num) override;
/** Support for Fl::set_font() */
virtual void font_name(int num, const char *name) override;
#if 0
// Draws an Fl_Image scaled to width W & height H
virtual int draw_scaled(Fl_Image *img, int X, int Y, int W, int H);
// TODO: we don't seem to need this until we introduce a scaling graphis driver
// super: virtual int draw_scaled(Fl_Image *img, int X, int Y, int W, int H);
/** Support function for fl_overlay_rect() and scaled GUI.
Defaut implementation may be enough */
virtual bool overlay_rect_unscaled();
#endif
// super: virtual bool overlay_rect_unscaled();
/** Support function for fl_overlay_rect() and scaled GUI.
Defaut implementation may be enough */
// super: virtual void overlay_rect(int x, int y, int w , int h) { loop(x, y, x+w-1, y, x+w-1, y+h-1, x, y+h-1); }
@ -305,7 +297,7 @@ public:
// --- start of Android additions --------------------------------------------
// start drawing with this driver into the given window
// TODO: how is this different to Fl_Graphics_Driver::set_current_() above
// The virtual call `set_current_()` changes surface, not windows
void make_current(Fl_Window*);
protected:

View File

@ -1031,10 +1031,10 @@ fl_uintptr_t Fl_Android_Graphics_Driver::cache(Fl_Pixmap *img)
const uchar *src = rgba + yy*rowBytes;
uint32_t *dst = cache->pWords + yy*cache->pStride;
for (int xx=0; xx<w; xx++) {
uint32_t c = ((((src[0] << 8) & 0xf800) |
((src[1] << 3) & 0x07e0) |
((src[2] >> 3) & 0x001f) ) << 16) | src[3]; // FIXME: alpha
*dst++ = c;
// uint32_t c = ((((src[0] << 8) & 0xf800) |
// ((src[1] << 3) & 0x07e0) |
// ((src[2] >> 3) & 0x001f) ) << 16) | src[3]; // FIXME: alpha
*dst++ = Fl_Android_565A_Map::toRGBA(src[0],src[1], src[2], src[3]);
src+=4;
}
}
@ -1044,6 +1044,86 @@ fl_uintptr_t Fl_Android_Graphics_Driver::cache(Fl_Pixmap *img)
}
void Fl_Android_Graphics_Driver::uncache_pixmap(fl_uintptr_t p)
{
Fl_Android_565A_Map *img = (Fl_Android_565A_Map*)p;
delete img;
}
void Fl_Android_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy)
{
int X, Y, W, H;
// Don't draw an empty image...
if (!img->d() || !img->array) {
Fl_Graphics_Driver::draw_empty(img, XP, YP);
return;
}
if (start_image(img, XP, YP, WP, HP, cx, cy, X, Y, W, H)) {
return;
}
Fl_Android_565A_Map *cgimg = (Fl_Android_565A_Map*)*Fl_Graphics_Driver::id(img);
if (!cgimg) {
int w = img->w(), h = img->h(), d = img->d(), stride = w*d + img->ld();
cgimg = new Fl_Android_565A_Map(w, h);
*Fl_Graphics_Driver::id(img) = (fl_uintptr_t)cgimg;
if (d==1) { // grayscale
for (int iy=0; iy<h; iy++) {
const uchar *src = img->array + iy*stride;
uint32_t *dst = cgimg->pWords + iy*cgimg->pStride;
for (int ix=0; ix<w; ix++) {
uchar l = *src++;
uint32_t rgba = Fl_Android_565A_Map::toRGBA(l, l, l, 255);
*dst++ = rgba;
}
}
} else if (d==2) { // gray + alpha
for (int iy=0; iy<h; iy++) {
const uchar *src = img->array + iy*stride;
uint32_t *dst = cgimg->pWords + iy*cgimg->pStride;
for (int ix=0; ix<w; ix++) {
uchar l = *src++, a = *src++;
uint32_t rgba = Fl_Android_565A_Map::toRGBA(l, l, l, a);
*dst++ = rgba;
}
}
} else if (d==3) { // rgb
for (int iy=0; iy<h; iy++) {
const uchar *src = img->array + iy*stride;
uint32_t *dst = cgimg->pWords + iy*cgimg->pStride;
for (int ix=0; ix<w; ix++) {
uchar r = *src++, g = *src++, b = *src++;
uint32_t rgba = Fl_Android_565A_Map::toRGBA(r, g, b, 255);
*dst++ = rgba;
}
}
} else if (d==4) { // rgb + alpha
for (int iy=0; iy<h; iy++) {
const uchar *src = img->array + iy*stride;
uint32_t *dst = cgimg->pWords + iy*cgimg->pStride;
for (int ix=0; ix<w; ix++) {
uchar r = *src++, g = *src++, b = *src++, a = *src++;
uint32_t rgba = Fl_Android_565A_Map::toRGBA(r, g, b, a);
*dst++ = rgba;
}
}
}
}
if (cgimg) {
for (const auto &it: pClippingRegion.overlapping(Fl_Rect_Region(X, Y, W, H))) {
draw(XP, YP, cgimg, it->clipped_rect());
}
}
}
void Fl_Android_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintptr_t&)
{
Fl_Android_565A_Map *cgimg = (Fl_Android_565A_Map*)id_;
delete cgimg;
}
void Fl_Android_Graphics_Driver::set_color(Fl_Color i, unsigned int c)
{
if (i>255) return;
@ -1056,6 +1136,19 @@ void Fl_Android_Graphics_Driver::color(uchar r, uchar g, uchar b)
color( (((Fl_Color)r)<<24)|(((Fl_Color)g)<<16)|(((Fl_Color)b)<<8) );
}
/**
* Draw a rectangle that may be dithered if we are in colormap mode (which in
* the year 2018 is as likely has a user with a berstein colored tube TV).
* FIXME: This function should be virtual as well, or should not exist at all.
*/
void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) {
#if USE_COLORMAP
// ...
#endif
fl_color(r,g,b);
fl_rectf(x,y,w,h);
}
//
// End of "$Id$".

View File

@ -23,7 +23,10 @@
#include "Fl_Android_Graphics_Driver.H"
// We violate FLTKs avoidance of STL because we live in a defined driver space
#define FL_ALLOW_STL 1
#ifdef FL_ALLOW_STL
#include <map>
#endif
#include "stb_truetype.h"
@ -31,6 +34,8 @@
/**
* A bytemap is an array of bytes, used as an alpha channel when redering glyphs
* in a given color.
* TODO: reate a class for RGB only and for grayscale and grayscale with alpha
* TODO: derive all this from a baseclass, so we can create the correct class for the required image
*/
class Fl_Android_Bytemap
{
@ -58,6 +63,12 @@ public:
Fl_Android_565A_Map();
Fl_Android_565A_Map(int w, int h);
~Fl_Android_565A_Map();
static inline uint32_t toRGBA(uchar r, uchar g, uchar b, uchar a)
{
return ((((r << 8) & 0xf800) |
((g << 3) & 0x07e0) |
((b >> 3) & 0x001f)) << 16) | a;
}
public:
int pWidth = 0, pHeight = 0, pStride = 0;
@ -98,7 +109,11 @@ public:
*/
class Fl_Android_Font_Descriptor : public Fl_Font_Descriptor
{
#ifdef FL_ALLOW_STL
typedef std::map<uint32_t, Fl_Android_Bytemap*> BytemapTable;
#else
typedef Fl_Android_Bytemap* BytemapTable[256];
#endif
private:
Fl_Android_Font_Source *pFontSource;
Fl_Font pFontIndex;

View File

@ -476,10 +476,16 @@ Fl_Android_Font_Descriptor::Fl_Android_Font_Descriptor(const char *fname, Fl_And
*/
Fl_Android_Font_Descriptor::~Fl_Android_Font_Descriptor()
{
#ifdef FL_ALLOW_STL
// Life is easy in C++11.
for (auto &i: pBytemapTable) {
delete i.second; i.second = nullptr;
}
#else
for (int i=0; i<256; i++) {
if (pBytemapTable[i]) delete pBytemapTable[i];
}
#endif
}
/*
@ -508,6 +514,7 @@ float Fl_Android_Font_Descriptor::get_advance(uint32_t c)
Fl_Android_Bytemap *Fl_Android_Font_Descriptor::get_bytemap(uint32_t c)
{
Fl_Android_Bytemap *bm = 0;
#ifdef FL_ALLOW_STL
auto it = pBytemapTable.find(c);
if (it==pBytemapTable.end()) {
bm = pFontSource->get_bytemap(c, size);
@ -516,6 +523,17 @@ Fl_Android_Bytemap *Fl_Android_Font_Descriptor::get_bytemap(uint32_t c)
} else {
bm = it->second;
}
#else
if (c<256) {
if (pBytemapTable[c]) {
bm = pBytemapTable[c];
} else {
bm = pFontSource->get_bytemap(c, size);
if (bm)
pBytemapTable[c] = bm;
}
}
#endif
return bm;
}