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>
This commit is contained in:
@@ -59,6 +59,9 @@ endif
|
||||
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 @@ ifeq ($(TW_CUSTOM_THEME),)
|
||||
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 @@ $(TWRP_RES_GEN):
|
||||
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
|
||||
|
||||
+1
-1
@@ -177,7 +177,7 @@ GUIConsole::GUIConsole(xml_node<>* node) : GUIObject(node)
|
||||
}
|
||||
}
|
||||
|
||||
gr_getFontDetails(mFont, &mFontHeight, NULL);
|
||||
mFontHeight = gr_getMaxFontHeight(mFont ? mFont->GetResource() : NULL);
|
||||
SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
|
||||
SetRenderPos(mConsoleX, mConsoleY);
|
||||
return;
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
Binary file not shown.
@@ -333,7 +333,7 @@ GUIFileSelector::GUIFileSelector(xml_node<>* node) : GUIObject(node)
|
||||
}
|
||||
|
||||
// Retrieve the line height
|
||||
gr_getFontDetails(mFont ? mFont->GetResource() : NULL, &mFontHeight, NULL);
|
||||
mFontHeight = gr_getMaxFontHeight(mFont ? mFont->GetResource() : NULL);
|
||||
mLineHeight = mFontHeight;
|
||||
mHeaderH = mFontHeight;
|
||||
|
||||
|
||||
+1
-1
@@ -139,7 +139,7 @@ GUIInput::GUIInput(xml_node<>* node)
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -271,7 +271,7 @@ GUIListBox::GUIListBox(xml_node<>* node) : GUIObject(node)
|
||||
}
|
||||
|
||||
// Retrieve the line height
|
||||
gr_getFontDetails(mFont ? mFont->GetResource() : NULL, &mFontHeight, NULL);
|
||||
mFontHeight = gr_getMaxFontHeight(mFont ? mFont->GetResource() : NULL);
|
||||
mLineHeight = mFontHeight;
|
||||
mHeaderH = mFontHeight;
|
||||
|
||||
|
||||
@@ -273,7 +273,7 @@ GUIPartitionList::GUIPartitionList(xml_node<>* node) : GUIObject(node)
|
||||
}
|
||||
|
||||
// Retrieve the line height
|
||||
gr_getFontDetails(mFont ? mFont->GetResource() : NULL, &mFontHeight, NULL);
|
||||
mFontHeight = gr_getMaxFontHeight(mFont ? mFont->GetResource() : NULL);
|
||||
mLineHeight = mFontHeight;
|
||||
mHeaderH = mFontHeight;
|
||||
|
||||
|
||||
+61
-6
@@ -65,27 +65,82 @@ FontResource::FontResource(xml_node<>* node, ZipArchive* pZip)
|
||||
: 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)
|
||||
|
||||
@@ -38,6 +38,14 @@ typedef enum {
|
||||
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 @@ public:
|
||||
|
||||
protected:
|
||||
void* mFont;
|
||||
Type m_type;
|
||||
};
|
||||
|
||||
class ImageResource : public Resource
|
||||
|
||||
+1
-1
@@ -198,7 +198,7 @@ GUISliderValue::GUISliderValue(xml_node<>* node) : GUIObject(node)
|
||||
}
|
||||
}
|
||||
|
||||
gr_getFontDetails(mFont ? mFont->GetResource() : NULL, (unsigned*) &mFontHeight, NULL);
|
||||
mFontHeight = gr_getMaxFontHeight(mFont ? mFont->GetResource() : NULL);
|
||||
|
||||
if(mShowCurr)
|
||||
{
|
||||
|
||||
+1
-1
@@ -97,7 +97,7 @@ GUIText::GUIText(xml_node<>* node)
|
||||
mLastValue = parseText();
|
||||
if (mLastValue != mText) mIsStatic = 0;
|
||||
|
||||
gr_getFontDetails(mFont ? mFont->GetResource() : NULL, (unsigned*) &mFontHeight, NULL);
|
||||
mFontHeight = gr_getMaxFontHeight(mFont ? mFont->GetResource() : NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+10
-2
@@ -107,8 +107,16 @@ ifneq ($(TW_WHITELIST_INPUT),)
|
||||
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
|
||||
|
||||
|
||||
+42
-59
@@ -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 @@ int gr_measureEx(const char *s, void* font)
|
||||
|
||||
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 @@ int gr_maxExW(const char *s, void* font, int max_width)
|
||||
|
||||
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 @@ int gr_maxExW(const char *s, void* font, int max_width)
|
||||
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 @@ int gr_textEx(int x, int y, const char *s, void* pFont)
|
||||
/* 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 @@ int gr_textExW(int x, int y, const char *s, void* pFont, int max_width)
|
||||
/* 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 @@ int gr_textExWH(int x, int y, const char *s, void* pFont, int max_width, int max
|
||||
/* 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 @@ int gr_textExWH(int x, int y, const char *s, void* pFont, int max_width, int max
|
||||
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 @@ void* gr_loadFont(const char* fontName)
|
||||
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 @@ static void gr_init_font(void)
|
||||
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;
|
||||
|
||||
+18
-3
@@ -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 @@ void gr_fill(int x, int y, int w, int h);
|
||||
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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -40,6 +40,7 @@ RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libext2_e2p.so
|
||||
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 @@ endif
|
||||
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user