mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-21 06:45:39 -06:00
Draw: Color Emoji now prefered as replacement
This commit is contained in:
parent
1a43549d5b
commit
ee220a64aa
9 changed files with 459 additions and 30 deletions
11
uppbox/Emoji/Emoji.upp
Normal file
11
uppbox/Emoji/Emoji.upp
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
uses
|
||||||
|
CtrlLib;
|
||||||
|
|
||||||
|
file
|
||||||
|
TypeReader.h,
|
||||||
|
TypeReader.cpp,
|
||||||
|
main.cpp;
|
||||||
|
|
||||||
|
mainconfig
|
||||||
|
"" = "GUI";
|
||||||
|
|
||||||
214
uppbox/Emoji/TypeReader.cpp
Normal file
214
uppbox/Emoji/TypeReader.cpp
Normal file
|
|
@ -0,0 +1,214 @@
|
||||||
|
#include "TypeReader.h"
|
||||||
|
|
||||||
|
#define LLOG(x) // LOG(x)
|
||||||
|
#define LDUMP(x) // LOG(#x << " = " << x);
|
||||||
|
|
||||||
|
int FontTypeReader::Error()
|
||||||
|
{
|
||||||
|
throw Fail(); return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FontTypeReader::Peek8(const char *s)
|
||||||
|
{
|
||||||
|
return s + 1 < data.end() ? (byte)*s : Error();
|
||||||
|
}
|
||||||
|
|
||||||
|
int FontTypeReader::Peek16(const char *s)
|
||||||
|
{
|
||||||
|
return s + 2 < data.end() ? Peek16be(s) : Error();
|
||||||
|
}
|
||||||
|
|
||||||
|
int FontTypeReader::Peek32(const char *s)
|
||||||
|
{
|
||||||
|
return s + 4 < data.end() ? Peek32be(s) : Error();
|
||||||
|
}
|
||||||
|
|
||||||
|
int FontTypeReader::Peek8(const char *s, int i)
|
||||||
|
{
|
||||||
|
return Peek8(s + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FontTypeReader::Peek16(const char *s, int i)
|
||||||
|
{
|
||||||
|
return Peek16(s + 2 * i);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FontTypeReader::Peek32(const char *s, int i)
|
||||||
|
{
|
||||||
|
return Peek32(s + 4 * i);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FontTypeReader::Read8(const char *&s)
|
||||||
|
{
|
||||||
|
int q = byte(*s);
|
||||||
|
s++;
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FontTypeReader::Read16(const char *&s)
|
||||||
|
{
|
||||||
|
int q = Peek16(s);
|
||||||
|
s += 2;
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FontTypeReader::Read32(const char *&s)
|
||||||
|
{
|
||||||
|
int q = Peek32(s);
|
||||||
|
s += 4;
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FontTypeReader::Open(Font font, bool symbol, bool justcheck)
|
||||||
|
{
|
||||||
|
// DDUMP(fnt.GetCount());
|
||||||
|
try {
|
||||||
|
int i;
|
||||||
|
#if 0
|
||||||
|
for(i = 0; i < table.GetCount(); i++)
|
||||||
|
LLOG("table: " << table.GetKey(i) << " offset: " << table[i].offset << " length: " << table[i].length);
|
||||||
|
|
||||||
|
s = Seek("hmtx");
|
||||||
|
int aw = 0;
|
||||||
|
for(i = 0; i < hhea.numOfLongHorMetrics; i++) {
|
||||||
|
aw = glyphinfo[i].advanceWidth = (uint16)Read16(s);
|
||||||
|
glyphinfo[i].leftSideBearing = (int16)Read16(s);
|
||||||
|
}
|
||||||
|
for(; i < maxp.numGlyphs; i++) {
|
||||||
|
glyphinfo[i].advanceWidth = aw;
|
||||||
|
glyphinfo[i].leftSideBearing = (int16)Read16(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
s = Seek("loca");
|
||||||
|
for(i = 0; i < maxp.numGlyphs; i++)
|
||||||
|
if(head.indexToLocFormat) {
|
||||||
|
glyphinfo[i].offset = Peek32(s, i);
|
||||||
|
glyphinfo[i].size = Peek32(s, i + 1) - glyphinfo[i].offset;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
glyphinfo[i].offset = 2 * (word)Peek16(s, i);
|
||||||
|
glyphinfo[i].size = 2 * (word)Peek16(s, i + 1) - glyphinfo[i].offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < maxp.numGlyphs; i++)
|
||||||
|
LLOG(i << " advance: " << glyphinfo[i].advanceWidth << ", left: " << glyphinfo[i].leftSideBearing
|
||||||
|
<< ", offset: " << glyphinfo[i].offset << ", size: " << glyphinfo[i].size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
data = font.GetData("OS/2");
|
||||||
|
panose.Clear();
|
||||||
|
if(data.GetCount() > 32 + 10)
|
||||||
|
panose = data.Mid(32, 10);
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
data = font.GetData("cmap");
|
||||||
|
for(int pass = 0; pass < 2; pass++) {
|
||||||
|
const char *p = data;
|
||||||
|
// LOGHEXDUMP(p, 256);
|
||||||
|
p += 2;
|
||||||
|
int n = Read16(p);
|
||||||
|
// DDUMP(n);
|
||||||
|
while(n--) {
|
||||||
|
int pid = Read16(p);
|
||||||
|
int psid = Read16(p);
|
||||||
|
int offset = Read32(p);
|
||||||
|
if(offset < 0 || offset > data.GetCount())
|
||||||
|
Error();
|
||||||
|
int format = Peek16(~data + offset);
|
||||||
|
LLOG("cmap pid: " << pid << " psid: " << psid << " format: " << format);
|
||||||
|
//Test with Symbol font !!!; improve - Unicode first, 256 bytes later..., symbol...
|
||||||
|
if(symbol) {
|
||||||
|
if(pid == 1 && psid == 0 && Peek16(~data + offset) == 0) {
|
||||||
|
LLOG("Reading symbol table");
|
||||||
|
p = ~data + offset + 6;
|
||||||
|
for(int i = 0; i < 256; i++);
|
||||||
|
//SetGlyph(i, (byte)p[i]);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if((pid == 3 && psid == 10) || (pid == 0 && psid == 4) && format == 12 && pass == 0) {
|
||||||
|
const char *p = ~data + offset;
|
||||||
|
int ngroups = Peek32(p + 12);
|
||||||
|
p += 16; // pointer to groups table
|
||||||
|
for(int i = 0; i < ngroups; i++) {
|
||||||
|
LLOG(Peek32(p) << " - " << Peek32(p + 4) << ", glyphi: " << Peek32(p + 8));
|
||||||
|
ranges.Add(MakeTuple(Peek32(p), Peek32(p + 4)));
|
||||||
|
p += 12;
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if((pid == 3 && psid == 1) || (pid == 0 && psid == 3) && format == 4 && pass == 1) {
|
||||||
|
const char *p = ~data + offset;
|
||||||
|
int n = Peek16(p + 6) >> 1;
|
||||||
|
LLOG("Found UNICODE encoding, offset " << offset << ", segments " << n);
|
||||||
|
const char *seg_end = p + 14;
|
||||||
|
const char *seg_start = seg_end + 2 * n + 2;
|
||||||
|
const char *idDelta = seg_start + 2 * n;
|
||||||
|
const char *idRangeOffset = idDelta + 2 * n;
|
||||||
|
for(int i = 0; i < n; i++) {
|
||||||
|
int start = Peek16(seg_start, i);
|
||||||
|
int end = Peek16(seg_end, i);
|
||||||
|
ranges.Add(MakeTuple(start, end));
|
||||||
|
#if 0
|
||||||
|
int delta = Peek16(idDelta, i);
|
||||||
|
int ro = Peek16(idRangeOffset, i);
|
||||||
|
if (ro && delta == 0) {
|
||||||
|
LOG(start << " - " << end);
|
||||||
|
LLOG("RangeOffset start: " << start << ", end: " << end << ", delta: " << (int16)delta);
|
||||||
|
LLOG("ro " << ro);
|
||||||
|
// const char *q = idRangeOffset + 2 * i + ro;
|
||||||
|
// for(int c = start; c <= end; c++) {
|
||||||
|
// SetGlyph(c, (word)Read16(q));
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG(start << " - " << end);
|
||||||
|
LLOG("Delta start: " << start << ", end: " << end << ", delta: " << (int16)delta);
|
||||||
|
// for(int c = start; c <= end; c++);
|
||||||
|
// SetGlyph(c, c + delta);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
done:;
|
||||||
|
#if 0
|
||||||
|
String names = font.GetData("name");
|
||||||
|
if(names.GetCount()) {
|
||||||
|
const char *strings = names;
|
||||||
|
const char *s = strings + 2;
|
||||||
|
int count = Read16(s);
|
||||||
|
strings += (word)Read16(s);
|
||||||
|
for(int i = 0; i < count; i++) {
|
||||||
|
int platform = Read16(s);
|
||||||
|
s += 4;
|
||||||
|
if(Read16(s) == 6) {
|
||||||
|
int len = Read16(s);
|
||||||
|
int offset = Read16(s);
|
||||||
|
if(platform == 1)
|
||||||
|
ps_name = String(strings + offset, len);
|
||||||
|
else {
|
||||||
|
s = strings + offset;
|
||||||
|
len >>= 1;
|
||||||
|
while(len--)
|
||||||
|
ps_name.Cat(Read16(s));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
s += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DDUMP(ps_name);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
catch(Fail) {
|
||||||
|
LLOG("ERROR");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
40
uppbox/Emoji/TypeReader.h
Normal file
40
uppbox/Emoji/TypeReader.h
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
#ifndef _FontMaps2_TypeReader_h_
|
||||||
|
#define _FontMaps2_TypeReader_h_
|
||||||
|
|
||||||
|
#include <CtrlLib/CtrlLib.h>
|
||||||
|
|
||||||
|
using namespace Upp;
|
||||||
|
|
||||||
|
class FontTypeReader {
|
||||||
|
String data;
|
||||||
|
|
||||||
|
struct Table : Moveable<Table> {
|
||||||
|
int offset;
|
||||||
|
int length;
|
||||||
|
};
|
||||||
|
VectorMap<String, Table> table;
|
||||||
|
|
||||||
|
struct Fail {};
|
||||||
|
static int Error();
|
||||||
|
|
||||||
|
int Peek8(const char *s);
|
||||||
|
int Peek16(const char *s);
|
||||||
|
int Peek32(const char *s);
|
||||||
|
int Peek8(const char *s, int i);
|
||||||
|
int Peek16(const char *s, int i);
|
||||||
|
int Peek32(const char *s, int i);
|
||||||
|
int Read8(const char *&s);
|
||||||
|
int Read16(const char *&s);
|
||||||
|
int Read32(const char *&s);
|
||||||
|
|
||||||
|
public:
|
||||||
|
String ps_name;
|
||||||
|
|
||||||
|
Array<Tuple<int, int>> ranges;
|
||||||
|
|
||||||
|
String panose;
|
||||||
|
|
||||||
|
bool Open(Font font, bool symbol = false, bool justcheck = false);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
109
uppbox/Emoji/main.cpp
Normal file
109
uppbox/Emoji/main.cpp
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
#include <CtrlLib/CtrlLib.h>
|
||||||
|
#include "TypeReader.h"
|
||||||
|
|
||||||
|
using namespace Upp;
|
||||||
|
|
||||||
|
#define MAKE_TT_TABLE_NAME(c1, c2, c3, c4) \
|
||||||
|
(((uint32)c4) << 24 | ((uint32)c3) << 16 | ((uint32)c2) << 8 | ((uint32)c1))
|
||||||
|
|
||||||
|
#define CMAP (MAKE_TT_TABLE_NAME('c','m','a','p'))
|
||||||
|
|
||||||
|
#ifdef PLATFORM_WIN32
|
||||||
|
|
||||||
|
namespace Upp {
|
||||||
|
HFONT GetWin32Font(Font fnt, int angle);
|
||||||
|
};
|
||||||
|
|
||||||
|
String GetFontDataSys(Font font, dword table)
|
||||||
|
{
|
||||||
|
String r;
|
||||||
|
HFONT hfont = GetWin32Font(font, 0);
|
||||||
|
if(hfont) {
|
||||||
|
HDC hdc = CreateIC("DISPLAY", NULL, NULL, NULL);
|
||||||
|
HFONT ohfont = (HFONT) ::SelectObject(hdc, hfont);
|
||||||
|
DWORD size = GetFontData(hdc, table, 0, NULL, 0);
|
||||||
|
if(size == GDI_ERROR) {
|
||||||
|
return Null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
StringBuffer b(size);
|
||||||
|
GetFontData(hdc, table, 0, b, size);
|
||||||
|
r = b;
|
||||||
|
}
|
||||||
|
::SelectObject(hdc, ohfont);
|
||||||
|
::DeleteDC(hdc);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
String ReadFontTable(Stream& in, const char *table, int fonti = 0)
|
||||||
|
{
|
||||||
|
in.Seek(0);
|
||||||
|
int q = in.Get32be();
|
||||||
|
if(q == 0x74746366) { // true type collection
|
||||||
|
in.Get32(); // skip major/minor version
|
||||||
|
int nfonts = in.Get32be();
|
||||||
|
if(fonti >= nfonts)
|
||||||
|
return Null;
|
||||||
|
in.SeekCur(fonti * 4);
|
||||||
|
int offset = in.Get32be();
|
||||||
|
if(offset < 0 || offset >= in.GetSize())
|
||||||
|
return Null;
|
||||||
|
in.Seek(offset);
|
||||||
|
q = in.Get32be();
|
||||||
|
}
|
||||||
|
if(q != 0x74727565 && q != 0x00010000)
|
||||||
|
return Null;
|
||||||
|
int n = in.Get16be();
|
||||||
|
in.Get32();
|
||||||
|
in.Get16();
|
||||||
|
while(n--) {
|
||||||
|
if(in.IsError() || in.IsEof()) return Null;
|
||||||
|
String tab = in.Get(4);
|
||||||
|
in.Get32();
|
||||||
|
int offset = in.Get32be();
|
||||||
|
int length = in.Get32be();
|
||||||
|
if(tab == table) {
|
||||||
|
if(offset < 0 || length < 0 || offset + length > in.GetSize())
|
||||||
|
return Null;
|
||||||
|
in.Seek(offset);
|
||||||
|
return in.Get(length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Null;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
Font fnt(Font::FindFaceNameIndex("Noto Color Emoji"), 20);
|
||||||
|
FontTypeReader r;
|
||||||
|
r.Open(fnt);
|
||||||
|
for(auto r : r.ranges) {
|
||||||
|
for(int c = r.a; c <= r.b; c++) {
|
||||||
|
w.DrawText(x, y, WString(c, 1), fnt);
|
||||||
|
w.DrawText(x + fnt[c], y, WString(c, 1));
|
||||||
|
w.DrawText(x + fnt[c] + StdFont()[c] + 4, y, Format("%x", c));
|
||||||
|
y += 30;
|
||||||
|
if(y > GetSize().cy - 30) {
|
||||||
|
y = 10;
|
||||||
|
x += 130;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
GUI_APP_MAIN {
|
||||||
|
MyApp().Sizeable().Zoomable().Run();
|
||||||
|
}
|
||||||
|
|
@ -75,6 +75,37 @@ String ReadFontTable(Stream& in, const char *table, int fonti = 0)
|
||||||
return Null;
|
return Null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
Font fnt(Font::FindFaceNameIndex("Noto Color Emoji"), 20);
|
||||||
|
FontTypeReader r;
|
||||||
|
r.Open(font);
|
||||||
|
for(auto r : r.ranges) {
|
||||||
|
for(int c = r.a; c <= r.b; c++) {
|
||||||
|
w.DrawText(x, y, WString(c, 1), fnt);
|
||||||
|
y += 30;
|
||||||
|
if(y > GetSize().cy - 30) {
|
||||||
|
y = 10;
|
||||||
|
x += 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
GUI_APP_MAIN {
|
||||||
|
MyApp().Sizeable().Zoomable().Run();
|
||||||
|
}
|
||||||
|
|
||||||
GUI_APP_MAIN
|
GUI_APP_MAIN
|
||||||
{
|
{
|
||||||
// FileIn in("C:/Windows/Fonts/arial.ttf");
|
// FileIn in("C:/Windows/Fonts/arial.ttf");
|
||||||
|
|
@ -85,24 +116,18 @@ GUI_APP_MAIN
|
||||||
DDUMPHEX(ReadFontTable(in, "cmap", 2));
|
DDUMPHEX(ReadFontTable(in, "cmap", 2));
|
||||||
return;
|
return;
|
||||||
*/
|
*/
|
||||||
#if 0
|
#if 1
|
||||||
Font font(Font::FindFaceNameIndex("Noto Serif CJK KR"), 20);
|
/* for(int i = 0; i < Font::GetFaceCount(); i++)
|
||||||
|
DDUMP(Font::GetFaceName(i));
|
||||||
// Font font = Roman(20);
|
return;*/
|
||||||
|
Font font(Font::FindFaceNameIndex("Noto Color Emoji"), 20);
|
||||||
// SaveFile("d:/xxx/font.bin", GetFontDataSys(font, 0));
|
|
||||||
|
|
||||||
// String cmap = GetFontDataSys(font, CMAP);
|
|
||||||
// LOGHEXDUMP(~cmap, 256);
|
|
||||||
|
|
||||||
FontTypeReader r;
|
FontTypeReader r;
|
||||||
// r.Open(Arial(20).GetData());
|
|
||||||
DDUMP(font.GetFaceName());
|
|
||||||
r.Open(font);
|
r.Open(font);
|
||||||
DDUMPHEX(r.panose);
|
for(auto r : r.ranges) {
|
||||||
return;
|
DUMPHEX(r.a);
|
||||||
|
DUMPHEX(r.b);
|
||||||
|
RLOG("=================");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
Progress pi;
|
Progress pi;
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,13 @@ struct FontGlyphConsumer {
|
||||||
|
|
||||||
class FontInfo;
|
class FontInfo;
|
||||||
|
|
||||||
|
|
||||||
|
inline
|
||||||
|
bool PreferColorEmoji(int c)
|
||||||
|
{ // for these codepoints we prefer replacemnet color emoji even if glyphs is in the font
|
||||||
|
return c >= 0x2600 && c <= 0x27ef || c >= 0x1f004 && c <= 0x1f251 || c >= 0x1f300 && c <= 0x1faf6;
|
||||||
|
}
|
||||||
|
|
||||||
class Font : public ValueType<Font, FONT_V, Moveable<Font> >{
|
class Font : public ValueType<Font, FONT_V, Moveable<Font> >{
|
||||||
union {
|
union {
|
||||||
int64 data;
|
int64 data;
|
||||||
|
|
|
||||||
|
|
@ -421,21 +421,29 @@ struct GlyphInfoMaker : ValueMaker {
|
||||||
CharEntry& e = CreateRawValue<CharEntry>(object);
|
CharEntry& e = CreateRawValue<CharEntry>(object);
|
||||||
e.font = font.AsInt64();
|
e.font = font.AsInt64();
|
||||||
e.chr = chr;
|
e.chr = chr;
|
||||||
e.info = GetGlyphInfoSys(font, chr);
|
Font rfnt;
|
||||||
if(!e.info.IsNormal()) {
|
if(PreferColorEmoji(chr) && !(font.GetFaceInfo() & Font::COLORIMG)
|
||||||
ComposedGlyph cg;
|
&& Replace(font, chr, rfnt) && rfnt != font) {
|
||||||
Font rfnt;
|
e.info.width = 0x8000;
|
||||||
if(Compose(font, chr, cg)) {
|
e.info.lspc = rfnt.GetFace();
|
||||||
e.info.lspc = -1;
|
e.info.rspc = rfnt.GetHeight();
|
||||||
e.info.rspc = (int16)cg.basic_char;
|
}
|
||||||
|
else {
|
||||||
|
e.info = GetGlyphInfoSys(font, chr);
|
||||||
|
if(!e.info.IsNormal()) {
|
||||||
|
ComposedGlyph cg;
|
||||||
|
if(Compose(font, chr, cg)) {
|
||||||
|
e.info.lspc = -1;
|
||||||
|
e.info.rspc = (int16)cg.basic_char;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(Replace(font, chr, rfnt)) {
|
||||||
|
e.info.lspc = rfnt.GetFace();
|
||||||
|
e.info.rspc = rfnt.GetHeight();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
e.info.lspc = -2;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
if(Replace(font, chr, rfnt)) {
|
|
||||||
e.info.lspc = rfnt.GetFace();
|
|
||||||
e.info.rspc = rfnt.GetHeight();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
e.info.lspc = -2;
|
|
||||||
}
|
}
|
||||||
return sizeof(e);
|
return sizeof(e);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -338,7 +338,9 @@ int PanoseDistance(byte *a, byte *b)
|
||||||
|
|
||||||
bool Replace(Font fnt, int chr, Font& rfnt)
|
bool Replace(Font fnt, int chr, Font& rfnt)
|
||||||
{
|
{
|
||||||
|
bool prefer_color = PreferColorEmoji(chr);
|
||||||
static VectorMap<int, sRFace *> rface[2]; // face index to font info
|
static VectorMap<int, sRFace *> rface[2]; // face index to font info
|
||||||
|
static Vector<int> color[2]; // colorimg faces
|
||||||
static bool all_loaded;
|
static bool all_loaded;
|
||||||
if(rface[0].GetCount() == 0) {
|
if(rface[0].GetCount() == 0) {
|
||||||
for(int i = 0; i < __countof(sFontReplacements); i++) {
|
for(int i = 0; i < __countof(sFontReplacements); i++) {
|
||||||
|
|
@ -347,6 +349,9 @@ bool Replace(Font fnt, int chr, Font& rfnt)
|
||||||
rface[0].Add(q) = &sFontReplacements[i];
|
rface[0].Add(q) = &sFontReplacements[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for(int i = 0; i < Font::GetFaceCount(); i++)
|
||||||
|
if(Font::GetFaceInfo(i) & Font::COLORIMG)
|
||||||
|
color[0].Add(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
int face = fnt.GetFace();
|
int face = fnt.GetFace();
|
||||||
|
|
@ -399,6 +404,11 @@ bool Replace(Font fnt, int chr, Font& rfnt)
|
||||||
distance.Add(PanoseDistance(rface[pass][i]->panose, panose));
|
distance.Add(PanoseDistance(rface[pass][i]->panose, panose));
|
||||||
candidate.Add(rface[pass].GetKey(i));
|
candidate.Add(rface[pass].GetKey(i));
|
||||||
}
|
}
|
||||||
|
if(prefer_color)
|
||||||
|
for(int fi : color[pass]) {
|
||||||
|
distance.Add(-1);
|
||||||
|
candidate.Add(fi);
|
||||||
|
}
|
||||||
StableIndexSort(distance, candidate);
|
StableIndexSort(distance, candidate);
|
||||||
for(int fi : candidate) {
|
for(int fi : candidate) {
|
||||||
f.Face(fi);
|
f.Face(fi);
|
||||||
|
|
@ -444,6 +454,8 @@ bool Replace(Font fnt, int chr, Font& rfnt)
|
||||||
rface[1].Add(i, &n);
|
rface[1].Add(i, &n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if((Font::GetFaceInfo(i) & Font::COLORIMG) && FindIndex(color[0], i) < 0)
|
||||||
|
color[1].Add(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,9 @@ struct MyApp : TopWindow {
|
||||||
text << " Quick brown fox, 訓民正音 (훈민정음) ";
|
text << " Quick brown fox, 訓民正音 (훈민정음) ";
|
||||||
|
|
||||||
w.DrawRect(GetSize(), White());
|
w.DrawRect(GetSize(), White());
|
||||||
|
|
||||||
|
// w.DrawText(500, 500, "Hello!" + WString(0x1F970, 1).ToString() + " Hello again!");
|
||||||
|
|
||||||
int y = 10;
|
int y = 10;
|
||||||
int x = 10;
|
int x = 10;
|
||||||
for(int i = 0; i < 3/*Font::GetFaceCount()*/; i++)
|
for(int i = 0; i < 3/*Font::GetFaceCount()*/; i++)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue