changeset 2547:dbd15c13f5bb

Android: Implement most of the font functions and control/widget color. Add an Android section in dwtest for picking fonts and folders. Minor update to the readme.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Fri, 14 May 2021 11:29:00 +0000
parents 897d94c20365
children c4d75d30430c
files android/DWindows.kt android/dw.cpp dwtest.c readme.txt
diffstat 4 files changed, 232 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/android/DWindows.kt	Thu May 13 22:52:11 2021 +0000
+++ b/android/DWindows.kt	Fri May 14 11:29:00 2021 +0000
@@ -240,6 +240,8 @@
 
 class DWRender(context: Context) : View(context) {
     var cachedCanvas: Canvas? = null
+    var typeface: Typeface? = null
+    var fontsize: Float? = null
 
     override fun onSizeChanged(width: Int, height: Int, oldWidth: Int, oldHeight: Int) {
         super.onSizeChanged(width, height, oldWidth, oldHeight)
@@ -686,6 +688,89 @@
         }
     }
 
+    fun typefaceFromFontName(fontname: String?): Typeface?
+    {
+        if(fontname != null) {
+            val bold: Boolean = fontname.contains(" Bold")
+            val italic: Boolean = fontname.contains(" Italic")
+            val font = fontname.substringAfter('.')
+            var fontFamily = font
+            var typeface: Typeface? = null
+
+            if (bold && font != null) {
+                fontFamily = font.substringBefore(" Bold")
+            } else if (italic && font != null) {
+                fontFamily = font.substringBefore(" Italic")
+            }
+
+            if (fontFamily != null) {
+                var style: Int = Typeface.NORMAL
+                if (bold && italic) {
+                    style = Typeface.BOLD_ITALIC
+                } else if (bold) {
+                    style = Typeface.BOLD
+                } else if (italic) {
+                    style = Typeface.ITALIC
+                }
+                typeface = Typeface.create(fontFamily, style)
+            }
+            return typeface
+        }
+        return Typeface.DEFAULT
+    }
+
+    fun windowSetFont(window: View, fontname: String?) {
+        var typeface: Typeface? = typefaceFromFontName(fontname)
+        var size: Float? = null
+
+        if(fontname != null) {
+            size = fontname.substringBefore('.').toFloatOrNull()
+        }
+
+        if(typeface != null) {
+            waitOnUiThread {
+                if (window is TextView) {
+                    var textview: TextView = window
+                    textview.typeface = typeface
+                    if(size != null) {
+                        textview.textSize = size
+                    }
+                } else if (window is Button) {
+                    var button: Button = window
+                    button.typeface = typeface
+                    if(size != null) {
+                        button.textSize = size
+                    }
+                } else if(window is DWRender) {
+                    var render: DWRender = window
+                    render.typeface = typeface
+                    if(size != null) {
+                        render.fontsize = size
+                    }
+                }
+            }
+        }
+    }
+
+    fun windowSetColor(window: View, falpha: Int, fred: Int, fgreen: Int, fblue: Int,
+                       balpha: Int, bred: Int, bgreen: Int, bblue: Int) {
+
+        waitOnUiThread {
+            if (window is TextView) {
+                var textview: TextView = window
+                textview.setTextColor(Color.rgb(fred, fgreen, fblue))
+                textview.setBackgroundColor(Color.rgb(bred, bgreen, bblue))
+            } else if (window is Button) {
+                var button: Button = window
+                button.setTextColor(Color.rgb(fred, fgreen, fblue))
+                button.setBackgroundColor(Color.rgb(bred, bgreen, bblue))
+            } else if(window is LinearLayout) {
+                var box: LinearLayout = window
+                box.setBackgroundColor(Color.rgb(bred, bgreen, bblue))
+            }
+        }
+    }
+
     fun windowSetText(window: View, text: String) {
         waitOnUiThread {
             if (window is TextView) {
@@ -2095,15 +2180,75 @@
         }
     }
 
-    fun drawText(render: DWRender?, bitmap: Bitmap?, x: Int, y: Int, text:String)
+    fun fontTextExtentsGet(render: DWRender?, bitmap: Bitmap?, text:String, typeface: Typeface?, fontsize: Int, window: View?): Long
+    {
+        var dimensions: Long = 0
+
+        waitOnUiThread {
+            var rect = Rect()
+
+            if (render != null) {
+                if (render.typeface != null) {
+                    paint.typeface = render.typeface
+                    if (render.fontsize != null && render.fontsize!! > 0F) {
+                        paint.textSize = render.fontsize!!
+                    }
+                }
+            } else if (bitmap != null) {
+                if (typeface != null) {
+                    paint.typeface = typeface
+                    if (fontsize > 0) {
+                        paint.textSize = fontsize.toFloat()
+                    }
+                } else if (window != null && window is DWRender) {
+                    val secondary: DWRender = window as DWRender
+
+                    if (secondary.typeface != null) {
+                        paint.typeface = secondary.typeface
+                        if (secondary.fontsize != null && secondary.fontsize!! > 0F) {
+                            paint.textSize = secondary.fontsize!!
+                        }
+                    }
+                }
+            }
+            paint.getTextBounds(text, 0, text.length, rect)
+            val textheight = rect.bottom - rect.top
+            val textwidth = rect.right - rect.left
+            dimensions = textwidth.toLong() or (textheight.toLong() shl 32)
+        }
+        return dimensions
+    }
+
+    fun drawText(render: DWRender?, bitmap: Bitmap?, x: Int, y: Int, text:String, typeface: Typeface?, fontsize: Int, window: View?)
     {
         waitOnUiThread {
             var canvas: Canvas? = null
 
-            if(render != null) {
+            if(render != null && render.cachedCanvas != null) {
                 canvas = render.cachedCanvas
+                if(render.typeface != null) {
+                    paint.typeface = render.typeface
+                    if(render.fontsize != null && render.fontsize!! > 0F) {
+                        paint.textSize = render.fontsize!!
+                    }
+                }
             } else if(bitmap != null) {
                 canvas = Canvas(bitmap)
+                if(typeface != null) {
+                    paint.typeface = typeface
+                    if(fontsize > 0) {
+                        paint.textSize = fontsize.toFloat()
+                    }
+                } else if(window != null && window is DWRender) {
+                    val secondary: DWRender = window as DWRender
+
+                    if(secondary.typeface != null) {
+                        paint.typeface = secondary.typeface
+                        if(secondary.fontsize != null && secondary.fontsize!! > 0F) {
+                            paint.textSize = secondary.fontsize!!
+                        }
+                    }
+                }
             }
 
             if(canvas != null) {
--- a/android/dw.cpp	Thu May 13 22:52:11 2021 +0000
+++ b/android/dw.cpp	Fri May 14 11:29:00 2021 +0000
@@ -2575,9 +2575,10 @@
         jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
         // Get the method that you want to call
         jmethodID drawLine = env->GetMethodID(clazz, "drawText",
-                                              "(Lorg/dbsoft/dwindows/DWRender;Landroid/graphics/Bitmap;IILjava/lang/String;)V");
+                                              "(Lorg/dbsoft/dwindows/DWRender;Landroid/graphics/Bitmap;IILjava/lang/String;Landroid/graphics/Typeface;ILandroid/view/View;)V");
         // Call the method on the object
-        env->CallVoidMethod(_dw_obj, drawLine, handle, pixmap ? pixmap->bitmap : NULL, x, y, jstr);
+        env->CallVoidMethod(_dw_obj, drawLine, handle, pixmap ? pixmap->bitmap : nullptr, x, y, jstr,
+                            pixmap ? pixmap->typeface : nullptr, pixmap ? pixmap->fontsize : 0, pixmap ? pixmap->handle : nullptr);
     }
 }
 
@@ -2591,6 +2592,27 @@
  */
 void API dw_font_text_extents_get(HWND handle, HPIXMAP pixmap, const char *text, int *width, int *height)
 {
+    JNIEnv *env;
+
+    if((handle || pixmap) && text && (width || height) && (env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
+    {
+        // Construct the string
+        jstring jstr = env->NewStringUTF(text);
+        // First get the class that contains the method you need to call
+        //jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
+        jclass clazz = env->FindClass(DW_CLASS_NAME);
+        // Get the method that you want to call
+        jmethodID fontTextExtentsGet = env->GetMethodID(clazz, "fontTextExtentsGet",
+                                                        "(Lorg/dbsoft/dwindows/DWRender;Landroid/graphics/Bitmap;Ljava/lang/String;Landroid/graphics/Typeface;ILandroid/view/View;)J");
+        // Call the method on the object
+        jlong dimensions = env->CallLongMethod(_dw_obj, fontTextExtentsGet, handle, pixmap ? pixmap->bitmap : nullptr, jstr,
+                            pixmap ? pixmap->typeface : nullptr, pixmap ? pixmap->fontsize : 0, pixmap ? pixmap->handle : nullptr);
+
+        if(width)
+            *width = dimensions & 0xFFFF;
+        if(height)
+            *height = (dimensions >> 32) & 0xFFFF;
+    }
 }
 
 /* Draw a polygon on a window (preferably a render window).
@@ -3586,6 +3608,29 @@
 */
 int API dw_pixmap_set_font(HPIXMAP pixmap, const char *fontname)
 {
+    JNIEnv *env;
+
+    if(pixmap && (env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
+    {
+        // Construct a string
+        jstring jstr = env->NewStringUTF(fontname);
+        // First get the class that contains the method you need to call
+        jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
+        // Get the method that you want to call
+        jmethodID typefaceFromFontName = env->GetMethodID(clazz, "typefaceFromFontName",
+                                                          "(Ljava/lang/String;)Landroid/graphics/Typeface;");
+        // Call the method on the object
+        jobject typeface = env->NewGlobalRef(env->CallObjectMethod(_dw_obj, typefaceFromFontName, jstr));
+        if(typeface)
+        {
+            jobject oldtypeface = pixmap->typeface;
+            pixmap->typeface = typeface;
+            if(oldtypeface)
+                env->DeleteGlobalRef(oldtypeface);
+            pixmap->fontsize = atoi(fontname);
+        }
+        return DW_ERROR_NONE;
+    }
     return DW_ERROR_GENERAL;
 }
 
@@ -4395,6 +4440,24 @@
  */
 int API dw_window_set_color(HWND handle, ULONG fore, ULONG back)
 {
+    JNIEnv *env;
+
+    if(handle && (env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
+    {
+        unsigned long _fore = _dw_get_color(fore);
+        unsigned long _back = _dw_get_color(back);
+
+        // First get the class that contains the method you need to call
+        jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
+        // Get the method that you want to call
+        jmethodID windowSetColor = env->GetMethodID(clazz, "windowSetColor",
+                                                    "(Landroid/view/View;IIIIIIII)V");
+        // Call the method on the object
+        env->CallVoidMethod(_dw_obj, windowSetColor, handle,
+                            0, (jint)DW_RED_VALUE(_fore), (jint)DW_GREEN_VALUE(_fore), (jint)DW_BLUE_VALUE(_fore),
+                            0, (jint)DW_RED_VALUE(_back), (jint)DW_GREEN_VALUE(_back), (jint)DW_BLUE_VALUE(_back));
+        return DW_ERROR_NONE;
+    }
     return DW_ERROR_GENERAL;
 }
 
@@ -4491,6 +4554,21 @@
  */
 int API dw_window_set_font(HWND handle, const char *fontname)
 {
+    JNIEnv *env;
+
+    if(handle && (env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
+    {
+        // Construct a string
+        jstring jstr = env->NewStringUTF(fontname);
+        // First get the class that contains the method you need to call
+        jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
+        // Get the method that you want to call
+        jmethodID windowHideShow = env->GetMethodID(clazz, "windowSetFont",
+                                                    "(Landroid/view/View;Ljava/lang/String;)V");
+        // Call the method on the object
+        env->CallVoidMethod(_dw_obj, windowHideShow, handle, jstr);
+        return DW_ERROR_NONE;
+    }
     return DW_ERROR_GENERAL;
 }
 
--- a/dwtest.c	Thu May 13 22:52:11 2021 +0000
+++ b/dwtest.c	Fri May 14 11:29:00 2021 +0000
@@ -29,6 +29,10 @@
 #define FIXEDFONT "9.Monaco"
 #define FOLDER_ICON_NAME "folder"
 #define FILE_ICON_NAME "file"
+#elif defined(__ANDROID__)
+#define FIXEDFONT "10.Monospace"
+#define FOLDER_ICON_NAME "folder"
+#define FILE_ICON_NAME "file"
 #elif GTK_MAJOR_VERSION > 1
 #define FIXEDFONT "10.monospace"
 #define FOLDER_ICON_NAME "gtk/folder"
--- a/readme.txt	Thu May 13 22:52:11 2021 +0000
+++ b/readme.txt	Fri May 14 11:29:00 2021 +0000
@@ -86,7 +86,7 @@
 Added new function dw_window_compare() to check if two window handles
     reference the same object.  Necessary in the Android port since
     handles passed to callbacks are local references, so they don't
-    match the handles saved during window creation.
+    always match the handles saved during window creation.
 Added support for dw_window_set_font() with a NULL font parameter.
     This resets the font used on the widget to the default font.
 Fixed GTK warnings on GTK3 caused by using Pango style font syntax.