AOSP10 TWRP Merge: fix conflicts and update libraries needed

This allows flame to boot TWRP. Still will need to work on
super partition for vendor and system access.

The plan will be to cherry-pick any updates to android-9.0
through gerrit.twrp.me to this branch as a WIP.
diff --git a/minuitwrp/Android.mk b/minuitwrp/Android.mk
index 2ca2091..99f9a23 100644
--- a/minuitwrp/Android.mk
+++ b/minuitwrp/Android.mk
@@ -201,7 +201,7 @@
 ifeq ($(shell test $(PLATFORM_SDK_VERSION) -gt 25; echo $$?),0)
 LOCAL_SHARED_LIBRARIES += libcutils liblog libutils
 endif
-LOCAL_MODULE_TAGS := eng
+LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE := libminuitwrp
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/minuitwrp/graphics.cpp b/minuitwrp/graphics.cpp
old mode 100644
new mode 100755
index 47ff3b9..8abf8eb
--- a/minuitwrp/graphics.cpp
+++ b/minuitwrp/graphics.cpp
@@ -37,6 +37,7 @@
 #include "graphics.h"
 // For std::min and std::max
 #include <algorithm>
+#include "truetype.hpp"
 
 struct GRFont {
     GRSurface* texture;
@@ -70,25 +71,25 @@
     if (!s || strlen(s) == 0 || !font)
         return 0;
 
-    measured_height = gr_ttf_getMaxFontHeight(font);
+    measured_height = twrpTruetype::gr_ttf_getMaxFontHeight(font);
 
     if (scale) {
-        measured_width = gr_ttf_measureEx(s, vfont);
+        measured_width = twrpTruetype::gr_ttf_measureEx(s, vfont);
         if (measured_width > max_width) {
             // Adjust font size down until the text fits
-            void *new_font = gr_ttf_scaleFont(vfont, max_width, measured_width);
+            void *new_font = twrpTruetype::gr_ttf_scaleFont(vfont, max_width, measured_width);
             if (!new_font) {
                 printf("gr_textEx_scaleW new_font is NULL\n");
                 return 0;
             }
-            measured_width = gr_ttf_measureEx(s, new_font);
+            measured_width = twrpTruetype::gr_ttf_measureEx(s, new_font);
             // These next 2 lines adjust the y point based on the new font's height
-            new_height = gr_ttf_getMaxFontHeight(new_font);
+            new_height = twrpTruetype::gr_ttf_getMaxFontHeight(new_font);
             y_scale = (measured_height - new_height) / 2;
             vfont = new_font;
         }
     } else
-        measured_width = gr_ttf_measureEx(s, vfont);
+        measured_width = twrpTruetype::gr_ttf_measureEx(s, vfont);
 
     int x_adj = measured_width;
     if (measured_width > max_width)
@@ -107,7 +108,7 @@
         else if (placement == BOTTOM_LEFT || placement == BOTTOM_RIGHT)
             y -= measured_height;
     }
-    return gr_ttf_textExWH(gl, x, y + y_scale, s, vfont, measured_width + x, -1, gr_draw);
+    return twrpTruetype::gr_ttf_textExWH(gl, x, y + y_scale, s, vfont, measured_width + x, -1, gr_draw);
 }
 
 void gr_clip(int x, int y, int w, int h)
diff --git a/minuitwrp/truetype.cpp b/minuitwrp/truetype.cpp
old mode 100644
new mode 100755
index 0416b0e..3dffbe4
--- a/minuitwrp/truetype.cpp
+++ b/minuitwrp/truetype.cpp
@@ -1,3 +1,21 @@
+/*
+		Copyright 2012 to 2020 TeamWin
+		This file is part of TWRP/TeamWin Recovery Project.
+
+		TWRP is free software: you can redistribute it and/or modify
+		it under the terms of the GNU General Public License as published by
+		the Free Software Foundation, either version 3 of the License, or
+		(at your option) any later version.
+
+		TWRP is distributed in the hope that it will be useful,
+		but WITHOUT ANY WARRANTY; without even the implied warranty of
+		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+		GNU General Public License for more details.
+
+		You should have received a copy of the GNU General Public License
+		along with TWRP.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
 #include <stdbool.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -5,856 +23,631 @@
 #include <errno.h>
 #include <stdio.h>
 
-#include "minui.h"
-
-#include <cutils/hashmap.h>
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_GLYPH_H
-
-#include <pixelflinger/pixelflinger.h>
 #include <pthread.h>
-// For std::min and std::max
 #include <algorithm>
-
-#define STRING_CACHE_MAX_ENTRIES 400
-#define STRING_CACHE_TRUNCATE_ENTRIES 150
-
-typedef struct
-{
-    int size;
-    int dpi;
-    char *path;
-} TrueTypeFontKey;
-
-typedef struct
-{
-    int type;
-    int refcount;
-    int size;
-    int dpi;
-    int max_height;
-    int base;
-    FT_Face face;
-    Hashmap *glyph_cache;
-    Hashmap *string_cache;
-    struct StringCacheEntry *string_cache_head;
-    struct StringCacheEntry *string_cache_tail;
-    pthread_mutex_t mutex;
-    TrueTypeFontKey *key;
-} TrueTypeFont;
-
-typedef struct
-{
-    FT_BBox bbox;
-    FT_BitmapGlyph glyph;
-} TrueTypeCacheEntry;
-
-typedef struct
-{
-    char *text;
-    int max_width;
-} StringCacheKey;
-
-struct StringCacheEntry
-{
-    GGLSurface surface;
-    int rendered_bytes; // number of bytes from C string rendered, not number of UTF8 characters!
-    StringCacheKey *key;
-    struct StringCacheEntry *prev;
-    struct StringCacheEntry *next;
-};
-
-typedef struct StringCacheEntry StringCacheEntry;
-
-typedef struct
-{
-    FT_Library ft_library;
-    Hashmap *fonts;
-    pthread_mutex_t mutex;
-} FontData;
+#include <string>
+#include "truetype.hpp"
 
 static FontData font_data = {
-    .ft_library = NULL,
-    .fonts = NULL,
-    .mutex = PTHREAD_MUTEX_INITIALIZER,
+	.ft_library = NULL,
+	.mutex = PTHREAD_MUTEX_INITIALIZER
 };
 
-#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
-#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
+twrpTruetype::twrpTruetype(void) {
 
-// 32bit FNV-1a hash algorithm
-// http://isthe.com/chongo/tech/comp/fnv/#FNV-1a
-static const uint32_t FNV_prime = 16777619U;
-static const uint32_t offset_basis = 2166136261U;
-
-static uint32_t fnv_hash(void *data, uint32_t len)
-{
-    uint8_t *d8 = (uint8_t *)data;
-    uint32_t *d32 = (uint32_t *)data;
-    uint32_t i, max;
-    uint32_t hash = offset_basis;
-
-    max = len/4;
-
-    // 32 bit data
-    for(i = 0; i < max; ++i)
-    {
-        hash ^= *d32++;
-        hash *= FNV_prime;
-    }
-
-    // last bits
-    for(i *= 4; i < len; ++i)
-    {
-        hash ^= (uint32_t) d8[i];
-        hash *= FNV_prime;
-    }
-    return hash;
 }
 
-static inline uint32_t fnv_hash_add(uint32_t cur_hash, uint32_t word)
-{
-    cur_hash ^= word;
-    cur_hash *= FNV_prime;
-    return cur_hash;
+int twrpTruetype::utf8_to_unicode(const char* pIn, unsigned int *pOut) {
+	int utf_bytes = 1;
+	unsigned int unicode = 0;
+	unsigned char tmp;
+	tmp = (unsigned char)*pIn++;
+	if (tmp < 0x80)
+	{
+		*pOut = tmp;
+	}
+	else
+	{
+		unsigned int high_bit_mask = 0x3F;
+		unsigned int high_bit_shift = 0;
+		int total_bits = 0;
+		while((tmp & 0xC0) == 0xC0)
+		{
+			utf_bytes ++;
+			if(utf_bytes > 6)
+			{
+				*pOut = tmp;
+				return 1;
+			}
+			tmp = 0xFF & (tmp << 1);
+			total_bits += 6;
+			high_bit_mask >>= 1;
+			high_bit_shift++;
+			unicode <<= 6;
+			unicode |= (*pIn++) & 0x3F;
+		}
+		unicode |= ((tmp >> high_bit_shift) & high_bit_mask) << total_bits;
+		*pOut = unicode;
+	}
+
+	return utf_bytes;
 }
 
-int utf8_to_unicode(const char* pIn, unsigned int *pOut)
-{
-    int utf_bytes = 1;
-    unsigned int unicode = 0;
-    unsigned char tmp;
-    tmp = (unsigned char)*pIn++;
-    if (tmp < 0x80)
-    {
-        *pOut = tmp;
-    }
-    else
-    {
-        unsigned int high_bit_mask = 0x3F;
-        unsigned int high_bit_shift = 0;
-        int total_bits = 0;
-        while((tmp & 0xC0) == 0xC0)
-        {
-            utf_bytes ++;
-            if(utf_bytes > 6)
-            {
-                *pOut = tmp;
-                return 1;
-            }
-            tmp = 0xFF & (tmp << 1);
-            total_bits += 6;
-            high_bit_mask >>= 1;
-            high_bit_shift++;
-            unicode <<= 6;
-            unicode |= (*pIn++) & 0x3F;
-        }
-        unicode |= ((tmp >> high_bit_shift) & high_bit_mask) << total_bits;
-        *pOut = unicode;
-    }
+void* twrpTruetype::gr_ttf_loadFont(const char *filename, int size, int dpi) {
+	int error;
+	TrueTypeFont* res = nullptr;
+	TrueTypeFontKey* key;
 
-    return utf_bytes;
-}
+	pthread_mutex_lock(&font_data.mutex);
 
-static bool gr_ttf_string_cache_equals(void *keyA, void *keyB)
-{
-    StringCacheKey *a = (StringCacheKey *)keyA;
-    StringCacheKey *b = (StringCacheKey *)keyB;
-    return a->max_width == b->max_width && strcmp(a->text, b->text) == 0;
-}
+	TrueTypeFontKey k = {
+		.size = size,
+		.dpi = dpi,
+		.path = (char*)filename
+	};
 
-static int gr_ttf_string_cache_hash(void *key)
-{
-    StringCacheKey *k = (StringCacheKey *)key;
-    return fnv_hash(k->text, strlen(k->text));
-}
+	TrueTypeFontMap::iterator ttfIter = font_data.fonts.find(k);
 
-static bool gr_ttf_font_cache_equals(void *keyA, void *keyB)
-{
-    TrueTypeFontKey *a = (TrueTypeFontKey *)keyA;
-    TrueTypeFontKey *b = (TrueTypeFontKey *)keyB;
-    return (a->size == b->size) && (a->dpi == b->dpi) && !strcmp(a->path, b->path);
-}
+	if (ttfIter != font_data.fonts.end())
+	{
+		res = ttfIter->second;
+		++res->refcount;
+		goto exit;
+	}
 
-static int gr_ttf_font_cache_hash(void *key)
-{
-    TrueTypeFontKey *k = (TrueTypeFontKey *)key;
+	if(!font_data.ft_library)
+	{
+		error = FT_Init_FreeType(&font_data.ft_library);
+		if(error)
+		{
+			fprintf(stderr, "Failed to init libfreetype! %d\n", error);
+			goto exit;
+		}
+	}
 
-    uint32_t hash = fnv_hash(k->path, strlen(k->path));
-    hash = fnv_hash_add(hash, k->size);
-    hash = fnv_hash_add(hash, k->dpi);
-    return hash;
-}
+	FT_Face face;
+	error = FT_New_Face(font_data.ft_library, filename, 0, &face);
+	if(error)
+	{
+		fprintf(stderr, "Failed to load truetype face %s: %d\n", filename, error);
+		goto exit;
+	}
 
-void *gr_ttf_loadFont(const char *filename, int size, int dpi)
-{
-    int error;
-    TrueTypeFont *res = NULL;
-    TrueTypeFontKey *key = NULL;
+	error = FT_Set_Char_Size(face, 0, size*16, dpi, dpi);
+	if(error)
+	{
+		 fprintf(stderr, "Failed to set truetype face size to %d, dpi %d: %d\n", size, dpi, error);
+		 FT_Done_Face(face);
+		 goto exit;
+	}
 
-    pthread_mutex_lock(&font_data.mutex);
+	res = new TrueTypeFont;
+	res->type = FONT_TYPE_TTF;
+	res->size = size;
+	res->dpi = dpi;
+	res->face = face;
+	res->max_height = -1;
+	res->base = -1;
+	res->refcount = 1;
 
-    if(font_data.fonts)
-    {
-        TrueTypeFontKey k = {
-            .size = size,
-            .dpi = dpi,
-            .path = (char*)filename
-        };
+	pthread_mutex_init(&res->mutex, 0);
 
-        res = (TrueTypeFont *)hashmapGet(font_data.fonts, &k);
-        if(res)
-        {
-            ++res->refcount;
-            goto exit;
-        }
-    }
+	key = new TrueTypeFontKey;
+	key->path = strdup(filename);
+	key->size = size;
+	key->dpi = dpi;
 
-    if(!font_data.ft_library)
-    {
-        error = FT_Init_FreeType(&font_data.ft_library);
-        if(error)
-        {
-            fprintf(stderr, "Failed to init libfreetype! %d\n", error);
-            goto exit;
-        }
-    }
-
-    FT_Face face;
-    error = FT_New_Face(font_data.ft_library, filename, 0, &face);
-    if(error)
-    {
-        fprintf(stderr, "Failed to load truetype face %s: %d\n", filename, error);
-        goto exit;
-    }
-
-    error = FT_Set_Char_Size(face, 0, size*16, dpi, dpi);
-    if(error)
-    {
-         fprintf(stderr, "Failed to set truetype face size to %d, dpi %d: %d\n", size, dpi, error);
-         FT_Done_Face(face);
-         goto exit;
-    }
-
-    res = (TrueTypeFont *)malloc(sizeof(TrueTypeFont));
-    memset(res, 0, sizeof(TrueTypeFont));
-    res->type = FONT_TYPE_TTF;
-    res->size = size;
-    res->dpi = dpi;
-    res->face = face;
-    res->max_height = -1;
-    res->base = -1;
-    res->refcount = 1;
-    res->glyph_cache = hashmapCreate(32, hashmapIntHash, hashmapIntEquals);
-    res->string_cache = hashmapCreate(128, gr_ttf_string_cache_hash, gr_ttf_string_cache_equals);
-    pthread_mutex_init(&res->mutex, 0);
-
-    if(!font_data.fonts)
-        font_data.fonts = hashmapCreate(4, gr_ttf_font_cache_hash, gr_ttf_font_cache_equals);
-
-    key = (TrueTypeFontKey *)malloc(sizeof(TrueTypeFontKey));
-    memset(key, 0, sizeof(TrueTypeFontKey));
-    key->path = strdup(filename);
-    key->size = size;
-    key->dpi = dpi;
-
-    res->key = key;
-
-    hashmapPut(font_data.fonts, key, res);
+	res->key = key;
+	font_data.fonts[*key] = res;
 
 exit:
-    pthread_mutex_unlock(&font_data.mutex);
-    return res;
+	pthread_mutex_unlock(&font_data.mutex);
+	return res;
 }
 
-void *gr_ttf_scaleFont(void *font, int max_width, int measured_width)
-{
-    if (!font)
-        return NULL;
+void* twrpTruetype::gr_ttf_scaleFont(void *font, int max_width, int measured_width) {
+	if (!font)
+		return nullptr;
 
-    TrueTypeFont *f = (TrueTypeFont *)font;
-    float scale_value = (float)(max_width) / (float)(measured_width);
-    int new_size = ((int)((float)f->size * scale_value)) - 1;
-    if (new_size < 1)
-        new_size = 1;
-    const char* file = f->key->path;
-    int dpi = f->dpi;
-    return gr_ttf_loadFont(file, new_size, dpi);
+	TrueTypeFont *f = (TrueTypeFont *)font;
+	float scale_value = (float)(max_width) / (float)(measured_width);
+	int new_size = ((int)((float)f->size * scale_value)) - 1;
+	if (new_size < 1)
+		new_size = 1;
+	const char* file = f->key->path;
+	int dpi = f->dpi;
+	return gr_ttf_loadFont(file, new_size, dpi);
 }
 
-static bool gr_ttf_freeFontCache(void *key, void *value, void *context __unused)
+static bool gr_ttf_freeFontCache(void *value, void *context __unused)
 {
-    TrueTypeCacheEntry *e = (TrueTypeCacheEntry *)value;
-    FT_Done_Glyph((FT_Glyph)e->glyph);
-    free(e);
-    free(key);
-    return true;
+	TrueTypeCacheEntry *e = (TrueTypeCacheEntry *)value;
+	FT_Done_Glyph((FT_Glyph)e->glyph);
+	free(e);
+	return true;
 }
 
-static bool gr_ttf_freeStringCache(void *key, void *value, void *context __unused)
-{
-    StringCacheKey *k = (StringCacheKey *)key;
-    free(k->text);
-    free(k);
+bool twrpTruetype::gr_ttf_freeStringCache(void *key, void *value, void *context __unused) {
+	StringCacheKey *k = (StringCacheKey *)key;
+	delete k->text;
+	delete k;
 
-    StringCacheEntry *e = (StringCacheEntry *)value;
-    free(e->surface.data);
-    free(e);
-    return true;
+	StringCacheEntry *e = (StringCacheEntry *)value;
+	delete e->surface.data;
+	delete e;
+	return true;
 }
 
-void gr_ttf_freeFont(void *font)
-{
-    pthread_mutex_lock(&font_data.mutex);
+void twrpTruetype::gr_ttf_freeFont(void *font) {
+	pthread_mutex_lock(&font_data.mutex);
 
-    TrueTypeFont *d = (TrueTypeFont *)font;
+	TrueTypeFont *d = (TrueTypeFont *)font;
+	if(--d->refcount == 0)
+	{
+		delete d->key->path;
+		delete d->key;
 
-    if(--d->refcount == 0)
-    {
-        hashmapRemove(font_data.fonts, d->key);
+		FT_Done_Face(d->face);
 
-        if(hashmapSize(font_data.fonts) == 0)
-        {
-            hashmapFree(font_data.fonts);
-            font_data.fonts = NULL;
-        }
+		StringCacheMap::iterator stringCacheEntryIt = d->string_cache.begin();
+		while (stringCacheEntryIt != d->string_cache.end()) {
+			gr_ttf_freeStringCache(stringCacheEntryIt->second->key, stringCacheEntryIt->second, NULL);
+			stringCacheEntryIt = d->string_cache.erase(stringCacheEntryIt);
+		}
 
-        free(d->key->path);
-        free(d->key);
+		TrueTypeCacheEntryMap::iterator ttcIt = d->glyph_cache.begin();
+		while(ttcIt != d->glyph_cache.end()) {
+			gr_ttf_freeFontCache(ttcIt->second, NULL);
+			ttcIt = d->glyph_cache.erase(ttcIt);
+		}
 
-        FT_Done_Face(d->face);
-        hashmapForEach(d->string_cache, gr_ttf_freeStringCache, NULL);
-        hashmapFree(d->string_cache);
-        hashmapForEach(d->glyph_cache, gr_ttf_freeFontCache, NULL);
-        hashmapFree(d->glyph_cache);
-        pthread_mutex_destroy(&d->mutex);
-        free(d);
-    }
+		pthread_mutex_destroy(&d->mutex);
 
-    pthread_mutex_unlock(&font_data.mutex);
+		TrueTypeFontMap::iterator trueTypeFontIt = font_data.fonts.find(*(d->key));
+		delete d;
+		font_data.fonts.erase(trueTypeFontIt);
+
+	}
+
+	pthread_mutex_unlock(&font_data.mutex);
 }
 
-static TrueTypeCacheEntry *gr_ttf_glyph_cache_peek(TrueTypeFont *font, int char_index)
-{
-    return (TrueTypeCacheEntry *)hashmapGet(font->glyph_cache, &char_index);
+TrueTypeCacheEntry* twrpTruetype::gr_ttf_glyph_cache_peek(TrueTypeFont *font, int char_index) {
+	TrueTypeCacheEntryMap::iterator glyphCacheItr = font->glyph_cache.find(char_index);
+
+	if(glyphCacheItr != font->glyph_cache.end()) {
+		return font->glyph_cache[char_index];
+	}
+	return nullptr;
 }
 
-static TrueTypeCacheEntry *gr_ttf_glyph_cache_get(TrueTypeFont *font, int char_index)
-{
-    TrueTypeCacheEntry *res = (TrueTypeCacheEntry *)hashmapGet(font->glyph_cache, &char_index);
-    if(!res)
-    {
-        int error = FT_Load_Glyph(font->face, char_index, FT_LOAD_RENDER);
-        if(error)
-        {
-            fprintf(stderr, "Failed to load glyph idx %d: %d\n", char_index, error);
-            return NULL;
-        }
+TrueTypeCacheEntry* twrpTruetype::gr_ttf_glyph_cache_get(TrueTypeFont *font, int char_index) {
+	TrueTypeCacheEntryMap::iterator glyphCacheItr = font->glyph_cache.find(char_index);
+	TrueTypeCacheEntry* res = nullptr;
+	if(glyphCacheItr == font->glyph_cache.end())
+	{
+		int error = FT_Load_Glyph(font->face, char_index, FT_LOAD_RENDER);
+		if(error)
+		{
+			fprintf(stderr, "Failed to load glyph idx %d: %d\n", char_index, error);
+			return NULL;
+		}
 
-        FT_BitmapGlyph glyph;
-        error = FT_Get_Glyph(font->face->glyph, (FT_Glyph*)&glyph);
-        if(error)
-        {
-            fprintf(stderr, "Failed to copy glyph %d: %d\n", char_index, error);
-            return NULL;
-        }
+		FT_BitmapGlyph glyph;
+		error = FT_Get_Glyph(font->face->glyph, (FT_Glyph*)&glyph);
+		if(error)
+		{
+			fprintf(stderr, "Failed to copy glyph %d: %d\n", char_index, error);
+			return NULL;
+		}
 
-        res = (TrueTypeCacheEntry *)malloc(sizeof(TrueTypeCacheEntry));
-        memset(res, 0, sizeof(TrueTypeCacheEntry));
-        res->glyph = glyph;
-        FT_Glyph_Get_CBox((FT_Glyph)glyph, FT_GLYPH_BBOX_PIXELS, &res->bbox);
+		res = new TrueTypeCacheEntry;
+		res->glyph = glyph;
+		FT_Glyph_Get_CBox((FT_Glyph)glyph, FT_GLYPH_BBOX_PIXELS, &res->bbox);
+		font->glyph_cache[char_index] = res;
+	}
+	else {
+		res = glyphCacheItr->second;
+	}
 
-        int *key = (int *)malloc(sizeof(int));
-        *key = char_index;
-
-        hashmapPut(font->glyph_cache, key, res);
-    }
-
-    return res;
+	return res;
 }
 
-static int gr_ttf_copy_glyph_to_surface(GGLSurface *dest, FT_BitmapGlyph glyph, int offX, int offY, int base)
-{
-    unsigned y;
-    uint8_t *src_itr = glyph->bitmap.buffer;
-    uint8_t *dest_itr = dest->data;
+int twrpTruetype::gr_ttf_copy_glyph_to_surface(GGLSurface *dest, FT_BitmapGlyph glyph, int offX, int offY, int base) {
+	unsigned y;
+	uint8_t *src_itr = glyph->bitmap.buffer;
+	uint8_t *dest_itr = dest->data;
 
-    if(glyph->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY)
-    {
-        fprintf(stderr, "Unsupported pixel mode in FT_BitmapGlyph %d\n", glyph->bitmap.pixel_mode);
-        return -1;
-    }
+	if(glyph->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY)
+	{
+		fprintf(stderr, "Unsupported pixel mode in FT_BitmapGlyph %d\n", glyph->bitmap.pixel_mode);
+		return -1;
+	}
 
-    dest_itr += (offY + base - glyph->top)*dest->stride + (offX + glyph->left);
+	dest_itr += (offY + base - glyph->top)*dest->stride + (offX + glyph->left);
 
-    // FIXME: if glyph->left is negative and everything else is 0 (e.g. letter 'j' in Roboto-Regular),
-    // the result might end up being before the buffer - I'm not sure how to properly handle this.
-    if(dest_itr < dest->data)
-        dest_itr = dest->data;
+	// FIXME: if glyph->left is negative and everything else is 0 (e.g. letter 'j' in Roboto-Regular),
+	// the result might end up being before the buffer - I'm not sure how to properly handle this.
+	if(dest_itr < dest->data)
+		dest_itr = dest->data;
 
-    for(y = 0; y < glyph->bitmap.rows; ++y)
-    {
-        memcpy(dest_itr, src_itr, glyph->bitmap.width);
-        src_itr += glyph->bitmap.pitch;
-        dest_itr += dest->stride;
-    }
-    return 0;
+	for(y = 0; y < glyph->bitmap.rows; ++y)
+	{
+		memcpy(dest_itr, src_itr, glyph->bitmap.width);
+		src_itr += glyph->bitmap.pitch;
+		dest_itr += dest->stride;
+	}
+	return 0;
 }
 
-static void gr_ttf_calcMaxFontHeight(TrueTypeFont *f)
-{
-    char c;
-    int char_idx;
-    int error;
-    FT_Glyph glyph;
-    FT_BBox bbox;
-    FT_BBox bbox_glyph;
-    TrueTypeCacheEntry *ent;
+void twrpTruetype::gr_ttf_calcMaxFontHeight(TrueTypeFont *f) {
+	char c;
+	int char_idx;
+	int error;
+	FT_Glyph glyph;
+	FT_BBox bbox;
+	FT_BBox bbox_glyph;
+	TrueTypeCacheEntry *ent;
 
-    bbox.yMin = bbox_glyph.yMin = LONG_MAX;
-    bbox.yMax = bbox_glyph.yMax = LONG_MIN;
+	bbox.yMin = bbox_glyph.yMin = LONG_MAX;
+	bbox.yMax = bbox_glyph.yMax = LONG_MIN;
 
-    for(c = '!'; c <= '~'; ++c)
-    {
-        char_idx = FT_Get_Char_Index(f->face, c);
-        ent = gr_ttf_glyph_cache_peek(f, char_idx);
-        if(ent)
-        {
-            bbox.yMin = MIN(bbox.yMin, ent->bbox.yMin);
-            bbox.yMax = MAX(bbox.yMax, ent->bbox.yMax);
-        }
-        else
-        {
-            error = FT_Load_Glyph(f->face, char_idx, 0);
-            if(error)
-                continue;
+	for(c = '!'; c <= '~'; ++c)
+	{
+		char_idx = FT_Get_Char_Index(f->face, c);
+		ent = gr_ttf_glyph_cache_peek(f, char_idx);
+		if(ent)
+		{
+			bbox.yMin = MIN(bbox.yMin, ent->bbox.yMin);
+			bbox.yMax = MAX(bbox.yMax, ent->bbox.yMax);
+		}
+		else
+		{
+			error = FT_Load_Glyph(f->face, char_idx, 0);
+			if(error)
+				continue;
 
-            error = FT_Get_Glyph(f->face->glyph, &glyph);
-            if(error)
-                continue;
+			error = FT_Get_Glyph(f->face->glyph, &glyph);
+			if(error)
+				continue;
 
-            FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &bbox_glyph);
-            bbox.yMin = MIN(bbox.yMin, bbox_glyph.yMin);
-            bbox.yMax = MAX(bbox.yMax, bbox_glyph.yMax);
+			FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &bbox_glyph);
+			bbox.yMin = MIN(bbox.yMin, bbox_glyph.yMin);
+			bbox.yMax = MAX(bbox.yMax, bbox_glyph.yMax);
 
-            FT_Done_Glyph(glyph);
-        }
-    }
+			FT_Done_Glyph(glyph);
+		}
+	}
 
-    if(bbox.yMin > bbox.yMax)
-        bbox.yMin = bbox.yMax = 0;
+	if(bbox.yMin > bbox.yMax)
+		bbox.yMin = bbox.yMax = 0;
 
-    f->max_height = bbox.yMax - bbox.yMin;
-    f->base = bbox.yMax;
+	f->max_height = bbox.yMax - bbox.yMin;
+	f->base = bbox.yMax;
 
-    // FIXME: twrp fonts have some padding on top, I'll add it here
-    // Should be fixed in the themes
-    f->max_height += f->size / 4;
-    f->base += f->size / 4;
+	// FIXME: twrp fonts have some padding on top, I'll add it here
+	// Should be fixed in the themes
+	f->max_height += f->size / 4;
+	f->base += f->size / 4;
 }
 
 // returns number of bytes from const char *text rendered to fit max_width, not number of UTF8 characters!
-static int gr_ttf_render_text(TrueTypeFont *font, GGLSurface *surface, const char *text, int max_width)
-{
-    TrueTypeFont *f = font;
-    TrueTypeCacheEntry *ent;
-    int bytes_rendered = 0, total_w = 0;
-    int utf_bytes = 0;
-    unsigned int unicode = 0;
-    int i, x, diff, char_idx, prev_idx = 0;
-    int height;
-    FT_Vector delta;
-    uint8_t *data = NULL;
-    const char *text_itr = text;
-    int *char_idxs;
-    int char_idxs_len = 0;
+int twrpTruetype::gr_ttf_render_text(TrueTypeFont *font, GGLSurface *surface, const char *text, int max_width) {
+	TrueTypeFont *f = font;
+	TrueTypeCacheEntry *ent;
+	int bytes_rendered = 0, total_w = 0;
+	int utf_bytes = 0;
+	unsigned int unicode = 0;
+	int i, x, diff, char_idx, prev_idx = 0;
+	int height;
+	FT_Vector delta;
+	uint8_t *data = NULL;
+	const char *text_itr = text;
+	int *char_idxs;
+	int char_idxs_len = 0;
 
-    char_idxs = (int *)malloc(strlen(text) * sizeof(int));
+	char_idxs = new int[strlen(text)];
 
-    while(*text_itr)
-    {
-        utf_bytes = utf8_to_unicode(text_itr, &unicode);
-        text_itr += utf_bytes;
-        bytes_rendered += utf_bytes;
+	while(*text_itr)
+	{
+		utf_bytes = utf8_to_unicode(text_itr, &unicode);
+		text_itr += utf_bytes;
+		bytes_rendered += utf_bytes;
 
-        char_idx = FT_Get_Char_Index(f->face, unicode);
-        char_idxs[char_idxs_len] = char_idx;
+		char_idx = FT_Get_Char_Index(f->face, unicode);
+		char_idxs[char_idxs_len] = char_idx;
+		ent = gr_ttf_glyph_cache_get(f, char_idx);
+		if(ent)
+		{
+			diff = ent->glyph->root.advance.x >> 16;
 
-        ent = gr_ttf_glyph_cache_get(f, char_idx);
-        if(ent)
-        {
-            diff = ent->glyph->root.advance.x >> 16;
+			if(FT_HAS_KERNING(f->face) && prev_idx && char_idx)
+			{
+				FT_Get_Kerning(f->face, prev_idx, char_idx, FT_KERNING_DEFAULT, &delta);
+				diff += delta.x >> 6;
+			}
 
-            if(FT_HAS_KERNING(f->face) && prev_idx && char_idx)
-            {
-                FT_Get_Kerning(f->face, prev_idx, char_idx, FT_KERNING_DEFAULT, &delta);
-                diff += delta.x >> 6;
-            }
+			if(max_width != -1 && total_w + diff > max_width)
+				break;
 
-            if(max_width != -1 && total_w + diff > max_width)
-                break;
+			total_w += diff;
+		}
+		prev_idx = char_idx;
+		++char_idxs_len;
+	}
 
-            total_w += diff;
-        }
-        prev_idx = char_idx;
-        ++char_idxs_len;
-    }
+	if(font->max_height == -1)
+		gr_ttf_calcMaxFontHeight(font);
 
-    if(font->max_height == -1)
-        gr_ttf_calcMaxFontHeight(font);
+	if(font->max_height == -1)
+	{
+		delete [] char_idxs;
+		return -1;
+	}
 
-    if(font->max_height == -1)
-    {
-        free(char_idxs);
-        return -1;
-    }
+	height = font->max_height;
 
-    height = font->max_height;
+	data = new uint8_t[total_w * height];
+	x = 0;
+	prev_idx = 0;
 
-    data = (uint8_t *)malloc(total_w*height);
-    memset(data, 0, total_w*height);
-    x = 0;
-    prev_idx = 0;
+	surface->version = sizeof(*surface);
+	surface->width = total_w;
+	surface->height = height;
+	surface->stride = total_w;
+	surface->data = (GGLubyte*)data;
+	surface->format = GGL_PIXEL_FORMAT_A_8;
 
-    surface->version = sizeof(*surface);
-    surface->width = total_w;
-    surface->height = height;
-    surface->stride = total_w;
-    surface->data = (GGLubyte*)data;
-    surface->format = GGL_PIXEL_FORMAT_A_8;
+	for(i = 0; i < char_idxs_len; ++i)
+	{
+		char_idx = char_idxs[i];
+		if(FT_HAS_KERNING(f->face) && prev_idx && char_idx)
+		{
+			FT_Get_Kerning(f->face, prev_idx, char_idx, FT_KERNING_DEFAULT, &delta);
+			x += delta.x >> 6;
+		}
 
-    for(i = 0; i < char_idxs_len; ++i)
-    {
-        char_idx = char_idxs[i];
-        if(FT_HAS_KERNING(f->face) && prev_idx && char_idx)
-        {
-            FT_Get_Kerning(f->face, prev_idx, char_idx, FT_KERNING_DEFAULT, &delta);
-            x += delta.x >> 6;
-        }
+		ent = gr_ttf_glyph_cache_get(f, char_idx);
+		if(ent)
+		{
+			gr_ttf_copy_glyph_to_surface(surface, ent->glyph, x, 0, font->base);
+			x += ent->glyph->root.advance.x >> 16;
+		}
 
-        ent = gr_ttf_glyph_cache_get(f, char_idx);
-        if(ent)
-        {
-            gr_ttf_copy_glyph_to_surface(surface, ent->glyph, x, 0, font->base);
-            x += ent->glyph->root.advance.x >> 16;
-        }
+		prev_idx = char_idx;
+	}
 
-        prev_idx = char_idx;
-    }
-
-    free(char_idxs);
-    return bytes_rendered;
+	delete [] char_idxs;
+	return bytes_rendered;
 }
 
-static StringCacheEntry *gr_ttf_string_cache_peek(TrueTypeFont *font, const char *text, int max_width)
-{
-    StringCacheKey k = {
-        .text = (char*)text,
-        .max_width = max_width
-    };
-
-    return (StringCacheEntry *)hashmapGet(font->string_cache, &k);
+StringCacheEntry* twrpTruetype::gr_ttf_string_cache_peek(TrueTypeFont *font, 
+	const char *text, 
+	__attribute__((unused)) int max_width) {
+		StringCacheKey k = {
+			.text = (char*)text,
+			.max_width = max_width
+		};
+		StringCacheMap::iterator stringCacheItr = font->string_cache.find(k);
+		if (stringCacheItr != font->string_cache.end()) {
+			return stringCacheItr->second;
+		}
+		else {
+			return nullptr;
+		}
 }
 
-static StringCacheEntry *gr_ttf_string_cache_get(TrueTypeFont *font, const char *text, int max_width)
-{
-    StringCacheEntry *res;
-    StringCacheKey k = {
-        .text = (char*)text,
-        .max_width = max_width
-    };
+StringCacheEntry* twrpTruetype::gr_ttf_string_cache_get(TrueTypeFont *font, const char *text, int max_width) {
+	StringCacheEntry *res = nullptr;
 
-    res = (StringCacheEntry *)hashmapGet(font->string_cache, &k);
-    if(!res)
-    {
-        res = (StringCacheEntry *)malloc(sizeof(StringCacheEntry));
-        memset(res, 0, sizeof(StringCacheEntry));
-        res->rendered_bytes = gr_ttf_render_text(font, &res->surface, text, max_width);
-        if(res->rendered_bytes < 0)
-        {
-            free(res);
-            return NULL;
-        }
+	StringCacheKey k = {
+		.text = (char*)text,
+		.max_width = max_width
+	};
 
-        StringCacheKey *new_key = (StringCacheKey *)malloc(sizeof(StringCacheKey));
-        memset(new_key, 0, sizeof(StringCacheKey));
-        new_key->max_width = max_width;
-        new_key->text = strdup(text);
+	StringCacheMap::iterator stringCacheItr = font->string_cache.find(k);
+	if (stringCacheItr == font->string_cache.end())
+	{
+		res = new StringCacheEntry;
+		res->rendered_bytes = gr_ttf_render_text(font, &res->surface, text, max_width);
+		if(res->rendered_bytes < 0)
+		{
+			delete res;
+			return nullptr;
+		}
 
-        res->key = new_key;
+		StringCacheKey *new_key = new StringCacheKey;
+		new_key->max_width = max_width;
+		new_key->text = strdup(text);
+		res->key = new_key;
+		font->string_cache[k] = res; 
+	}
+	else
+	{
+		res = stringCacheItr->second;
 
-        if(font->string_cache_tail)
-        {
-            res->prev = font->string_cache_tail;
-            res->prev->next = res;
-        }
-        else
-            font->string_cache_head = res;
-        font->string_cache_tail = res;
+		// truncate old entries
+		if (font->string_cache.size() >= STRING_CACHE_MAX_ENTRIES)
+		{
+			StringCacheEntry *ent;
+			for(int i = 0; i < STRING_CACHE_TRUNCATE_ENTRIES; ++i)
+			{
+				StringCacheMap::iterator stringTruncCacheItr = font->string_cache.find(k);
 
-        hashmapPut(font->string_cache, new_key, res);
-    }
-    else if(res->next)
-    {
-        // move this entry to the tail of the linked list
-        // if it isn't already there
-        if(res->prev)
-            res->prev->next = res->next;
-
-        res->next->prev = res->prev;
-
-        if(!res->prev)
-            font->string_cache_head = res->next;
-
-        res->next = NULL;
-        res->prev = font->string_cache_tail;
-        res->prev->next = res;
-        font->string_cache_tail = res;
-
-        // truncate old entries
-        if(hashmapSize(font->string_cache) >= STRING_CACHE_MAX_ENTRIES)
-        {
-            printf("Truncating string cache entries.\n");
-            int i;
-            StringCacheEntry *ent;
-            for(i = 0; i < STRING_CACHE_TRUNCATE_ENTRIES; ++i)
-            {
-                ent = font->string_cache_head;
-                font->string_cache_head = ent->next;
-                font->string_cache_head->prev = NULL;
-
-                hashmapRemove(font->string_cache, ent->key);
-
-                gr_ttf_freeStringCache(ent->key, ent, NULL);
-            }
-        }
-    }
-    return res;
+				if (stringTruncCacheItr != font->string_cache.end()) {
+					ent = stringTruncCacheItr->second;
+					gr_ttf_freeStringCache(ent->key, ent, nullptr);
+					font->string_cache.erase(stringTruncCacheItr);
+				}
+			}
+		}
+	}
+	return res;
 }
 
-int gr_ttf_measureEx(const char *s, void *font)
-{
-    TrueTypeFont *f = (TrueTypeFont *)font;
-    int res = -1;
+int twrpTruetype::gr_ttf_measureEx(const char *s, void *font) {
+	TrueTypeFont *f = (TrueTypeFont *)font;
+	int res = -1;
 
-    pthread_mutex_lock(&f->mutex);
-    StringCacheEntry *e = gr_ttf_string_cache_get(f, s, -1);
-    if(e)
-        res = e->surface.width;
-    pthread_mutex_unlock(&f->mutex);
+	pthread_mutex_lock(&f->mutex);
+	StringCacheEntry *e = gr_ttf_string_cache_get(f, s, -1);
+	if(e)
+		res = e->surface.width;
+	pthread_mutex_unlock(&f->mutex);
 
-    return res;
+	return res;
 }
 
-int gr_ttf_maxExW(const char *s, void *font, int max_width)
-{
-    TrueTypeFont *f = (TrueTypeFont *)font;
-    TrueTypeCacheEntry *ent;
-    int max_bytes = 0, total_w = 0;
-    int utf_bytes, prev_utf_bytes = 0;
-    unsigned int unicode = 0;
-    int char_idx, prev_idx = 0;
-    FT_Vector delta;
-    StringCacheEntry *e;
+int twrpTruetype::gr_ttf_maxExW(const char *s, void *font, int max_width) {
+	TrueTypeFont *f = (TrueTypeFont *)font;
+	TrueTypeCacheEntry *ent;
+	int max_bytes = 0, total_w = 0;
+	int utf_bytes, prev_utf_bytes = 0;
+	unsigned int unicode = 0;
+	int char_idx, prev_idx = 0;
+	FT_Vector delta;
+	StringCacheEntry *e;
 
-    pthread_mutex_lock(&f->mutex);
+	pthread_mutex_lock(&f->mutex);
 
-    e = gr_ttf_string_cache_peek(f, s, max_width);
-    if(e)
-    {
-        max_bytes = e->rendered_bytes;
-        pthread_mutex_unlock(&f->mutex);
-        return max_bytes;
-    }
+	e = gr_ttf_string_cache_peek(f, s, max_width);
+	if(e)
+	{
+		max_bytes = e->rendered_bytes;
+		pthread_mutex_unlock(&f->mutex);
+		return max_bytes;
+	}
 
-    while(*s)
-    {
-        utf_bytes = utf8_to_unicode(s, &unicode);
-        s += utf_bytes;
+	while(*s)
+	{
+		utf_bytes = utf8_to_unicode(s, &unicode);
+		s += utf_bytes;
 
-        char_idx = FT_Get_Char_Index(f->face, unicode);
-        if(FT_HAS_KERNING(f->face) && prev_idx && char_idx)
-        {
-            FT_Get_Kerning(f->face, prev_idx, char_idx, FT_KERNING_DEFAULT, &delta);
-            total_w += delta.x >> 6;
-        }
-        prev_idx = char_idx;
+		char_idx = FT_Get_Char_Index(f->face, unicode);
+		if(FT_HAS_KERNING(f->face) && prev_idx && char_idx)
+		{
+			FT_Get_Kerning(f->face, prev_idx, char_idx, FT_KERNING_DEFAULT, &delta);
+			total_w += delta.x >> 6;
+		}
+		prev_idx = char_idx;
 
-        if(total_w > max_width)
-        {
-            max_bytes -= prev_utf_bytes;
-            break;
-        }
-        prev_utf_bytes = utf_bytes;
+		if(total_w > max_width)
+		{
+			max_bytes -= prev_utf_bytes;
+			break;
+		}
+		prev_utf_bytes = utf_bytes;
+		ent = gr_ttf_glyph_cache_get(f, char_idx);
+		if(!ent)
+			continue;
 
-        ent = gr_ttf_glyph_cache_get(f, char_idx);
-        if(!ent)
-            continue;
-
-        total_w += ent->glyph->root.advance.x >> 16;
-        max_bytes += utf_bytes;
-    }
-    pthread_mutex_unlock(&f->mutex);
-    return max_bytes;
+		total_w += ent->glyph->root.advance.x >> 16;
+		max_bytes += utf_bytes;
+	}
+	pthread_mutex_unlock(&f->mutex);
+	return max_bytes;
 }
 
-int gr_ttf_textExWH(void *context, int x, int y,
-                    const char *s, void *pFont,
-                    int max_width, int max_height,
-                    const gr_surface gr_draw_surface)
-{
-    GGLContext *gl = (GGLContext *)context;
-    TrueTypeFont *font = (TrueTypeFont *)pFont;
-    const GRSurface *gr_draw = (const GRSurface*) gr_draw_surface;
+int twrpTruetype::gr_ttf_textExWH(void *context, int x, int y,
+					const char *s, void *pFont,
+					int max_width, int max_height,
+					const gr_surface gr_draw_surface) {
+	GGLContext *gl = (GGLContext *)context;
+	TrueTypeFont *font = (TrueTypeFont *)pFont;
+	const GRSurface *gr_draw = (const GRSurface*) gr_draw_surface;
 
-    // not actualy max width, but max_width + x
-    if(max_width != -1)
-    {
-        max_width -= x;
-        if(max_width <= 0)
-            return 0;
-    }
+	// not actualy max width, but max_width + x
+	if(max_width != -1)
+	{
+		max_width -= x;
+		if(max_width <= 0)
+			return 0;
+	}
 
-    pthread_mutex_lock(&font->mutex);
+	pthread_mutex_lock(&font->mutex);
 
-    StringCacheEntry *e = gr_ttf_string_cache_get(font, s, max_width);
-    if(!e)
-    {
-        pthread_mutex_unlock(&font->mutex);
-        return -1;
-    }
+	StringCacheEntry *e = gr_ttf_string_cache_get(font, s, max_width);
+	if(!e)
+	{
+		pthread_mutex_unlock(&font->mutex);
+		return -1;
+	}
 
 #if TW_ROTATION != 0
-    // Do not perform relatively expensive operation if not needed
-    GGLSurface string_surface_rotated;
-    string_surface_rotated.version = sizeof(string_surface_rotated);
-    // Skip the **(TW_ROTATION == 0)** || (TW_ROTATION == 180) check
-    // because we are under a TW_ROTATION != 0 conditional compilation statement
-    string_surface_rotated.width   = (TW_ROTATION == 180) ? e->surface.width  : e->surface.height;
-    string_surface_rotated.height  = (TW_ROTATION == 180) ? e->surface.height : e->surface.width;
-    string_surface_rotated.stride  = string_surface_rotated.width;
-    string_surface_rotated.format  = e->surface.format;
-    // e->surface.format is GGL_PIXEL_FORMAT_A_8 (grayscale)
-    string_surface_rotated.data    = (GGLubyte*) malloc(string_surface_rotated.stride * string_surface_rotated.height * 1);
-    surface_ROTATION_transform((gr_surface) &string_surface_rotated, (const gr_surface) &e->surface, 1);
+	// Do not perform relatively expensive operation if not needed
+	GGLSurface string_surface_rotated;
+	string_surface_rotated.version = sizeof(string_surface_rotated);
+	// Skip the **(TW_ROTATION == 0)** || (TW_ROTATION == 180) check
+	// because we are under a TW_ROTATION != 0 conditional compilation statement
+	string_surface_rotated.width   = (TW_ROTATION == 180) ? e->surface.width  : e->surface.height;
+	string_surface_rotated.height  = (TW_ROTATION == 180) ? e->surface.height : e->surface.width;
+	string_surface_rotated.stride  = string_surface_rotated.width;
+	string_surface_rotated.format  = e->surface.format;
+	// e->surface.format is GGL_PIXEL_FORMAT_A_8 (grayscale)
+	string_surface_rotated.data = new GGLubyte[string_surface_rotated.stride * string_surface_rotated.height * 1];
+	surface_ROTATION_transform((gr_surface) &string_surface_rotated, (const gr_surface) &e->surface, 1);
 #endif
 
-    int y_bottom = y + e->surface.height;
-    int res = e->rendered_bytes;
+	int y_bottom = y + e->surface.height;
+	int res = e->rendered_bytes;
 
-    if(max_height != -1 && max_height < y_bottom)
-    {
-        y_bottom = max_height;
-        if(y_bottom <= y)
-        {
-            pthread_mutex_unlock(&font->mutex);
-            return 0;
-        }
-    }
+	if(max_height != -1 && max_height < y_bottom)
+	{
+		y_bottom = max_height;
+		if(y_bottom <= y)
+		{
+			pthread_mutex_unlock(&font->mutex);
+			return 0;
+		}
+	}
 
-    // Figuring out display coordinates works for TW_ROTATION == 0 too,
-    // and isn't as expensive as allocating and rotating another surface,
-    // so we do this anyway.
-    int x0_disp, y0_disp, x1_disp, y1_disp;
-    int l_disp, r_disp, t_disp, b_disp;
+	// Figuring out display coordinates works for TW_ROTATION == 0 too,
+	// and isn't as expensive as allocating and rotating another surface,
+	// so we do this anyway.
+	int x0_disp, y0_disp, x1_disp, y1_disp;
+	int l_disp, r_disp, t_disp, b_disp;
 
-    x0_disp = ROTATION_X_DISP(x, y, gr_draw);
-    y0_disp = ROTATION_Y_DISP(x, y, gr_draw);
-    x1_disp = ROTATION_X_DISP(x + e->surface.width, y_bottom, gr_draw);
-    y1_disp = ROTATION_Y_DISP(x + e->surface.width, y_bottom, gr_draw);
-    l_disp = std::min(x0_disp, x1_disp);
-    r_disp = std::max(x0_disp, x1_disp);
-    t_disp = std::min(y0_disp, y1_disp);
-    b_disp = std::max(y0_disp, y1_disp);
+	x0_disp = ROTATION_X_DISP(x, y, gr_draw);
+	y0_disp = ROTATION_Y_DISP(x, y, gr_draw);
+	x1_disp = ROTATION_X_DISP(x + e->surface.width, y_bottom, gr_draw);
+	y1_disp = ROTATION_Y_DISP(x + e->surface.width, y_bottom, gr_draw);
+	l_disp = std::min(x0_disp, x1_disp);
+	r_disp = std::max(x0_disp, x1_disp);
+	t_disp = std::min(y0_disp, y1_disp);
+	b_disp = std::max(y0_disp, y1_disp);
 
 #if TW_ROTATION != 0
-    gl->bindTexture(gl, &string_surface_rotated);
+	gl->bindTexture(gl, &string_surface_rotated);
 #else
-    gl->bindTexture(gl, &e->surface);
+	gl->bindTexture(gl, &e->surface);
 #endif
-    gl->texEnvi(gl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE);
-    gl->texGeni(gl, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
-    gl->texGeni(gl, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
+	gl->texEnvi(gl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE);
+	gl->texGeni(gl, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
+	gl->texGeni(gl, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
 
-    gl->enable(gl, GGL_TEXTURE_2D);
-    gl->texCoord2i(gl, -l_disp, -t_disp);
-    gl->recti(gl, l_disp, t_disp, r_disp, b_disp);
-    gl->disable(gl, GGL_TEXTURE_2D);
+	gl->enable(gl, GGL_TEXTURE_2D);
+	gl->texCoord2i(gl, -l_disp, -t_disp);
+	gl->recti(gl, l_disp, t_disp, r_disp, b_disp);
+	gl->disable(gl, GGL_TEXTURE_2D);
 
 #if TW_ROTATION != 0
-    free(string_surface_rotated.data);
+	delete [] string_surface_rotated.data;
 #endif
 
-    pthread_mutex_unlock(&font->mutex);
-    return res;
+	pthread_mutex_unlock(&font->mutex);
+	return res;
 }
 
-int gr_ttf_getMaxFontHeight(void *font)
-{
-    int res;
-    TrueTypeFont *f = (TrueTypeFont *)font;
+int twrpTruetype::gr_ttf_getMaxFontHeight(void *font) {
+	int res;
+	TrueTypeFont *f = (TrueTypeFont *)font;
 
-    pthread_mutex_lock(&f->mutex);
+	pthread_mutex_lock(&f->mutex);
 
-    if(f->max_height == -1)
-        gr_ttf_calcMaxFontHeight(f);
-    res = f->max_height;
+	if(f->max_height == -1)
+		gr_ttf_calcMaxFontHeight(f);
+	res = f->max_height;
 
-    pthread_mutex_unlock(&f->mutex);
-    return res;
-}
-
-static bool gr_ttf_dump_stats_count_string_cache(void *key __unused, void *value, void *context)
-{
-    int *string_cache_size = (int *)context;
-    StringCacheEntry *e = (StringCacheEntry *)value;
-    *string_cache_size += e->surface.height*e->surface.width + sizeof(StringCacheEntry);
-    return true;
-}
-
-static bool gr_ttf_dump_stats_font(void *key, void *value, void *context)
-{
-    TrueTypeFontKey *k = (TrueTypeFontKey *)key;
-    TrueTypeFont *f = (TrueTypeFont *)value;
-    int *total_string_cache_size = (int *)context;
-    int string_cache_size = 0;
-
-    pthread_mutex_lock(&f->mutex);
-
-    hashmapForEach(f->string_cache, gr_ttf_dump_stats_count_string_cache, &string_cache_size);
-
-    printf("  Font %s (size %d, dpi %d):\n"
-            "    refcount: %d\n"
-            "    max_height: %d\n"
-            "    base: %d\n"
-            "    glyph_cache: %zu entries\n"
-            "    string_cache: %zu entries (%.2f kB)\n",
-            k->path, k->size, k->dpi,
-            f->refcount, f->max_height, f->base,
-            hashmapSize(f->glyph_cache),
-            hashmapSize(f->string_cache), ((double)string_cache_size)/1024);
-
-    pthread_mutex_unlock(&f->mutex);
-
-    *total_string_cache_size += string_cache_size;
-    return true;
-}
-
-void gr_ttf_dump_stats(void)
-{
-    pthread_mutex_lock(&font_data.mutex);
-
-    printf("TrueType fonts system stats: ");
-    if(!font_data.fonts)
-        printf("no truetype fonts loaded.\n");
-    else
-    {
-        int total_string_cache_size = 0;
-        printf("%zu fonts loaded.\n", hashmapSize(font_data.fonts));
-        hashmapForEach(font_data.fonts, gr_ttf_dump_stats_font, &total_string_cache_size);
-        printf("  Total string cache size: %.2f kB\n", ((double)total_string_cache_size)/1024);
-    }
-
-    pthread_mutex_unlock(&font_data.mutex);
+	pthread_mutex_unlock(&f->mutex);
+	return res;
 }
diff --git a/minuitwrp/truetype.hpp b/minuitwrp/truetype.hpp
new file mode 100755
index 0000000..e0d7a2f
--- /dev/null
+++ b/minuitwrp/truetype.hpp
@@ -0,0 +1,121 @@
+/*

+		Copyright 2013 to 2020 TeamWin

+		TWRP is free software: you can redistribute it and/or modify

+		it under the terms of the GNU General Public License as published by

+		the Free Software Foundation, either version 3 of the License, or

+		(at your option) any later version.

+

+		TWRP is distributed in the hope that it will be useful,

+		but WITHOUT ANY WARRANTY; without even the implied warranty of

+		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

+		GNU General Public License for more details.

+

+		You should have received a copy of the GNU General Public License

+		along with TWRP.  If not, see <http://www.gnu.org/licenses/>.

+*/

+

+#ifndef _TWRP_TRUETYPE_HPP

+#define _TWRP_TRUETYPE_HPP

+

+#include <map>

+#include <ft2build.h>

+#include FT_FREETYPE_H

+#include FT_GLYPH_H

+#include <pixelflinger/pixelflinger.h>

+#include "minui.h"

+

+struct TrueTypeFontKey {

+    int size;

+    int dpi;

+    char *path;

+

+    bool operator<(const TrueTypeFontKey &ttfk) const {

+        return size < ttfk.size || (size == ttfk.size && dpi < ttfk.dpi) || (size == ttfk.size && dpi == ttfk.dpi 

+        && std::strcmp(path, ttfk.path) < 0) || (size == ttfk.size && std::strcmp(path, ttfk.path) > 0);

+    }

+};

+

+typedef struct TrueTypeFontKey TrueTypeFontKey;

+

+typedef struct {

+    FT_BBox bbox;

+    FT_BitmapGlyph glyph;

+} TrueTypeCacheEntry;

+

+struct StringCacheKey {

+    char *text;

+    int max_width;

+

+    bool operator<(const StringCacheKey &sck) const {

+        return max_width < sck.max_width || (max_width == sck.max_width 

+        && std::strcmp(text, sck.text) < 0) || (max_width == sck.max_width && std::strcmp(text, sck.text) > 0);

+    }

+};

+

+typedef struct StringCacheKey StringCacheKey;

+

+typedef struct StringCacheEntry {

+    GGLSurface surface;

+    int rendered_bytes; // number of bytes from C string rendered, not number of UTF8 characters!

+    StringCacheKey *key;

+} StringCacheEntry;

+

+typedef struct {

+    int type;

+    int refcount;

+    int size;

+    int dpi;

+    int max_height;

+    int base;

+    FT_Face face;

+    std::map<int, TrueTypeCacheEntry*> glyph_cache;

+    std::map<StringCacheKey, StringCacheEntry*> string_cache;

+    pthread_mutex_t mutex;

+    TrueTypeFontKey *key;

+} TrueTypeFont;

+

+typedef struct {

+    FT_Library ft_library;

+    std::map<TrueTypeFontKey, TrueTypeFont*> fonts;

+    pthread_mutex_t mutex;

+} FontData;

+

+typedef std::map<StringCacheKey, StringCacheEntry*> StringCacheMap;

+typedef std::map<int, TrueTypeCacheEntry*> TrueTypeCacheEntryMap;

+typedef std::map<TrueTypeFontKey, TrueTypeFont*> TrueTypeFontMap;

+

+#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))

+#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))

+

+// 32bit FNV-1a hash algorithm

+// http://isthe.com/chongo/tech/comp/fnv/#FNV-1a

+static const uint32_t FNV_prime = 16777619U;

+static const uint32_t offset_basis = 2166136261U;

+

+#define STRING_CACHE_MAX_ENTRIES 400

+#define STRING_CACHE_TRUNCATE_ENTRIES 150

+

+class twrpTruetype {

+public:

+    twrpTruetype();

+    static int utf8_to_unicode(const char* pIn, unsigned int *pOut);

+    static void* gr_ttf_loadFont(const char *filename, int size, int dpi);

+    static void* gr_ttf_scaleFont(void *font, int max_width, int measured_width);

+    static bool gr_ttf_freeStringCache(void *key, void *value, void *context __unused);

+    static void gr_ttf_freeFont(void *font);

+    static TrueTypeCacheEntry* gr_ttf_glyph_cache_peek(TrueTypeFont *font, int char_index);

+    static TrueTypeCacheEntry* gr_ttf_glyph_cache_get(TrueTypeFont *font, int char_index);

+    static int gr_ttf_copy_glyph_to_surface(GGLSurface *dest, FT_BitmapGlyph glyph, int offX, int offY, int base);

+    static void gr_ttf_calcMaxFontHeight(TrueTypeFont *f);

+    static int gr_ttf_render_text(TrueTypeFont *font, GGLSurface *surface, const char *text, int max_width);

+    static StringCacheEntry* gr_ttf_string_cache_peek(TrueTypeFont *font, const char *text, __attribute__((unused)) int max_width);

+    static StringCacheEntry* gr_ttf_string_cache_get(TrueTypeFont *font, const char *text, int max_width);

+    static int gr_ttf_measureEx(const char *s, void *font);

+    static int gr_ttf_maxExW(const char *s, void *font, int max_width);

+    static int gr_ttf_textExWH(void *context, int x, int y,

+                    const char *s, void *pFont,

+                    int max_width, int max_height,

+                    const gr_surface gr_draw_surface);

+    static int gr_ttf_getMaxFontHeight(void *font);

+};

+#endif // _TWRP_TRUETYPE_HPP