mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-21 06:45:39 -06:00
Draw: Fixed Color Emoji with FreeType
This commit is contained in:
parent
7edfc57742
commit
d16b2ab18a
9 changed files with 77 additions and 26 deletions
|
|
@ -8,11 +8,6 @@ int FontTypeReader::Error()
|
|||
throw Fail(); return 0;
|
||||
}
|
||||
|
||||
int FontTypeReader::Error()
|
||||
{
|
||||
throw Fail(); return 0;
|
||||
}
|
||||
|
||||
int FontTypeReader::Peek8(const char *s)
|
||||
{
|
||||
return s + 1 < data.end() ? (byte)*s : Error();
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ FT_Face FTFace(Font fnt, String *rpath = NULL);
|
|||
|
||||
struct FontSysData {
|
||||
cairo_scaled_font_t *scaled_font;
|
||||
bool colorimg = false;
|
||||
Sizef colorimg_size;
|
||||
|
||||
void Init(Font font, int angle);
|
||||
~FontSysData() { cairo_scaled_font_destroy(scaled_font); }
|
||||
|
|
@ -31,7 +33,10 @@ void FontSysData::Init(Font font, int angle)
|
|||
|
||||
cairo_matrix_t font_matrix[1], ctm[1];
|
||||
cairo_matrix_init_identity(ctm);
|
||||
cairo_matrix_init_scale(font_matrix, font.GetHeight(), font.GetHeight());
|
||||
|
||||
int fh = font.GetHeight();
|
||||
|
||||
cairo_matrix_init_scale(font_matrix, fh, fh);
|
||||
|
||||
if(font.IsItalic() && !(FTFace(font)->style_flags & FT_STYLE_FLAG_ITALIC)) {
|
||||
cairo_matrix_t sheer[1];
|
||||
|
|
@ -42,6 +47,7 @@ void FontSysData::Init(Font font, int angle)
|
|||
|
||||
if(angle)
|
||||
cairo_matrix_rotate(font_matrix, -angle * M_2PI / 3600);
|
||||
|
||||
cairo_font_options_t *opt = cairo_font_options_create();
|
||||
scaled_font = cairo_scaled_font_create(font_face, font_matrix, ctm, opt);
|
||||
|
||||
|
|
@ -66,6 +72,15 @@ void SystemDraw::FlushText()
|
|||
{
|
||||
if(textcache.GetCount() == 0)
|
||||
return;
|
||||
static LRUCache<FontSysData, Tuple2<Font, int> > cache;
|
||||
FontDataSysMaker m;
|
||||
m.font = textfont;
|
||||
m.angle = textangle;
|
||||
FontSysData& sf = cache.Get(m);
|
||||
|
||||
cairo_set_scaled_font(cr, sf.scaled_font);
|
||||
SetColor(textink);
|
||||
|
||||
Buffer<cairo_glyph_t> gs(textcache.GetCount());
|
||||
for(int i = 0; i < textcache.GetCount(); i++) {
|
||||
cairo_glyph_t& g = gs[i];
|
||||
|
|
@ -74,14 +89,6 @@ void SystemDraw::FlushText()
|
|||
g.y = textcache[i].y;
|
||||
}
|
||||
|
||||
static LRUCache<FontSysData, Tuple2<Font, int> > cache;
|
||||
FontDataSysMaker m;
|
||||
m.font = textfont;
|
||||
m.angle = textangle;
|
||||
FontSysData& sf = cache.Get(m);
|
||||
cairo_set_scaled_font(cr, sf.scaled_font);
|
||||
|
||||
SetColor(textink);
|
||||
cairo_show_glyphs(cr, gs, textcache.GetCount());
|
||||
|
||||
cache.Shrink(INT_MAX, 128);
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ public:
|
|||
SPECIAL = 0x0010,
|
||||
SERIFSTYLE = 0x0020,
|
||||
SCRIPTSTYLE = 0x0040,
|
||||
COLORIMG = 0x0080, // freetype color bitmap font (emojis)
|
||||
};
|
||||
|
||||
static int GetFaceCount();
|
||||
|
|
|
|||
|
|
@ -68,12 +68,12 @@ FT_Face CreateFTFace(const FcPattern *pattern, String *rpath) {
|
|||
if (FcPatternGetDouble(pattern, FC_ASPECT, 0, &aspect) != FcResultMatch)
|
||||
aspect = 1.0;
|
||||
|
||||
FT_F26Dot6 ysize = (FT_F26Dot6) (dsize * 64.0);
|
||||
FT_F26Dot6 xsize = (FT_F26Dot6) (dsize * aspect * 64.0);
|
||||
|
||||
if(FT_New_Face(sFTlib, (const char *)filename, 0, &face))
|
||||
return NULL;
|
||||
|
||||
FT_F26Dot6 ysize = (FT_F26Dot6) (dsize * 64.0);
|
||||
FT_F26Dot6 xsize = (FT_F26Dot6) (dsize * aspect * 64.0);
|
||||
|
||||
FT_Set_Char_Size(face, xsize, ysize, 0, 0);
|
||||
return face;
|
||||
}
|
||||
|
|
@ -154,6 +154,13 @@ CommonFontInfo GetFontInfoSys(Font font)
|
|||
strcpy(fi.path, ~path);
|
||||
else
|
||||
*fi.path = 0;
|
||||
|
||||
if(font.GetFaceInfo() & Font::COLORIMG) {
|
||||
fi.colorimg_cy = fi.ascent + fi.descent;
|
||||
int h = font.GetHeight();
|
||||
fi.ascent = h * fi.ascent / fi.colorimg_cy;
|
||||
fi.descent = h - fi.ascent;
|
||||
}
|
||||
}
|
||||
return fi;
|
||||
}
|
||||
|
|
@ -177,16 +184,21 @@ GlyphInfo GetGlyphInfoSys(Font font, int chr)
|
|||
LTIMING("GetGlyphInfoSys 2");
|
||||
int glyph_index = FT_Get_Char_Index(face, chr);
|
||||
if(glyph_index) {
|
||||
// if(GetGlyphInfoSysXft)
|
||||
// return (*GetGlyphInfoSysXft)(font, chr);
|
||||
if(FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP) == 0 ||
|
||||
FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT) == 0) {
|
||||
FT_Glyph_Metrics& m = face->glyph->metrics;
|
||||
int left = FLOOR(m.horiBearingX);
|
||||
int width = TRUNC(CEIL(m.horiBearingX + m.width) - left);
|
||||
gi.width = TRUNC(ROUND(face->glyph->advance.x));
|
||||
if(font.GetFaceInfo() & Font::COLORIMG) {
|
||||
gi.lspc = gi.rspc = 0;
|
||||
int q = GetFontInfo(font).colorimg_cy;
|
||||
gi.width = font.GetCy() * gi.width / q + max(1, font.GetCy() / 10); // add a little space there...
|
||||
}
|
||||
else {
|
||||
gi.lspc = TRUNC(left);
|
||||
gi.rspc = gi.width - width - gi.lspc;
|
||||
}
|
||||
gi.glyphi = glyph_index;
|
||||
}
|
||||
}
|
||||
|
|
@ -233,7 +245,7 @@ Vector<FaceInfo> GetAllFacesSys()
|
|||
if(FcPatternGetBool(pt, FC_SYMBOL, 0, &bv) == 0 && bv)
|
||||
fi.info |= Font::SPECIAL;
|
||||
if(FcPatternGetBool(pt, FC_COLOR, 0, &bv) == 0 && bv)
|
||||
fi.info |= Font::SPECIAL;
|
||||
fi.info |= Font::COLORIMG;
|
||||
if(FcPatternGetBool(pt, FC_SCALABLE, 0, &bv) == 0 && bv)
|
||||
fi.info |= Font::SCALEABLE;
|
||||
String h = ToLower(fi.name);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ struct CommonFontInfo {
|
|||
bool scaleable;
|
||||
bool ttf;
|
||||
int aux;
|
||||
int colorimg_cy; // FreeType color Emoji original height
|
||||
|
||||
char path[256]; // optional (linux only)
|
||||
int fonti = 0; // font index in .ttc, .otc
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Predefined replacement fonts; if codepoint is not found in these, remaining fonts cmaps from host are loaded
|
||||
|
||||
#if defined(PLATFORM_POSIX) && !defined(PLATFORM_COCOA)
|
||||
{ "Noto Color Emoji", { 2,0,6,9,0,0,0,0,0,0 }, { 0xa0000000,0x03a00000,0x00000000,0x00000000,0x00000038,0x00000000,0x00000000,0x00000001 } },
|
||||
{ "Abyssinica SIL", { 2,0,0,0,0,0,0,0,0,0 }, { 0xfe1d0000,0x23400000,0x0080010c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } },
|
||||
{ "Andale Mono", { 2,11,5,9,0,0,0,0,0,4 }, { 0xff17e000,0x07000000,0x0000002c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } },
|
||||
{ "AnjaliOldLipi", { 2,0,6,3,0,0,0,0,0,0 }, { 0xfc100000,0x43000000,0x00000264,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } },
|
||||
|
|
|
|||
|
|
@ -5,20 +5,21 @@ using namespace Upp;
|
|||
struct MyApp : TopWindow {
|
||||
void Paint(Draw& w) {
|
||||
String text;
|
||||
text << WString(0x1F970, 1).ToString();
|
||||
text << WString(0x1F603, 1).ToString();
|
||||
text << WString(0x1F923, 1).ToString();
|
||||
text << " Quick brown fox, 訓民正音 (훈민정음) ";
|
||||
|
||||
w.DrawRect(GetSize(), White());
|
||||
int y = 10;
|
||||
int x = 10;
|
||||
for(int i = 0; i < Font::GetFaceCount(); i++)
|
||||
for(int i = 0; i < 3/*Font::GetFaceCount()*/; i++)
|
||||
{
|
||||
Font fnt(i, 30);
|
||||
DLOG(i << " " << fnt << " " << fnt[0x1F970]);
|
||||
if(fnt.IsSpecial()) continue;
|
||||
fnt.Italic();
|
||||
String n = AsString(i) + ": " + fnt.GetFaceName() + ": ";
|
||||
if(fnt.IsSpecial())
|
||||
n << " (special)";
|
||||
String n; // = AsString(i) + ": " + fnt.GetFaceName() + ": ";
|
||||
w.DrawText(x, y, n, StdFont());
|
||||
w.DrawText(x + GetTextSize(n, StdFont()).cx, y, text, fnt);
|
||||
y += fnt.GetLineHeight() + 10;
|
||||
|
|
|
|||
9
upptst/ColorEmoji/ColorEmoji.upp
Normal file
9
upptst/ColorEmoji/ColorEmoji.upp
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
uses
|
||||
CtrlLib;
|
||||
|
||||
file
|
||||
main.cpp;
|
||||
|
||||
mainconfig
|
||||
"" = "GUI";
|
||||
|
||||
24
upptst/ColorEmoji/main.cpp
Normal file
24
upptst/ColorEmoji/main.cpp
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#include <CtrlLib/CtrlLib.h>
|
||||
|
||||
using namespace Upp;
|
||||
|
||||
struct MyApp : TopWindow {
|
||||
void Paint(Draw& w) {
|
||||
w.DrawRect(GetSize(), White());
|
||||
String text;
|
||||
text << "Behold: "
|
||||
<< WString(0x1F970, 1).ToString()
|
||||
<< WString(0x1F603, 1).ToString()
|
||||
<< WString(0x1F923, 1).ToString()
|
||||
<< WString(0x1F970, 1).ToString()
|
||||
<< " is not that nice?";
|
||||
;
|
||||
w.DrawText(500, 200, text, StdFont());
|
||||
w.DrawText(500, 250, text, StdFont().Italic());
|
||||
w.DrawText(500, 700, 300, text, StdFont());
|
||||
}
|
||||
};
|
||||
|
||||
GUI_APP_MAIN {
|
||||
MyApp().Sizeable().Zoomable().Run();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue