Add support for TrueType fonts
* Keeps original font system in place
* Uses the same API as original font system:
- You can render only one line at a time
- You can only use one font and color for one gr_text* call
* Caches all rendered text, with a string cache limited to 400
entries, then it trucates to 250, which results in memory
usage hovering around 5-10MB
Change-Id: I36107b9dcd8d57bae4486fce8b8f64e49ef3d906
Signed-off-by: Vojtech Bocek <vbocek@gmail.com>
diff --git a/gui/Android.mk b/gui/Android.mk
index 52d5f55..baae3ed 100644
--- a/gui/Android.mk
+++ b/gui/Android.mk
@@ -59,6 +59,9 @@
ifeq ($(TW_OEM_BUILD), true)
LOCAL_CFLAGS += -DTW_OEM_BUILD
endif
+ifeq ($(TW_DISABLE_TTF), true)
+ LOCAL_CFLAGS += -DTW_DISABLE_TTF
+endif
ifeq ($(DEVICE_RESOLUTION),)
$(warning ********************************************************************************)
@@ -104,6 +107,13 @@
else
TWRP_THEME_LOC := $(TW_CUSTOM_THEME)
endif
+
+ifeq ($(TW_DISABLE_TTF), true)
+ TWRP_REMOVE_FONT := rm -f $(TARGET_RECOVERY_ROOT_OUT)/res/fonts/*.ttf
+else
+ TWRP_REMOVE_FONT := rm -f $(TARGET_RECOVERY_ROOT_OUT)/res/fonts/*.dat
+endif
+
TWRP_RES_GEN := $(intermediates)/twrp
ifneq ($(TW_USE_TOOLBOX), true)
TWRP_SH_TARGET := /sbin/busybox
@@ -116,6 +126,7 @@
cp -fr $(TWRP_RES_LOC)/* $(TARGET_RECOVERY_ROOT_OUT)/res/
cp -fr $(TWRP_THEME_LOC)/* $(TARGET_RECOVERY_ROOT_OUT)/res/
$(TWRP_COMMON_XML)
+ $(TWRP_REMOVE_FONT)
mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/sbin/
ln -sf $(TWRP_SH_TARGET) $(TARGET_RECOVERY_ROOT_OUT)/sbin/sh
ln -sf /sbin/pigz $(TARGET_RECOVERY_ROOT_OUT)/sbin/gzip
diff --git a/gui/console.cpp b/gui/console.cpp
index 897c582..aad392c 100644
--- a/gui/console.cpp
+++ b/gui/console.cpp
@@ -177,7 +177,7 @@
}
}
- gr_getFontDetails(mFont, &mFontHeight, NULL);
+ mFontHeight = gr_getMaxFontHeight(mFont ? mFont->GetResource() : NULL);
SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
SetRenderPos(mConsoleX, mConsoleY);
return;
diff --git a/gui/devices/1024x600/res/ui.xml b/gui/devices/1024x600/res/ui.xml
index 87248a6..4d6f317 100644
--- a/gui/devices/1024x600/res/ui.xml
+++ b/gui/devices/1024x600/res/ui.xml
@@ -14,7 +14,7 @@
</include>
<resources>
- <resource name="font" type="font" filename="Roboto-Regular-20" />
+ <resource name="font" type="font" filename="RobotoCondensed-Regular.ttf" size="20" fallback="Roboto-Regular-20" />
<resource name="base" type="image" filename="background.jpg" />
<resource name="main_button" type="image" filename="button" />
<resource name="file_icon" type="image" filename="file" />
diff --git a/gui/devices/1024x768/res/ui.xml b/gui/devices/1024x768/res/ui.xml
index 407e18b..29f1690 100644
--- a/gui/devices/1024x768/res/ui.xml
+++ b/gui/devices/1024x768/res/ui.xml
@@ -14,7 +14,7 @@
</include>
<resources>
- <resource name="font" type="font" filename="Roboto-Regular-20" />
+ <resource name="font" type="font" filename="RobotoCondensed-Regular.ttf" size="20" fallback="Roboto-Regular-20" />
<resource name="base" type="image" filename="background.jpg" />
<resource name="main_button" type="image" filename="button" />
<resource name="file_icon" type="image" filename="file" />
diff --git a/gui/devices/1080x1920/res/ui.xml b/gui/devices/1080x1920/res/ui.xml
index 0d547a6..95c48a5 100644
--- a/gui/devices/1080x1920/res/ui.xml
+++ b/gui/devices/1080x1920/res/ui.xml
@@ -14,9 +14,9 @@
</include>
<resources>
- <resource name="font" type="font" filename="Roboto-Condensed-40" />
- <resource name="mediumfont" type="font" filename="Roboto-Condensed-40" />
- <resource name="filelist" type="font" filename="Roboto-Condensed-40" />
+ <resource name="font" type="font" filename="RobotoCondensed-Regular.ttf" size="40" fallback="Roboto-Condensed-40" />
+ <resource name="mediumfont" type="font" filename="RobotoCondensed-Regular.ttf" size="40" fallback="Roboto-Condensed-40" />
+ <resource name="filelist" type="font" filename="RobotoCondensed-Regular.ttf" size="40" fallback="Roboto-Condensed-40" />
<resource name="top_bar" type="image" filename="top-bar.jpg" />
<resource name="main_button" type="image" filename="menu-button" />
<resource name="file_icon" type="image" filename="file" />
diff --git a/gui/devices/1200x1920/res/ui.xml b/gui/devices/1200x1920/res/ui.xml
index 0778692..428880d 100644
--- a/gui/devices/1200x1920/res/ui.xml
+++ b/gui/devices/1200x1920/res/ui.xml
@@ -14,9 +14,9 @@
</include>
<resources>
- <resource name="font" type="font" filename="Roboto-Condensed-40" />
- <resource name="mediumfont" type="font" filename="Roboto-Condensed-40" />
- <resource name="filelist" type="font" filename="Roboto-Condensed-40" />
+ <resource name="font" type="font" filename="RobotoCondensed-Regular.ttf" size="40" fallback="Roboto-Condensed-40" />
+ <resource name="mediumfont" type="font" filename="RobotoCondensed-Regular.ttf" size="40" fallback="Roboto-Condensed-40" />
+ <resource name="filelist" type="font" filename="RobotoCondensed-Regular.ttf" size="40" fallback="Roboto-Condensed-40" />
<resource name="top_bar" type="image" filename="top-bar.jpg" />
<resource name="main_button" type="image" filename="menu-button" />
<resource name="file_icon" type="image" filename="file" />
diff --git a/gui/devices/1280x800/res/ui.xml b/gui/devices/1280x800/res/ui.xml
index bfb1a3a..6f6c2bd 100644
--- a/gui/devices/1280x800/res/ui.xml
+++ b/gui/devices/1280x800/res/ui.xml
@@ -14,7 +14,7 @@
</include>
<resources>
- <resource name="font" type="font" filename="Roboto-Regular-20" />
+ <resource name="font" type="font" filename="RobotoCondensed-Regular.ttf" size="20" fallback="Roboto-Regular-20" />
<resource name="base" type="image" filename="background.jpg" />
<resource name="main_button" type="image" filename="button" />
<resource name="file_icon" type="image" filename="file" />
diff --git a/gui/devices/1440x2560/res/ui.xml b/gui/devices/1440x2560/res/ui.xml
index ae25d33..fe55dfd 100644
--- a/gui/devices/1440x2560/res/ui.xml
+++ b/gui/devices/1440x2560/res/ui.xml
@@ -14,9 +14,9 @@
</include>
<resources>
- <resource name="font" type="font" filename="Roboto-Condensed-50" />
- <resource name="mediumfont" type="font" filename="Roboto-Condensed-50" />
- <resource name="filelist" type="font" filename="Roboto-Condensed-50" />
+ <resource name="font" type="font" filename="RobotoCondensed-Regular.ttf" size="50" fallback="Roboto-Condensed-50" />
+ <resource name="mediumfont" type="font" filename="RobotoCondensed-Regular.ttf" size="50" fallback="Roboto-Condensed-50" />
+ <resource name="filelist" type="font" filename="RobotoCondensed-Regular.ttf" size="50" fallback="Roboto-Condensed-50" />
<resource name="top_bar" type="image" filename="top-bar.jpg" />
<resource name="main_button" type="image" filename="menu-button" />
<resource name="file_icon" type="image" filename="file" />
diff --git a/gui/devices/1600x2560/res/ui.xml b/gui/devices/1600x2560/res/ui.xml
index 9703881..8561b2d 100644
--- a/gui/devices/1600x2560/res/ui.xml
+++ b/gui/devices/1600x2560/res/ui.xml
@@ -14,9 +14,9 @@
</include>
<resources>
- <resource name="font" type="font" filename="Roboto-Condensed-40" />
- <resource name="mediumfont" type="font" filename="Roboto-Condensed-40" />
- <resource name="filelist" type="font" filename="Roboto-Condensed-40" />
+ <resource name="font" type="font" filename="RobotoCondensed-Regular.ttf" size="40" fallback="Roboto-Condensed-40" />
+ <resource name="mediumfont" type="font" filename="RobotoCondensed-Regular.ttf" size="40" fallback="Roboto-Condensed-40" />
+ <resource name="filelist" type="font" filename="RobotoCondensed-Regular.ttf" size="40" fallback="Roboto-Condensed-40" />
<resource name="top_bar" type="image" filename="top-bar.jpg" />
<resource name="main_button" type="image" filename="menu-button" />
<resource name="file_icon" type="image" filename="file" />
diff --git a/gui/devices/1920x1200/res/ui.xml b/gui/devices/1920x1200/res/ui.xml
index d8d8a7d..3e8c9f1 100644
--- a/gui/devices/1920x1200/res/ui.xml
+++ b/gui/devices/1920x1200/res/ui.xml
@@ -14,7 +14,7 @@
</include>
<resources>
- <resource name="font" type="font" filename="Roboto-Regular-30" />
+ <resource name="font" type="font" filename="RobotoCondensed-Regular.ttf" size="30" fallback="Roboto-Regular-30" />
<resource name="base" type="image" filename="background.jpg" />
<resource name="main_button" type="image" filename="button" />
<resource name="file_icon" type="image" filename="file" />
diff --git a/gui/devices/240x240/res/ui.xml b/gui/devices/240x240/res/ui.xml
index 4cc25dd..294e595 100644
--- a/gui/devices/240x240/res/ui.xml
+++ b/gui/devices/240x240/res/ui.xml
@@ -14,9 +14,9 @@
</include>
<resources>
- <resource name="font" type="font" filename="Roboto-Condensed-12" />
- <resource name="mediumfont" type="font" filename="Roboto-Condensed-12" />
- <resource name="filelist" type="font" filename="Roboto-Condensed-12" />
+ <resource name="font" type="font" filename="RobotoCondensed-Regular.ttf" size="12" fallback="Roboto-Condensed-12" />
+ <resource name="mediumfont" type="font" filename="RobotoCondensed-Regular.ttf" size="12" fallback="Roboto-Condensed-12" />
+ <resource name="filelist" type="font" filename="RobotoCondensed-Regular.ttf" size="12" fallback="Roboto-Condensed-12" />
<resource name="top_bar" type="image" filename="top-bar.jpg" />
<resource name="main_button" type="image" filename="menu-button" />
<resource name="file_icon" type="image" filename="file" />
diff --git a/gui/devices/2560x1600/res/ui.xml b/gui/devices/2560x1600/res/ui.xml
index ca0d883..cb0c12e 100644
--- a/gui/devices/2560x1600/res/ui.xml
+++ b/gui/devices/2560x1600/res/ui.xml
@@ -14,7 +14,7 @@
</include>
<resources>
- <resource name="font" type="font" filename="Roboto-Regular-40" />
+ <resource name="font" type="font" filename="RobotoCondensed-Regular.ttf" size="40" fallback="Roboto-Regular-40" />
<resource name="base" type="image" filename="background.jpg" />
<resource name="main_button" type="image" filename="button" />
<resource name="file_icon" type="image" filename="file" />
diff --git a/gui/devices/280x280/res/ui.xml b/gui/devices/280x280/res/ui.xml
index 5a705a0..99532ed 100644
--- a/gui/devices/280x280/res/ui.xml
+++ b/gui/devices/280x280/res/ui.xml
@@ -14,9 +14,9 @@
</include>
<resources>
- <resource name="font" type="font" filename="Roboto-Condensed-12" />
- <resource name="mediumfont" type="font" filename="Roboto-Condensed-12" />
- <resource name="filelist" type="font" filename="Roboto-Condensed-12" />
+ <resource name="font" type="font" filename="RobotoCondensed-Regular.ttf" size="12" fallback="Roboto-Condensed-12" />
+ <resource name="mediumfont" type="font" filename="RobotoCondensed-Regular.ttf" size="12" fallback="Roboto-Condensed-12" />
+ <resource name="filelist" type="font" filename="RobotoCondensed-Regular.ttf" size="12" fallback="Roboto-Condensed-12" />
<resource name="top_bar" type="image" filename="top-bar.jpg" />
<resource name="main_button" type="image" filename="menu-button" />
<resource name="file_icon" type="image" filename="file" />
diff --git a/gui/devices/320x320/res/ui.xml b/gui/devices/320x320/res/ui.xml
index a9be8c9..f668529 100644
--- a/gui/devices/320x320/res/ui.xml
+++ b/gui/devices/320x320/res/ui.xml
@@ -14,9 +14,9 @@
</include>
<resources>
- <resource name="font" type="font" filename="Roboto-Condensed-14" />
- <resource name="mediumfont" type="font" filename="Roboto-Condensed-14" />
- <resource name="filelist" type="font" filename="Roboto-Condensed-14" />
+ <resource name="font" type="font" filename="RobotoCondensed-Regular.ttf" size="14" fallback="Roboto-Condensed-14" />
+ <resource name="mediumfont" type="font" filename="RobotoCondensed-Regular.ttf" size="14" fallback="Roboto-Condensed-14" />
+ <resource name="filelist" type="font" filename="RobotoCondensed-Regular.ttf" size="14" fallback="Roboto-Condensed-14" />
<resource name="top_bar" type="image" filename="top-bar.jpg" />
<resource name="main_button" type="image" filename="menu-button" />
<resource name="file_icon" type="image" filename="file" />
diff --git a/gui/devices/320x480/res/ui.xml b/gui/devices/320x480/res/ui.xml
index 57baf5f..cccd5b3 100644
--- a/gui/devices/320x480/res/ui.xml
+++ b/gui/devices/320x480/res/ui.xml
@@ -14,9 +14,9 @@
</include>
<resources>
- <resource name="font" type="font" filename="Roboto-Condensed-16" />
- <resource name="mediumfont" type="font" filename="Roboto-Condensed-14" />
- <resource name="filelist" type="font" filename="Roboto-Condensed-14" />
+ <resource name="font" type="font" filename="RobotoCondensed-Regular.ttf" size="14" fallback="Roboto-Condensed-16" />
+ <resource name="mediumfont" type="font" filename="RobotoCondensed-Regular.ttf" size="14" fallback="Roboto-Condensed-14" />
+ <resource name="filelist" type="font" filename="RobotoCondensed-Regular.ttf" size="14" fallback="Roboto-Condensed-14" />
<resource name="top_bar" type="image" filename="top-bar.jpg" />
<resource name="main_button" type="image" filename="menu-button" />
<resource name="file_icon" type="image" filename="file" />
diff --git a/gui/devices/480x800/res/ui.xml b/gui/devices/480x800/res/ui.xml
index aad9822..940ad43 100644
--- a/gui/devices/480x800/res/ui.xml
+++ b/gui/devices/480x800/res/ui.xml
@@ -14,9 +14,9 @@
</include>
<resources>
- <resource name="font" type="font" filename="Roboto-Regular-20" />
- <resource name="mediumfont" type="font" filename="Roboto-Regular-20" />
- <resource name="filelist" type="font" filename="Roboto-Regular-20" />
+ <resource name="font" type="font" filename="RobotoCondensed-Regular.ttf" size="20" fallback="Roboto-Regular-20" />
+ <resource name="mediumfont" type="font" filename="RobotoCondensed-Regular.ttf" size="20" fallback="Roboto-Regular-20" />
+ <resource name="filelist" type="font" filename="RobotoCondensed-Regular.ttf" size="20" fallback="Roboto-Regular-20" />
<resource name="top_bar" type="image" filename="top-bar.jpg" />
<resource name="main_button" type="image" filename="menu-button" />
<resource name="file_icon" type="image" filename="file" />
diff --git a/gui/devices/480x854/res/ui.xml b/gui/devices/480x854/res/ui.xml
index ea0cf77..dce1d88 100644
--- a/gui/devices/480x854/res/ui.xml
+++ b/gui/devices/480x854/res/ui.xml
@@ -14,9 +14,9 @@
</include>
<resources>
- <resource name="font" type="font" filename="Roboto-Regular-20" />
- <resource name="mediumfont" type="font" filename="Roboto-Regular-20" />
- <resource name="filelist" type="font" filename="Roboto-Regular-20" />
+ <resource name="font" type="font" filename="RobotoCondensed-Regular.ttf" size="20" fallback="Roboto-Regular-20" />
+ <resource name="mediumfont" type="font" filename="RobotoCondensed-Regular.ttf" size="20" fallback="Roboto-Regular-20" />
+ <resource name="filelist" type="font" filename="RobotoCondensed-Regular.ttf" size="20" fallback="Roboto-Regular-20" />
<resource name="top_bar" type="image" filename="top-bar.jpg" />
<resource name="main_button" type="image" filename="menu-button" />
<resource name="file_icon" type="image" filename="file" />
diff --git a/gui/devices/540x960/res/ui.xml b/gui/devices/540x960/res/ui.xml
index 58d6c9d..37c3e26 100644
--- a/gui/devices/540x960/res/ui.xml
+++ b/gui/devices/540x960/res/ui.xml
@@ -14,9 +14,9 @@
</include>
<resources>
- <resource name="font" type="font" filename="Roboto-Regular-20" />
- <resource name="mediumfont" type="font" filename="Roboto-Regular-20" />
- <resource name="filelist" type="font" filename="Roboto-Regular-25" />
+ <resource name="font" type="font" filename="RobotoCondensed-Regular.ttf" size="20" fallback="Roboto-Regular-20" />
+ <resource name="mediumfont" type="font" filename="RobotoCondensed-Regular.ttf" size="20" fallback="Roboto-Regular-20" />
+ <resource name="filelist" type="font" filename="RobotoCondensed-Regular.ttf" size="20" fallback="Roboto-Regular-25" />
<resource name="top_bar" type="image" filename="top-bar.jpg" />
<resource name="main_button" type="image" filename="qhd-menu-button" />
<resource name="file_icon" type="image" filename="file" />
diff --git a/gui/devices/720x1280/res/ui.xml b/gui/devices/720x1280/res/ui.xml
index f44998f..a7ff192 100644
--- a/gui/devices/720x1280/res/ui.xml
+++ b/gui/devices/720x1280/res/ui.xml
@@ -14,9 +14,9 @@
</include>
<resources>
- <resource name="font" type="font" filename="Roboto-Condensed-30" />
- <resource name="mediumfont" type="font" filename="Roboto-Condensed-30" />
- <resource name="filelist" type="font" filename="Roboto-Condensed-30" />
+ <resource name="font" type="font" filename="RobotoCondensed-Regular.ttf" size="30" fallback="Roboto-Condensed-30" />
+ <resource name="mediumfont" type="font" filename="RobotoCondensed-Regular.ttf" size="30" fallback="Roboto-Condensed-30" />
+ <resource name="filelist" type="font" filename="RobotoCondensed-Regular.ttf" size="30" fallback="Roboto-Condensed-30" />
<resource name="top_bar" type="image" filename="top-bar.jpg" />
<resource name="main_button" type="image" filename="menu-button" />
<resource name="file_icon" type="image" filename="file" />
diff --git a/gui/devices/800x1280/res/ui.xml b/gui/devices/800x1280/res/ui.xml
index b074931..e0036bf 100644
--- a/gui/devices/800x1280/res/ui.xml
+++ b/gui/devices/800x1280/res/ui.xml
@@ -14,9 +14,9 @@
</include>
<resources>
- <resource name="font" type="font" filename="Roboto-Condensed-30" />
- <resource name="mediumfont" type="font" filename="Roboto-Condensed-30" />
- <resource name="filelist" type="font" filename="Roboto-Condensed-30" />
+ <resource name="font" type="font" filename="RobotoCondensed-Regular.ttf" size="30" fallback="Roboto-Condensed-30" />
+ <resource name="mediumfont" type="font" filename="RobotoCondensed-Regular.ttf" size="30" fallback="Roboto-Condensed-30" />
+ <resource name="filelist" type="font" filename="RobotoCondensed-Regular.ttf" size="30" fallback="Roboto-Condensed-30" />
<resource name="top_bar" type="image" filename="top-bar.jpg" />
<resource name="main_button" type="image" filename="menu-button" />
<resource name="file_icon" type="image" filename="file" />
diff --git a/gui/devices/800x480/res/ui.xml b/gui/devices/800x480/res/ui.xml
index 0ee0e94..9acb7a1 100644
--- a/gui/devices/800x480/res/ui.xml
+++ b/gui/devices/800x480/res/ui.xml
@@ -14,7 +14,7 @@
</include>
<resources>
- <resource name="font" type="font" filename="Roboto-Condensed-16" />
+ <resource name="font" type="font" filename="RobotoCondensed-Regular.ttf" size="16" fallback="Roboto-Condensed-16" />
<resource name="base" type="image" filename="background.jpg" />
<resource name="main_button" type="image" filename="button" />
<resource name="file_icon" type="image" filename="file" />
diff --git a/gui/devices/common/res/fonts/RobotoCondensed-Regular.ttf b/gui/devices/common/res/fonts/RobotoCondensed-Regular.ttf
new file mode 100644
index 0000000..b9fc49c
--- /dev/null
+++ b/gui/devices/common/res/fonts/RobotoCondensed-Regular.ttf
Binary files differ
diff --git a/gui/fileselector.cpp b/gui/fileselector.cpp
index 4f90ca3..cf7a9a9 100644
--- a/gui/fileselector.cpp
+++ b/gui/fileselector.cpp
@@ -333,7 +333,7 @@
}
// Retrieve the line height
- gr_getFontDetails(mFont ? mFont->GetResource() : NULL, &mFontHeight, NULL);
+ mFontHeight = gr_getMaxFontHeight(mFont ? mFont->GetResource() : NULL);
mLineHeight = mFontHeight;
mHeaderH = mFontHeight;
diff --git a/gui/input.cpp b/gui/input.cpp
index 61b0cff..84ee17b 100644
--- a/gui/input.cpp
+++ b/gui/input.cpp
@@ -139,7 +139,7 @@
attr = child->first_attribute("resource");
if (attr) {
mFont = PageManager::FindResource(attr->value());
- gr_getFontDetails(mFont ? mFont->GetResource() : NULL, &mFontHeight, NULL);
+ mFontHeight = gr_getMaxFontHeight(mFont ? mFont->GetResource() : NULL);
}
}
diff --git a/gui/listbox.cpp b/gui/listbox.cpp
index e09ec53..851b373 100644
--- a/gui/listbox.cpp
+++ b/gui/listbox.cpp
@@ -271,7 +271,7 @@
}
// Retrieve the line height
- gr_getFontDetails(mFont ? mFont->GetResource() : NULL, &mFontHeight, NULL);
+ mFontHeight = gr_getMaxFontHeight(mFont ? mFont->GetResource() : NULL);
mLineHeight = mFontHeight;
mHeaderH = mFontHeight;
diff --git a/gui/partitionlist.cpp b/gui/partitionlist.cpp
index 317e178..2d464e1 100644
--- a/gui/partitionlist.cpp
+++ b/gui/partitionlist.cpp
@@ -273,7 +273,7 @@
}
// Retrieve the line height
- gr_getFontDetails(mFont ? mFont->GetResource() : NULL, &mFontHeight, NULL);
+ mFontHeight = gr_getMaxFontHeight(mFont ? mFont->GetResource() : NULL);
mLineHeight = mFontHeight;
mHeaderH = mFontHeight;
diff --git a/gui/resources.cpp b/gui/resources.cpp
index 8d430b1..4fce0ca 100644
--- a/gui/resources.cpp
+++ b/gui/resources.cpp
@@ -65,27 +65,82 @@
: Resource(node, pZip)
{
std::string file;
+ xml_attribute<>* attr;
mFont = NULL;
if (!node)
return;
- if (node->first_attribute("filename"))
- file = node->first_attribute("filename")->value();
+ attr = node->first_attribute("filename");
+ if (!attr)
+ return;
- if (ExtractResource(pZip, "fonts", file, ".dat", TMP_RESOURCE_NAME) == 0)
+ file = attr->value();
+
+#ifndef TW_DISABLE_TTF
+ if(file.size() >= 4 && file.compare(file.size()-4, 4, ".ttf") == 0)
{
- mFont = gr_loadFont(TMP_RESOURCE_NAME);
- unlink(TMP_RESOURCE_NAME);
+ m_type = TYPE_TTF;
+
+ attr = node->first_attribute("size");
+ if(!attr)
+ return;
+
+ int size = atoi(attr->value());
+ int dpi = 300;
+
+ attr = node->first_attribute("dpi");
+ if(attr)
+ dpi = atoi(attr->value());
+
+ if (ExtractResource(pZip, "fonts", file, "", TMP_RESOURCE_NAME) == 0)
+ {
+ mFont = gr_ttf_loadFont(TMP_RESOURCE_NAME, size, dpi);
+ unlink(TMP_RESOURCE_NAME);
+ }
+ else
+ {
+ file = std::string("/res/fonts/") + file;
+ mFont = gr_ttf_loadFont(file.c_str(), size, dpi);
+ }
}
else
+#endif
{
- mFont = gr_loadFont(file.c_str());
+ m_type = TYPE_TWRP;
+
+ if(file.size() >= 4 && file.compare(file.size()-4, 4, ".ttf") == 0)
+ {
+ attr = node->first_attribute("fallback");
+ if (!attr)
+ return;
+
+ file = attr->value();
+ }
+
+ if (ExtractResource(pZip, "fonts", file, ".dat", TMP_RESOURCE_NAME) == 0)
+ {
+ mFont = gr_loadFont(TMP_RESOURCE_NAME);
+ unlink(TMP_RESOURCE_NAME);
+ }
+ else
+ {
+ mFont = gr_loadFont(file.c_str());
+ }
}
}
FontResource::~FontResource()
{
+ if(mFont)
+ {
+#ifndef TW_DISABLE_TTF
+ if(m_type == TYPE_TTF)
+ gr_ttf_freeFont(mFont);
+ else
+#endif
+ gr_freeFont(mFont);
+ }
}
ImageResource::ImageResource(xml_node<>* node, ZipArchive* pZip)
diff --git a/gui/resources.hpp b/gui/resources.hpp
index 874836e..3cb5281 100644
--- a/gui/resources.hpp
+++ b/gui/resources.hpp
@@ -38,6 +38,14 @@
class FontResource : public Resource
{
public:
+ enum Type
+ {
+ TYPE_TWRP,
+#ifndef TW_DISABLE_TTF
+ TYPE_TTF,
+#endif
+ };
+
FontResource(xml_node<>* node, ZipArchive* pZip);
virtual ~FontResource();
@@ -46,6 +54,7 @@
protected:
void* mFont;
+ Type m_type;
};
class ImageResource : public Resource
diff --git a/gui/slidervalue.cpp b/gui/slidervalue.cpp
index 5b4d57f..700d7d5 100644
--- a/gui/slidervalue.cpp
+++ b/gui/slidervalue.cpp
@@ -198,7 +198,7 @@
}
}
- gr_getFontDetails(mFont ? mFont->GetResource() : NULL, (unsigned*) &mFontHeight, NULL);
+ mFontHeight = gr_getMaxFontHeight(mFont ? mFont->GetResource() : NULL);
if(mShowCurr)
{
diff --git a/gui/text.cpp b/gui/text.cpp
index c594f48..29d7ad9 100644
--- a/gui/text.cpp
+++ b/gui/text.cpp
@@ -97,7 +97,7 @@
mLastValue = parseText();
if (mLastValue != mText) mIsStatic = 0;
- gr_getFontDetails(mFont ? mFont->GetResource() : NULL, (unsigned*) &mFontHeight, NULL);
+ mFontHeight = gr_getMaxFontHeight(mFont ? mFont->GetResource() : NULL);
return;
}
diff --git a/minuitwrp/Android.mk b/minuitwrp/Android.mk
index ba81f27..bc4e054 100644
--- a/minuitwrp/Android.mk
+++ b/minuitwrp/Android.mk
@@ -107,8 +107,16 @@
LOCAL_CFLAGS += -DWHITELIST_INPUT=$(TW_WHITELIST_INPUT)
endif
-LOCAL_SHARED_LIBRARIES += libz libc libcutils libjpeg
-LOCAL_STATIC_LIBRARIES += libpng libpixelflinger_static
+ifeq ($(TW_DISABLE_TTF), true)
+ LOCAL_CFLAGS += -DTW_DISABLE_TTF
+else
+ LOCAL_SHARED_LIBRARIES += libft2
+ LOCAL_C_INCLUDES += external/freetype/include
+ LOCAL_SRC_FILES += truetype.c
+endif
+
+LOCAL_SHARED_LIBRARIES += libz libc libcutils libjpeg libpng
+LOCAL_STATIC_LIBRARIES += libpixelflinger_static
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := libminuitwrp
diff --git a/minuitwrp/graphics.c b/minuitwrp/graphics.c
index 79b1e9a..9926904 100644
--- a/minuitwrp/graphics.c
+++ b/minuitwrp/graphics.c
@@ -58,6 +58,7 @@
// #define PRINT_SCREENINFO 1 // Enables printing of screen info to log
typedef struct {
+ int type;
GGLSurface texture;
unsigned offset[97];
unsigned cheight;
@@ -392,6 +393,11 @@
if (!fnt) fnt = gr_font;
+#ifndef TW_DISABLE_TTF
+ if(fnt->type == FONT_TYPE_TTF)
+ return gr_ttf_measureEx(s, font);
+#endif
+
while ((off = *s++))
{
off -= 32;
@@ -410,6 +416,11 @@
if (!fnt) fnt = gr_font;
+#ifndef TW_DISABLE_TTF
+ if(fnt->type == FONT_TYPE_TTF)
+ return gr_ttf_maxExW(s, font, max_width);
+#endif
+
while ((off = *s++))
{
off -= 32;
@@ -425,21 +436,6 @@
return total;
}
-unsigned character_width(const char *s, void* pFont)
-{
- GRFont *font = (GRFont*) pFont;
- unsigned off;
-
- /* Handle default font */
- if (!font) font = gr_font;
-
- off = *s - 32;
- if (off == 0)
- return 0;
-
- return font->offset[off+1] - font->offset[off];
-}
-
int gr_textEx(int x, int y, const char *s, void* pFont)
{
GGLContext *gl = gr_context;
@@ -450,6 +446,11 @@
/* Handle default font */
if (!font) font = gr_font;
+#ifndef TW_DISABLE_TTF
+ if(font->type == FONT_TYPE_TTF)
+ return gr_ttf_textExWH(gl, x, y, s, pFont, -1, -1);
+#endif
+
gl->bindTexture(gl, &font->texture);
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);
@@ -480,6 +481,11 @@
/* Handle default font */
if (!font) font = gr_font;
+#ifndef TW_DISABLE_TTF
+ if(font->type == FONT_TYPE_TTF)
+ return gr_ttf_textExWH(gl, x, y, s, pFont, max_width, -1);
+#endif
+
gl->bindTexture(gl, &font->texture);
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);
@@ -518,6 +524,11 @@
/* Handle default font */
if (!font) font = gr_font;
+#ifndef TW_DISABLE_TTF
+ if(font->type == FONT_TYPE_TTF)
+ return gr_ttf_textExWH(gl, x, y, s, pFont, max_width, max_height);
+#endif
+
gl->bindTexture(gl, &font->texture);
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);
@@ -549,34 +560,6 @@
return x;
}
-int twgr_text(int x, int y, const char *s)
-{
- GGLContext *gl = gr_context;
- GRFont *font = gr_font;
- unsigned off;
- unsigned cwidth = 0;
-
- y -= font->ascent;
-
- gl->bindTexture(gl, &font->texture);
- 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);
-
- while((off = *s++)) {
- off -= 32;
- if (off < 96) {
- cwidth = font->offset[off+1] - font->offset[off];
- gl->texCoord2i(gl, (off * cwidth) - x, 0 - y);
- gl->recti(gl, x, y, x + cwidth, y + font->cheight);
- }
- x += cwidth;
- }
-
- return x;
-}
-
void gr_fill(int x, int y, int w, int h)
{
GGLContext *gl = gr_context;
@@ -682,33 +665,32 @@
ftex->stride = width;
ftex->data = (void*) bits;
ftex->format = GGL_PIXEL_FORMAT_A_8;
+ font->type = FONT_TYPE_TWRP;
font->cheight = height;
font->ascent = height - 2;
return (void*) font;
}
-int gr_getFontDetails(void* font, unsigned* cheight, unsigned* maxwidth)
+void gr_freeFont(void *font)
+{
+ GRFont *f = font;
+ free(f->texture.data);
+ free(f);
+}
+
+int gr_getMaxFontHeight(void *font)
{
GRFont *fnt = (GRFont*) font;
if (!fnt) fnt = gr_font;
if (!fnt) return -1;
- if (cheight) *cheight = fnt->cheight;
- if (maxwidth)
- {
- int pos;
- *maxwidth = 0;
- for (pos = 0; pos < 96; pos++)
- {
- unsigned int width = fnt->offset[pos+1] - fnt->offset[pos];
- if (width > *maxwidth)
- {
- *maxwidth = width;
- }
- }
- }
- return 0;
+#ifndef TW_DISABLE_TTF
+ if(fnt->type == FONT_TYPE_TTF)
+ return gr_ttf_getMaxFontHeight(font);
+#endif
+
+ return fnt->cheight;
}
static void gr_init_font(void)
@@ -746,6 +728,7 @@
ftex->stride = width;
ftex->data = (void*) bits;
ftex->format = GGL_PIXEL_FORMAT_A_8;
+ gr_font->type = FONT_TYPE_TWRP;
gr_font->cheight = height;
gr_font->ascent = height - 2;
return;
diff --git a/minuitwrp/minui.h b/minuitwrp/minui.h
index f04f518..cb9f8a3 100644
--- a/minuitwrp/minui.h
+++ b/minuitwrp/minui.h
@@ -20,6 +20,12 @@
typedef void* gr_surface;
typedef unsigned short gr_pixel;
+#define FONT_TYPE_TWRP 0
+
+#ifndef TW_DISABLE_TTF
+#define FONT_TYPE_TTF 1
+#endif
+
int gr_init(void);
void gr_exit(void);
@@ -35,16 +41,25 @@
int gr_textEx(int x, int y, const char *s, void* font);
int gr_textExW(int x, int y, const char *s, void* font, int max_width);
int gr_textExWH(int x, int y, const char *s, void* pFont, int max_width, int max_height);
-int twgr_text(int x, int y, const char *s);
static inline int gr_text(int x, int y, const char *s) { return gr_textEx(x, y, s, NULL); }
int gr_measureEx(const char *s, void* font);
static inline int gr_measure(const char *s) { return gr_measureEx(s, NULL); }
int gr_maxExW(const char *s, void* font, int max_width);
-int gr_getFontDetails(void* font, unsigned* cheight, unsigned* maxwidth);
-static inline void gr_font_size(int *x, int *y) { gr_getFontDetails(NULL, (unsigned*) y, (unsigned*) x); }
+int gr_getMaxFontHeight(void *font);
void* gr_loadFont(const char* fontName);
+void gr_freeFont(void *font);
+
+#ifndef TW_DISABLE_TTF
+void *gr_ttf_loadFont(const char *filename, int size, int dpi);
+void gr_ttf_freeFont(void *font);
+int gr_ttf_textExWH(void *context, int x, int y, const char *s, void *pFont, int max_width, int max_height);
+int gr_ttf_measureEx(const char *s, void *font);
+int gr_ttf_maxExW(const char *s, void *font, int max_width);
+int gr_ttf_getMaxFontHeight(void *font);
+void gr_ttf_dump_stats(void);
+#endif
void gr_blit(gr_surface source, int sx, int sy, int w, int h, int dx, int dy);
unsigned int gr_get_width(gr_surface surface);
diff --git a/minuitwrp/truetype.c b/minuitwrp/truetype.c
new file mode 100644
index 0000000..8e0df42
--- /dev/null
+++ b/minuitwrp/truetype.c
@@ -0,0 +1,731 @@
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#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>
+
+#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_len;
+ 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;
+
+static FontData font_data = {
+ .ft_library = NULL,
+ .fonts = NULL,
+ .mutex = PTHREAD_MUTEX_INITIALIZER,
+};
+
+#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;
+
+static uint32_t fnv_hash(void *data, uint32_t len)
+{
+ uint8_t *d8 = data;
+ uint32_t *d32 = 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;
+}
+
+static bool gr_ttf_string_cache_equals(void *keyA, void *keyB)
+{
+ StringCacheKey *a = keyA;
+ StringCacheKey *b = keyB;
+ return a->max_width == b->max_width && strcmp(a->text, b->text) == 0;
+}
+
+static int gr_ttf_string_cache_hash(void *key)
+{
+ StringCacheKey *k = key;
+ return fnv_hash(k->text, strlen(k->text));
+}
+
+static bool gr_ttf_font_cache_equals(void *keyA, void *keyB)
+{
+ TrueTypeFontKey *a = keyA;
+ TrueTypeFontKey *b = keyB;
+ return (a->size == b->size) && (a->dpi == b->dpi) && !strcmp(a->path, b->path);
+}
+
+static int gr_ttf_font_cache_hash(void *key)
+{
+ TrueTypeFontKey *k = key;
+
+ 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;
+}
+
+void *gr_ttf_loadFont(const char *filename, int size, int dpi)
+{
+ int error;
+ TrueTypeFont *res = NULL;
+
+ pthread_mutex_lock(&font_data.mutex);
+
+ if(font_data.fonts)
+ {
+ TrueTypeFontKey k = {
+ .size = size,
+ .dpi = dpi,
+ .path = (char*)filename
+ };
+
+ res = hashmapGet(font_data.fonts, &k);
+ if(res)
+ {
+ ++res->refcount;
+ goto exit;
+ }
+ }
+
+ 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 = 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);
+
+ TrueTypeFontKey *key = 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);
+
+exit:
+ pthread_mutex_unlock(&font_data.mutex);
+ return res;
+}
+
+static bool gr_ttf_freeFontCache(void *key, void *value, void *context)
+{
+ TrueTypeCacheEntry *e = value;
+ FT_Done_Glyph((FT_Glyph)e->glyph);
+ free(e);
+ free(key);
+ return true;
+}
+
+static bool gr_ttf_freeStringCache(void *key, void *value, void *context)
+{
+ StringCacheKey *k = key;
+ free(k->text);
+ free(k);
+
+ StringCacheEntry *e = value;
+ free(e->surface.data);
+ free(e);
+ return true;
+}
+
+void gr_ttf_freeFont(void *font)
+{
+ pthread_mutex_lock(&font_data.mutex);
+
+ TrueTypeFont *d = font;
+
+ if(--d->refcount == 0)
+ {
+ hashmapRemove(font_data.fonts, d->key);
+
+ if(hashmapSize(font_data.fonts) == 0)
+ {
+ hashmapFree(font_data.fonts);
+ font_data.fonts = NULL;
+ }
+
+ free(d->key->path);
+ free(d->key);
+
+ 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_unlock(&font_data.mutex);
+}
+
+static TrueTypeCacheEntry *gr_ttf_glyph_cache_peek(TrueTypeFont *font, int char_index)
+{
+ return hashmapGet(font->glyph_cache, &char_index);
+}
+
+static TrueTypeCacheEntry *gr_ttf_glyph_cache_get(TrueTypeFont *font, int char_index)
+{
+ TrueTypeCacheEntry *res = 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;
+ }
+
+ 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 = malloc(sizeof(TrueTypeCacheEntry));
+ memset(res, 0, sizeof(TrueTypeCacheEntry));
+ res->glyph = glyph;
+ FT_Glyph_Get_CBox((FT_Glyph)glyph, FT_GLYPH_BBOX_PIXELS, &res->bbox);
+
+ int *key = malloc(sizeof(int));
+ *key = char_index;
+
+ hashmapPut(font->glyph_cache, key, res);
+ }
+
+ return res;
+}
+
+static int gr_ttf_copy_glyph_to_surface(GGLSurface *dest, FT_BitmapGlyph glyph, int offX, int offY, int base)
+{
+ int 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;
+ }
+
+ dest_itr += (offY + base - glyph->top)*dest->stride + (offX + glyph->left);
+
+ 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 int gr_ttf_render_text(TrueTypeFont *font, GGLSurface *surface, const char *text, int max_width)
+{
+ TrueTypeFont *f = font;
+ TrueTypeCacheEntry *ent;
+ int max_len = 0, total_w = 0;
+ char c;
+ int i, x, diff, char_idx, prev_idx = 0;
+ int height, base;
+ FT_Vector delta;
+ uint8_t *data = NULL;
+ const char *text_itr = text;
+
+ while((c = *text_itr++))
+ {
+ char_idx = FT_Get_Char_Index(f->face, c);
+ 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(max_width != -1 && total_w + diff > max_width)
+ break;
+
+ total_w += diff;
+ }
+ prev_idx = char_idx;
+ ++max_len;
+ }
+
+ if(font->max_height == -1)
+ gr_ttf_getMaxFontHeight(font);
+
+ if(font->max_height == -1)
+ return -1;
+
+ height = font->max_height;
+
+ data = 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 = (void*)data;
+ surface->format = GGL_PIXEL_FORMAT_A_8;
+
+ for(i = 0; i < max_len; ++i)
+ {
+ char_idx = FT_Get_Char_Index(f->face, text[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;
+ }
+
+ prev_idx = char_idx;
+ }
+
+ return max_len;
+}
+
+static StringCacheEntry *gr_ttf_string_cache_peek(TrueTypeFont *font, const char *text, int max_width)
+{
+ StringCacheEntry *res;
+ StringCacheKey k = {
+ .text = (char*)text,
+ .max_width = max_width
+ };
+
+ return hashmapGet(font->string_cache, &k);
+}
+
+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
+ };
+
+ res = hashmapGet(font->string_cache, &k);
+ if(!res)
+ {
+ res = malloc(sizeof(StringCacheEntry));
+ memset(res, 0, sizeof(StringCacheEntry));
+ res->rendered_len = gr_ttf_render_text(font, &res->surface, text, max_width);
+ if(res->rendered_len < 0)
+ {
+ free(res);
+ return NULL;
+ }
+
+ StringCacheKey *new_key = malloc(sizeof(StringCacheKey));
+ memset(new_key, 0, sizeof(StringCacheKey));
+ new_key->max_width = max_width;
+ new_key->text = strdup(text);
+
+ res->key = new_key;
+
+ 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;
+
+ 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;
+}
+
+int gr_ttf_measureEx(const char *s, void *font)
+{
+ TrueTypeFont *f = font;
+ int res = -1;
+
+ pthread_mutex_lock(&f->mutex);
+ StringCacheEntry *e = gr_ttf_string_cache_get(font, s, -1);
+ if(e)
+ res = e->surface.width;
+ pthread_mutex_unlock(&f->mutex);
+
+ return res;
+}
+
+int gr_ttf_maxExW(const char *s, void *font, int max_width)
+{
+ TrueTypeFont *f = font;
+ TrueTypeCacheEntry *ent;
+ int max_len = 0, total_w = 0;
+ char c;
+ int char_idx, prev_idx = 0;
+ FT_Vector delta;
+ StringCacheEntry *e;
+
+ pthread_mutex_lock(&f->mutex);
+
+ e = gr_ttf_string_cache_peek(font, s, max_width);
+ if(e)
+ {
+ max_len = e->rendered_len;
+ pthread_mutex_unlock(&f->mutex);
+ return max_len;
+ }
+
+ for(; (c = *s++); ++max_len)
+ {
+ char_idx = FT_Get_Char_Index(f->face, c);
+ 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)
+ break;
+
+ ent = gr_ttf_glyph_cache_get(f, char_idx);
+ if(!ent)
+ continue;
+
+ total_w += ent->glyph->root.advance.x >> 16;
+ }
+ pthread_mutex_unlock(&f->mutex);
+ return max_len > 0 ? max_len - 1 : 0;
+}
+
+int gr_ttf_textExWH(void *context, int x, int y, const char *s, void *pFont, int max_width, int max_height)
+{
+ GGLContext *gl = context;
+ TrueTypeFont *font = pFont;
+
+ // 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);
+
+ StringCacheEntry *e = gr_ttf_string_cache_get(font, s, max_width);
+ if(!e)
+ {
+ pthread_mutex_unlock(&font->mutex);
+ return -1;
+ }
+
+ int y_bottom = y + e->surface.height;
+ int res = e->rendered_len;
+
+ if(max_height != -1 && max_height < y_bottom)
+ {
+ y_bottom = max_height;
+ if(y_bottom <= y)
+ {
+ pthread_mutex_unlock(&font->mutex);
+ return 0;
+ }
+ }
+
+ gl->bindTexture(gl, &e->surface);
+ 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, -x, -y);
+ gl->recti(gl, x, y, x + e->surface.width, y_bottom);
+
+ pthread_mutex_unlock(&font->mutex);
+ return res;
+}
+
+int gr_ttf_getMaxFontHeight(void *font)
+{
+ int res;
+ TrueTypeFont *f = font;
+
+ pthread_mutex_lock(&f->mutex);
+
+ if(f->max_height == -1)
+ {
+ 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;
+
+ 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;
+
+ 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);
+ }
+ }
+
+ if(bbox.yMin > bbox.yMax)
+ bbox.yMin = bbox.yMax = 0;
+
+ 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;
+ }
+
+ res = f->max_height;
+
+ pthread_mutex_unlock(&f->mutex);
+ return res;
+}
+
+static bool gr_ttf_dump_stats_count_string_cache(void *key, void *value, void *context)
+{
+ int *string_cache_size = context;
+ StringCacheEntry *e = 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 = key;
+ TrueTypeFont *f = value;
+ int *total_string_cache_size = 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: %d entries\n"
+ " string_cache: %d 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("%d 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);
+}
diff --git a/prebuilt/Android.mk b/prebuilt/Android.mk
index 1526a9f..07962c5 100644
--- a/prebuilt/Android.mk
+++ b/prebuilt/Android.mk
@@ -40,6 +40,7 @@
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libext2fs.so
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libext2_profile.so
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libext2_uuid.so
+RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libpng.so
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/liblog.so
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libm.so
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libstdc++.so
@@ -122,6 +123,9 @@
ifneq ($(wildcard system/core/reboot/Android.mk),)
RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/reboot
endif
+ifneq ($(TW_DISABLE_TTF), true)
+ RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libft2.so
+endif
TWRP_AUTOGEN := $(intermediates)/teamwin