diff options
| author | Matthias Melcher <fltk@matthiasm.com> | 2018-03-17 16:23:40 +0000 |
|---|---|---|
| committer | Matthias Melcher <fltk@matthiasm.com> | 2018-03-17 16:23:40 +0000 |
| commit | 0016617ad480241f372c1e5325303816e9be26c0 (patch) | |
| tree | ab3227eb55166691867f5bdf9795eaaa4516cc3f | |
| parent | 69e534b48fe13064b027cece43e05b7b48671868 (diff) | |
Android: yes, we can unicode; cleanup; documentd
Next: add caching, add other font related calls, add clipping,
add font paths for package resources
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12765 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
| -rw-r--r-- | ide/AndroidStudio3/app/src/main/cpp/HelloAndroid.cxx | 2 | ||||
| -rw-r--r-- | src/drivers/Android/Fl_Android_Graphics_Font.H | 87 | ||||
| -rw-r--r-- | src/drivers/Android/Fl_Android_Graphics_Font.cxx | 233 |
3 files changed, 224 insertions, 98 deletions
diff --git a/ide/AndroidStudio3/app/src/main/cpp/HelloAndroid.cxx b/ide/AndroidStudio3/app/src/main/cpp/HelloAndroid.cxx index 37cfed565..7e91157ab 100644 --- a/ide/AndroidStudio3/app/src/main/cpp/HelloAndroid.cxx +++ b/ide/AndroidStudio3/app/src/main/cpp/HelloAndroid.cxx @@ -77,7 +77,7 @@ int main(int argc, char **argv) } ); - btn = new MyButton((win->w()-280)/2, 200+40, 280, 35, "Hello, Android!"); + btn = new MyButton((win->w()-280)/2, 200+40, 280, 35, "Hello, \u00c4\u00e4\u00d6\u00f6\u00dc\u00fc\u00df \u2639 \u263a"); btn->labelfont(FL_TIMES_BOLD_ITALIC); btn->labelsize(30); diff --git a/src/drivers/Android/Fl_Android_Graphics_Font.H b/src/drivers/Android/Fl_Android_Graphics_Font.H index 8b035521a..7e8af7d52 100644 --- a/src/drivers/Android/Fl_Android_Graphics_Font.H +++ b/src/drivers/Android/Fl_Android_Graphics_Font.H @@ -24,6 +24,10 @@ #include "stb_truetype.h" +/** + * A bytemap is an array of bytes, used as an alpha channel when redering glyphs + * in a given color. + */ class Fl_Android_Bytemap { public: @@ -36,6 +40,10 @@ public: }; +/** + * This class reads True Type Font files and creates Bytemaps for glyphs at the + * requested height. + */ class Fl_Android_Font_Source { private: @@ -46,12 +54,16 @@ private: public: Fl_Android_Font_Source(const char *fname, Fl_Font fnum); + ~Fl_Android_Font_Source(); void load_font(); Fl_Android_Bytemap *get_bytemap(uint32_t c, int size); float get_advance(uint32_t c, Fl_Fontsize size); }; +/** + * This class caches glyphs of a font for a specified height. + */ class Fl_Android_Font_Descriptor : public Fl_Font_Descriptor { private: @@ -63,83 +75,10 @@ public: float get_advance(uint32_t c); Fl_Android_Bytemap *get_bytemap(uint32_t c); Fl_Android_Font_Source *get_font_source() { return pFontSource; } -}; - - - -#if 0 - -fl_fonts array is managed by core?! - - /** Some platforms may need to implement this to support fonts */ -virtual Fl_Fontdesc* calc_fl_fonts(void) {return NULL;} - - typedef int Fl_Fontsize; - class Fl_Font_Descriptor; - struct Fl_Fontdesc; - - /* This class is not part of FLTK's public API. - Platforms usually define a derived class called Fl_XXX_Font_Descriptor - containing extra platform-specific data/functions. - This is a class for an actual system font, with junk to - help choose it and info on character sizes. Each Fl_Fontdesc has a - linked list of these. These are created the first time each system - font/size combination is used. - */ -class Fl_Font_Descriptor { -public: - /** linked list for this Fl_Fontdesc */ - Fl_Font_Descriptor *next; - Fl_Fontsize size; /**< font size */ - Fl_Font_Descriptor(const char* fontname, Fl_Fontsize size); - FL_EXPORT ~Fl_Font_Descriptor() {} - short ascent, descent, q_width; - unsigned int listbase;// base of display list, 0 = none -}; -// This struct is not part of FLTK's public API. -struct Fl_Fontdesc { - const char *name; - char fontname[128]; // "Pretty" font name - Fl_Font_Descriptor *first; // linked list of sizes of this style + static Fl_Android_Font_Descriptor* find(Fl_Font fnum, Fl_Fontsize size); }; -#endif - -#if 0 -// 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 - - #endif - #endif // FL_ANDROID_GRAPHICS_FONT_H diff --git a/src/drivers/Android/Fl_Android_Graphics_Font.cxx b/src/drivers/Android/Fl_Android_Graphics_Font.cxx index 47af9ec45..681d910bf 100644 --- a/src/drivers/Android/Fl_Android_Graphics_Font.cxx +++ b/src/drivers/Android/Fl_Android_Graphics_Font.cxx @@ -58,12 +58,17 @@ static Fl_Fontdesc built_in_table[] = { Fl_Fontdesc* fl_fonts = built_in_table; +/** + * Create an empty Bytemap. + */ Fl_Android_Bytemap::Fl_Android_Bytemap() : pBytes(0L) { } - +/** + * Destroy the Bytemap and its allocated resources. + */ Fl_Android_Bytemap::~Fl_Android_Bytemap() { if (pBytes) ::free(pBytes); @@ -72,7 +77,11 @@ Fl_Android_Bytemap::~Fl_Android_Bytemap() // ----------------------------------------------------------------------------- - +/** + * Create a True Type font manager. + * @param fname the name of the font as it appears in the fl_fonts table. + * @param fnum the index into the fl_fonts table + */ Fl_Android_Font_Source::Fl_Android_Font_Source(const char *fname, Fl_Font fnum) : pFileBuffer(0L), pName(fname), @@ -80,7 +89,19 @@ Fl_Android_Font_Source::Fl_Android_Font_Source(const char *fname, Fl_Font fnum) { } +/** + * Release all resources. + */ +Fl_Android_Font_Source::~Fl_Android_Font_Source() +{ + if (pFileBuffer) ::free(pFileBuffer); + // pFont does not allocate any buffers and needs no destructor +} +/** + * Load a True Type font file and initialize the TTF interpreter. + * A copy of the font file must remain in memory for the interpreter to work. + */ void Fl_Android_Font_Source::load_font() { if (pFileBuffer==0) { @@ -101,7 +122,12 @@ void Fl_Android_Font_Source::load_font() } } - +/** + * Return a bytemap for the give unicode character. + * @param c unicode character + * @param size height in pixels + * @return a bytemap + */ Fl_Android_Bytemap *Fl_Android_Font_Source::get_bytemap(uint32_t c, int size) { if (pFileBuffer==0) load_font(); @@ -140,7 +166,15 @@ Fl_Android_Bytemap *Fl_Android_Font_Source::get_bytemap(uint32_t c, int size) return byteMap; } - +/** + * Get the width of the character in pixels. + * This is not a good function because character advance also depends on kerning + * which takes the next character in a text line into account. Also, FLTK is + * limited to interger character positions, and so is the Android driver. + * @param c unicode character + * @param size height in pixels + * @return width in pixels to the start of the next character + */ float Fl_Android_Font_Source::get_advance(uint32_t c, Fl_Fontsize size) { int advance, lsb; @@ -154,7 +188,14 @@ float Fl_Android_Font_Source::get_advance(uint32_t c, Fl_Fontsize size) // ----------------------------------------------------------------------------- - +/** + * Create a new font descriptor. + * @param fname name of this font as in fl_fonts + * @param fsrc the font source for this font; there is one single font source + * for all hights of a single font + * @param fnum index into the fl_fonts array + * @param fsize height of font in pixels + */ Fl_Android_Font_Descriptor::Fl_Android_Font_Descriptor(const char *fname, Fl_Android_Font_Source *fsrc, Fl_Font fnum, Fl_Fontsize fsize) : Fl_Font_Descriptor(fname, fsize), pFontSource(fsrc), @@ -172,13 +213,21 @@ Fl_Android_Font_Descriptor::Fl_Android_Font_Descriptor(const char *fname, Fl_And // unsigned int listbase; // base of display list, 0 = none } - +/* + * Get the width of the character in pixels. + * @param c unicode character + * @return width in pixels to the start of the next character + */ float Fl_Android_Font_Descriptor::get_advance(uint32_t c) { return pFontSource->get_advance(c, size); } - +/** + * Get the pixels for a given Unicode character. + * @param c unicode character + * @return a bytemap + */ Fl_Android_Bytemap *Fl_Android_Font_Descriptor::get_bytemap(uint32_t c) { // TODO: cache bytemaps here for fast access @@ -186,7 +235,13 @@ Fl_Android_Bytemap *Fl_Android_Font_Descriptor::get_bytemap(uint32_t c) } -static Fl_Android_Font_Descriptor* find(Fl_Font fnum, Fl_Fontsize size) +/** + * Find or create a font descriptor for a given font and height. + * @param fnum index into fl_fonts + * @param size height in pixels + * @return an existing oder newly created descriptor + */ +Fl_Android_Font_Descriptor* Fl_Android_Font_Descriptor::find(Fl_Font fnum, Fl_Fontsize size) { Fl_Fontdesc &s = fl_fonts[fnum]; if (!s.name) s = fl_fonts[0]; // use 0 if fnum undefined @@ -208,21 +263,26 @@ static Fl_Android_Font_Descriptor* find(Fl_Font fnum, Fl_Fontsize size) // ============================================================================= - +/** + * Set a font for future use in text rendering calls. + * @param fnum index into fl_fonts + * @param size height in pixels + */ void Fl_Android_Graphics_Driver::font_unscaled(Fl_Font fnum, Fl_Fontsize size) { - Fl_Android_Application::log_e("FLTK is requesting font %d at %d pixels (%08x)", fnum, size, fl_fonts); - font_descriptor( find(fnum, size) ); + font_descriptor( Fl_Android_Font_Descriptor::find(fnum, size) ); size_ = size; font_ = fnum; } - +/** + * Copy a single letter to the screen. + * @param xx, yy position of character on screen + * @param c unicode character + * @return x position of next character on screen + */ int Fl_Android_Graphics_Driver::render_letter(int xx, int yy, uint32_t c) { -// unsigned char *bitmap; int oxx = xx; -// int w, h, size = 30; -// int dx, dy; // find the font descriptor Fl_Android_Font_Descriptor *fd = (Fl_Android_Font_Descriptor*)font_descriptor(); @@ -248,13 +308,13 @@ int Fl_Android_Graphics_Driver::render_letter(int xx, int yy, uint32_t c) *d = cc; } else if (v<50) { // 0% } else if (v>150) { // 75% - uint16_t nn = *d, nn14 = (nn&0xe79c)>>2; + uint16_t nn = *d, nn14 = (nn&(uint16_t(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; + uint16_t nn = *d, nn12 = (nn&(uint16_t(0xf7de)))>>1, nn14 = (nn12&(uint16_t(0xf7de)))>>1, nn34 = nn12+nn14; *d = nn34 + cc14; } else { // 50% - uint16_t nn = *d, nn12 = (nn&0xf7de)>>1; + uint16_t nn = *d, nn12 = (nn&(uint16_t(0xf7de)))>>1; *d = nn12 + cc12; } #else @@ -266,19 +326,146 @@ int Fl_Android_Graphics_Driver::render_letter(int xx, int yy, uint32_t c) } } delete bm; - return oxx + fd->get_advance(c); + return oxx + (int)(fd->get_advance(c)+0.5f); } - +/** + * Render a string to screen. + * @param str text in utf-8 encoding + * @param n number of bytes to render + * @param x, y position on screen + */ void Fl_Android_Graphics_Driver::draw_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]); + const char *e = str+n; + for (int i=0; i<n; ) { + int incr = 1; + unsigned uniChar = fl_utf8decode(str + i, e, &incr); + int x1 = x; + x = render_letter(x, y, uniChar); + Fl_Color old = fl_color(); + fl_color(FL_RED); + fl_xyline(x1, y, x); + fl_color(old); + i += incr; + } + } +} + +#if 0 + +// TODO: do we need that? +const char* Fl_Xlib_Graphics_Driver::get_font_name(Fl_Font fnum, int* ap) { + Fl_Xlib_Fontdesc *f = ((Fl_Xlib_Fontdesc*)fl_fonts) + fnum; + if (!f->fontname[0]) { + int type = 0; + const char* p = f->name; + if (!p) { + if (ap) *ap = 0; + return ""; + } + char *o = f->fontname; + + if (*p != '-') { // non-standard font, just replace * with spaces: + if (strstr(p,"bold")) type = FL_BOLD; + if (strstr(p,"ital")) type |= FL_ITALIC; + for (;*p; p++) { + if (*p == '*' || *p == ' ' || *p == '-') { + do p++; while (*p == '*' || *p == ' ' || *p == '-'); + if (!*p) break; + if (o < (f->fontname + ENDOFBUFFER - 1)) *o++ = ' '; + } + if (o < (f->fontname + ENDOFBUFFER - 1)) *o++ = *p; + } + *o = 0; + + } else { // standard dash-separated font: + + // get the family: + const char *x = fl_font_word(p,2); if (*x) x++; if (*x=='*') x++; + if (!*x) { + if (ap) *ap = 0; + return p; + } + const char *e = fl_font_word(x,1); + if ((e - x) < (int)(ENDOFBUFFER - 1)) { + // MRS: we want strncpy here, not strlcpy... + strncpy(o,x,e-x); + o += e-x; + } else { + strlcpy(f->fontname, x, ENDOFBUFFER); + o = f->fontname+ENDOFBUFFER-1; + } + + // collect all the attribute words: + for (int n = 3; n <= 6; n++) { + // get the next word: + if (*e) e++; x = e; e = fl_font_word(x,1); + int t = attribute(n,x); + if (t < 0) { + if (o < (f->fontname + ENDOFBUFFER - 1)) *o++ = ' '; + if ((e - x) < (int)(ENDOFBUFFER - (o - f->fontname) - 1)) { + // MRS: we want strncpy here, not strlcpy... + strncpy(o,x,e-x); + o += e-x; + } else { + strlcpy(o,x, ENDOFBUFFER - (o - f->fontname) - 1); + o = f->fontname+ENDOFBUFFER-1; + } + } else type |= t; + } + + // skip over the '*' for the size and get the registry-encoding: + x = fl_font_word(e,2); + if (*x) {x++; *o++ = '('; while (*x) *o++ = *x++; *o++ = ')';} + + *o = 0; + if (type & FL_BOLD) strlcat(f->fontname, " bold", ENDOFBUFFER); + if (type & FL_ITALIC) strlcat(f->fontname, " italic", ENDOFBUFFER); + } + f->fontname[ENDOFBUFFER] = (char)type; } + if (ap) *ap = f->fontname[ENDOFBUFFER]; + return f->fontname; } +#define ENDOFBUFFER sizeof(fl_fonts->fontname)-1 + +// turn a stored font name into a pretty name: +const char* Fl_Quartz_Graphics_Driver::get_font_name(Fl_Font fnum, int* ap) { + if (!fl_fonts) fl_fonts = calc_fl_fonts(); + Fl_Fontdesc *f = fl_fonts + fnum; + if (!f->fontname[0]) { + this->set_fontname_in_fontdesc(f); + const char* p = f->name; + if (!p || !*p) {if (ap) *ap = 0; return "";} + int type = 0; + if (strstr(f->name, "Bold")) type |= FL_BOLD; + if (strstr(f->name, "Italic") || strstr(f->name, "Oblique")) type |= FL_ITALIC; + f->fontname[ENDOFBUFFER] = (char)type; + } + if (ap) *ap = f->fontname[ENDOFBUFFER]; + return f->fontname; +} + + +int Fl_Quartz_Graphics_Driver::get_font_sizes(Fl_Font fnum, int*& sizep) { + static int array[128]; + if (!fl_fonts) fl_fonts = calc_fl_fonts(); + Fl_Fontdesc *s = fl_fonts+fnum; + if (!s->name) s = fl_fonts; // empty slot in table, use entry 0 + int cnt = 0; + + // ATS supports all font size + array[0] = 0; + sizep = array; + cnt = 1; + + return cnt; +} + +#endif // // End of "$Id$". |
