git-svn-id: svn://ultimatepp.org/upp/trunk@14902 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2020-08-26 15:40:59 +00:00
parent 57b8ac15f4
commit eb20efbc72
8 changed files with 30870 additions and 671 deletions

View file

@ -1,108 +0,0 @@
#include <Core/Core.h>
#include <Draw/Draw.h>
using namespace Upp;
#define VAL(x) (String() << "TEST(" << #x << ", \"" << (x) << "\");")
#define TEST0(x) LOG(VAL(x))
#define TEST(x, y) LOG(VAL(x)); ASSERT(AsString(x) == y);
CONSOLE_APP_MAIN
{
StdLogSetup(LOG_COUT|LOG_FILE);
#ifdef CPU_SIMD
RGBA x = Color(11, 22, 33);
RGBA *s = &x;
TEST(LoadRGBAF(&x), "255 11 22 33");
TEST(i16x8(*(dword *)s), "0 0 0 0 0 0 0 5665");
TEST(Unpack8L(i16x8(*(dword *)s)), "0 0 0 0 0 0 22 33");
TEST(Unpack8L(i16x8(*(dword *)s)), "0 0 0 0 0 0 22 33");
{
f32x4 x(1, 2, 3, 4);
f32x4 y(1, 3, 2, 4);
DLOG("----------------");
TEST0(x);
TEST0(Broadcast0(x));
TEST0(Broadcast1(x));
TEST0(Broadcast2(x));
TEST0(Broadcast3(x));
TEST0(min(x, y));
TEST0(max(x, y));
TEST0(x == y);
TEST0(x != y);
TEST0(x < y);
TEST0(x <= y);
TEST0(x > y);
TEST0(x >= y);
TEST0(AllTrue(x == y));
TEST0(AllTrue(x == x));
TEST0(x + y);
TEST0(x - y);
TEST0(x / y);
TEST0(x * y);
}
{
i16x8 x(1, 2, 3, 4, 5, 6, 7, 8);
i16x8 y(1, 4, 2, 3, 8, 7, 5, 6);
DLOG("----------------");
TEST0(BroadcastLH0(x));
TEST0(BroadcastLH1(x));
TEST0(BroadcastLH2(x));
TEST0(BroadcastLH3(x));
TEST0(x == y);
TEST0(x < y);
TEST0(x > y);
TEST0(AllTrue(x == y));
TEST0(AllTrue(x == x));
TEST0(x + y);
TEST0(x - y);
TEST0(x * y);
}
{
i8x16 x(1,2,3,4, 11,12,13,14, 21,22,23,24, 31,32,33,34);
DLOG("----------------");
TEST0(x);
TEST0(Unpack8L(x));
TEST0(Unpack8H(x));
}
{
i16x8 x(1,2,3,4, 11,12,13,14);
DLOG("----------------");
TEST0(Unpack16L(x));
TEST0(Unpack16H(x));
}
{
i32x4 x(1, 2, 3, 4);
i32x4 y(1, 4, 2, 3);
DLOG("----------------");
TEST0(ToFloat(x));
TEST0(x == y);
TEST0(x < y);
TEST0(x > y);
TEST0(AllTrue(x == y));
TEST0(AllTrue(x == x));
TEST0(x + y);
TEST0(x - y);
TEST0(x * y);
}
{
f32x4 x(1.1, 2.8, 3.7, -4.2);
DLOG("----------------");
TEST0(x);
TEST0(Truncate(x));
TEST0(Round(x));
}
LOG("================ OK");
#else
LOG("================ NO SIMD");
#endif
}

View file

@ -1,9 +0,0 @@
uses
Core;
file
SIMD.cpp;
mainconfig
"" = "";

View file

@ -1,164 +0,0 @@
* C:\upp\out\upptst\MSBT19.Debug.Debug_Full\SIMD2.exe 27.07.2020 17:35:09, user: cxl
f32x4(r) = 0 0 0 0
x = 4 3 2 1
f32x4(r) = 0 0 0 1
f32x4(r) = 0 0 2 1
f32x4(r) = 4 3 2 1
x = 0 0 0 11
x = 0 0 12 11
f32x4((int)1) = 0 0 0 1
f32x4((float)2) = 0 0 0 2
f32x4((double)3) = 0 0 0 3
f32x4(11, 22, 33, 44) = 11 22 33 44
f32all(3.14159) = 3.14159 3.14159 3.14159 3.14159
a = 1 2 3 4
b = 2 2 2 2
a + b = 3 4 5 6
a - b = -1 0 1 2
a * b = 2 4 6 8
a / b = 0.5 1 1.5 2
min(a, b) = 1 2 2 2
max(a, b) = 2 2 3 4
Broadcast0(a) = 4 4 4 4
Broadcast1(a) = 3 3 3 3
Broadcast2(a) = 2 2 2 2
Broadcast3(a) = 1 1 1 1
(a == a) = -nan -nan -nan -nan
(a != a) = 0 0 0 0
(a == b) = 0 -nan 0 0
(a != b) = -nan 0 -nan -nan
(a < b) = -nan 0 0 0
(b < a) = 0 0 -nan -nan
(a > b) = 0 0 -nan -nan
(b > a) = -nan 0 0 0
AllTrue(a == a) = true
AllTrue(a != a) = false
AllTrue(a == b) = false
AllTrue(a != b) = false
AllTrue(a < b) = true
AllTrue(b < a) = false
AllTrue(a > b) = false
AllTrue(b > a) = true
==================================
x = 0 0 0 0 0 0 2 1
x = 0 0 0 0 4 3 2 1
x = 8 7 6 5 4 3 2 1
i16x8(r) = 0 0 0 0 0 0 2 1
i16x8(r) = 0 0 0 0 4 3 2 1
i16x8(r) = 8 7 6 5 4 3 2 1
i16x8(13) = 0 0 0 0 0 0 0 13
i16all(13) = 13 13 13 13 13 13 13 13
a = 1 2 3 4 5 6 7 8
b = 2 2 2 2 2 2 2 2
a + b = 3 4 5 6 7 8 9 10
a - b = -1 0 1 2 3 4 5 6
a * b = 2 4 6 8 10 12 14 16
a & b = 0 2 2 0 0 2 2 0
a | b = 3 2 3 6 7 6 7 10
a ^ b = 3 0 1 6 7 4 5 10
~a = -2 -3 -4 -5 -6 -7 -8 -9
a << 1 = 2 4 6 8 10 12 14 16
a >> 1 = 0 1 1 2 2 3 3 4
(a == a) = -1 -1 -1 -1 -1 -1 -1 -1
(a == b) = 0 -1 0 0 0 0 0 0
(a < b) = -1 0 0 0 0 0 0 0
(b < a) = 0 0 -1 -1 -1 -1 -1 -1
(a > b) = 0 0 -1 -1 -1 -1 -1 -1
(b > a) = -1 0 0 0 0 0 0 0
AllTrue(a == a) = true
AllTrue(a == b) = false
AllTrue(a < b) = true
AllTrue(b < a) = false
AllTrue(a > b) = false
AllTrue(b > a) = true
==========================================================
x = 0 0 0 1
x = 0 0 2 1
x = 4 3 2 1
i32x4(r) = 0 0 0 1
i32x4(r) = 0 0 2 1
i32x4(r) = 4 3 2 1
i32x4(13) = 0 0 0 13
i32all(13) = 13 13 13 13
a = 1 2 3 4
b = 2 2 2 2
a + b = 3 4 5 6
a - b = -1 0 1 2
a & b = 0 2 2 0
a | b = 3 2 3 6
a ^ b = 3 0 1 6
~a = -2 -3 -4 -5
a << 1 = 2 4 6 8
a >> 1 = 0 1 1 2
(a == a) = -1 -1 -1 -1
(a == b) = 0 -1 0 0
(a < b) = -1 0 0 0
(b < a) = 0 0 -1 -1
(a > b) = 0 0 -1 -1
(b > a) = -1 0 0 0
AllTrue(a == a) = true
AllTrue(a == b) = false
AllTrue(a < b) = true
AllTrue(b < a) = false
AllTrue(a > b) = false
AllTrue(b > a) = true
==========================================================
x = 0 0 0 0 . 0 0 0 0 . 0 0 0 0 . 4 3 2 1
x = 0 0 0 0 . 0 0 0 0 . 8 7 6 5 . 4 3 2 1
x = 16 15 14 13 . 12 11 10 9 . 8 7 6 5 . 4 3 2 1
i8x16(r) = 0 0 0 0 . 0 0 0 0 . 0 0 0 0 . 4 3 2 1
i8x16(r) = 0 0 0 0 . 0 0 0 0 . 8 7 6 5 . 4 3 2 1
i8x16(r) = 16 15 14 13 . 12 11 10 9 . 8 7 6 5 . 4 3 2 1
i8x16(13) = 0 0 0 0 . 0 0 0 0 . 0 0 0 0 . 0 0 0 13
i8all(13) = 13 13 13 13 . 13 13 13 13 . 13 13 13 13 . 13 13 13 13
a = 1 2 3 4 . 5 6 7 8 . 9 10 11 12 . 13 14 15 16
b = 2 2 2 2 . 2 2 2 2 . 2 2 2 2 . 2 2 2 2
a + b = 3 4 5 6 . 7 8 9 10 . 11 12 13 14 . 15 16 17 18
a - b = -1 0 1 2 . 3 4 5 6 . 7 8 9 10 . 11 12 13 14
a & b = 0 2 2 0 . 0 2 2 0 . 0 2 2 0 . 0 2 2 0
a | b = 3 2 3 6 . 7 6 7 10 . 11 10 11 14 . 15 14 15 18
a ^ b = 3 0 1 6 . 7 4 5 10 . 11 8 9 14 . 15 12 13 18
~a = -2 -3 -4 -5 . -6 -7 -8 -9 . -10 -11 -12 -13 . -14 -15 -16 -17
=========================
Unpack8L(a) = 9 10 11 12 13 14 15 16
Unpack8H(a) = 1 2 3 4 5 6 7 8
Unpack16L(h) = 5 6 7 8
Unpack16H(h) = 1 2 3 4
Pack16(Unpack8L(a), Unpack8H(a)) = 1 2 3 4 . 5 6 7 8 . 9 10 11 12 . 13 14 15 16
Pack32(Unpack16L(h)) = 0 0 0 0 5 6 7 8
=========================
a = 1 2 3 4 5 6 7 8
BroadcastLH0(a) = 4 4 4 4 8 8 8 8
BroadcastLH1(a) = 3 3 3 3 7 7 7 7
BroadcastLH2(a) = 2 2 2 2 6 6 6 6
BroadcastLH3(a) = 1 1 1 1 5 5 5 5
Hex((byte *)&i64, 16) = ef cd ab 89 67 45 23 01 ef cd ab 89 67 45 23 01
=========================
f32x4(q) = 0 0 0 4
f32x4(q) = 0 0 3 4
f32x4(q) = 1 2 3 4
x = 0 0 0 4
x = 0 0 3 4
x = 1 2 3 4
=========================
i16x8(q) = 0 0 0 0 0 0 7 8
i16x8(q) = 0 0 0 0 5 6 7 8
i16x8(q) = 1 2 3 4 5 6 7 8
x = 0 0 0 0 0 0 7 8
x = 0 0 0 0 5 6 7 8
x = 1 2 3 4 5 6 7 8
=========================
i32x4(q) = 0 0 0 4
i32x4(q) = 0 0 3 4
i32x4(q) = 1 2 3 4
x = 0 0 0 4
x = 0 0 3 4
x = 1 2 3 4
=========================
i8x16(q) = 0 0 0 0 . 0 0 0 0 . 0 0 0 0 . 13 14 15 16
i8x16(q) = 0 0 0 0 . 0 0 0 0 . 9 10 11 12 . 13 14 15 16
i8x16(q) = 1 2 3 4 . 5 6 7 8 . 9 10 11 12 . 13 14 15 16
x = 0 0 0 0 . 0 0 0 0 . 0 0 0 0 . 13 14 15 16
x = 0 0 0 0 . 0 0 0 0 . 9 10 11 12 . 13 14 15 16
x = 1 2 3 4 . 5 6 7 8 . 9 10 11 12 . 13 14 15 16

View file

@ -1,380 +0,0 @@
#include <Core/Core.h>
using namespace Upp;
String Hex(const void *ptr, int count)
{
String r;
const byte *p = (const byte *)ptr;
while(count--)
MergeWith(r, " ", FormatIntHex(*p++, 2));
return r;
}
CONSOLE_APP_MAIN
{
StdLogSetup(LOG_FILE|LOG_COUT);
{
float r[4] = { 0 };
DUMP(f32x4(r));
f32x4 x;
float y[] = { 1, 2, 3, 4 };
x.Load(y);
DUMP(x);
x.Store32(r);
DUMP(f32x4(r));
x.Store64(r);
DUMP(f32x4(r));
x.Store(r);
DUMP(f32x4(r));
float yy[] = { 11, 12 };
x.Load32(yy);
DUMP(x);
x.Load64(yy);
DUMP(x);
DUMP(f32x4((int)1));
DUMP(f32x4((float)2));
DUMP(f32x4((double)3));
DUMP(f32x4(11, 22, 33, 44));
DUMP(f32all(3.14159));
f32x4 a(1, 2, 3, 4);
f32x4 b(2, 2, 2, 2);
DUMP(a);
DUMP(b);
DUMP(a + b);
DUMP(a - b);
DUMP(a * b);
DUMP(a / b);
DUMP(min(a, b));
DUMP(max(a, b));
DUMP(Broadcast0(a));
DUMP(Broadcast1(a));
DUMP(Broadcast2(a));
DUMP(Broadcast3(a));
DUMP((a == a));
DUMP((a != a));
DUMP((a == b));
DUMP((a != b));
DUMP((a < b));
DUMP((b < a));
DUMP((a > b));
DUMP((b > a));
DUMP(AllTrue(a == a));
DUMP(AllTrue(a != a));
DUMP(AllTrue(a == b));
DUMP(AllTrue(a != b));
b = f32all(5);
DUMP(AllTrue(a < b));
DUMP(AllTrue(b < a));
DUMP(AllTrue(a > b));
DUMP(AllTrue(b > a));
LOG("==================================");
}
{
int16 y[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
i16x8 x;
x.Load32(y);
DUMP(x);
x.Load64(y);
DUMP(x);
x.Load(y);
DUMP(x);
int16 r[8] = { 0 };
x.Store32(r);
DUMP(i16x8(r));
x.Store64(r);
DUMP(i16x8(r));
x.Store(r);
DUMP(i16x8(r));
DUMP(i16x8(13));
DUMP(i16all(13));
i16x8 a(1, 2, 3, 4, 5, 6, 7, 8);
i16x8 b(2, 2, 2, 2, 2, 2, 2, 2);
DUMP(a);
DUMP(b);
DUMP(a + b);
DUMP(a - b);
DUMP(a * b);
DUMP(a & b);
DUMP(a | b);
DUMP(a ^ b);
DUMP(~a);
DUMP(a << 1);
DUMP(a >> 1);
DUMP((a == a));
DUMP((a == b));
DUMP((a < b));
DUMP((b < a));
DUMP((a > b));
DUMP((b > a));
DUMP(AllTrue(a == a));
DUMP(AllTrue(a == b));
b = i16all(10);
DUMP(AllTrue(a < b));
DUMP(AllTrue(b < a));
DUMP(AllTrue(a > b));
DUMP(AllTrue(b > a));
}
{
LOG("==========================================================");
int y[] = { 1, 2, 3, 4 };
i32x4 x;
x.Load32(y);
DUMP(x);
x.Load64(y);
DUMP(x);
x.Load(y);
DUMP(x);
int16 r[8] = { 0 };
x.Store32(r);
DUMP(i32x4(r));
x.Store64(r);
DUMP(i32x4(r));
x.Store(r);
DUMP(i32x4(r));
DUMP(i32x4(13));
DUMP(i32all(13));
i32x4 a(1, 2, 3, 4);
i32x4 b(2, 2, 2, 2);
DUMP(a);
DUMP(b);
DUMP(a + b);
DUMP(a - b);
DUMP(a & b);
DUMP(a | b);
DUMP(a ^ b);
DUMP(~a);
DUMP(a << 1);
DUMP(a >> 1);
DUMP((a == a));
DUMP((a == b));
DUMP((a < b));
DUMP((b < a));
DUMP((a > b));
DUMP((b > a));
DUMP(AllTrue(a == a));
DUMP(AllTrue(a == b));
b = i32all(10);
DUMP(AllTrue(a < b));
DUMP(AllTrue(b < a));
DUMP(AllTrue(a > b));
DUMP(AllTrue(b > a));
}
{
LOG("==========================================================");
int8 y[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
i8x16 x;
x.Load32(y);
DUMP(x);
x.Load64(y);
DUMP(x);
x.Load(y);
DUMP(x);
int16 r[8] = { 0 };
x.Store32(r);
DUMP(i8x16(r));
x.Store64(r);
DUMP(i8x16(r));
x.Store(r);
DUMP(i8x16(r));
DUMP(i8x16(13));
DUMP(i8all(13));
i8x16 a(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
i8x16 b(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2);
DUMP(a);
DUMP(b);
DUMP(a + b);
DUMP(a - b);
DUMP(a & b);
DUMP(a | b);
DUMP(a ^ b);
DUMP(~a);
}
{
LOG("=========================");
i8x16 a(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
DUMP(Unpack8L(a));
DUMP(Unpack8H(a));
i16x8 h = Unpack8H(a);
DUMP(Unpack16L(h));
DUMP(Unpack16H(h));
DUMP(Pack16(Unpack8L(a), Unpack8H(a)));
DUMP(Pack32(Unpack16L(h)));
}
{
LOG("=========================");
i16x8 a(1, 2, 3, 4, 5, 6, 7, 8);
DUMP(a);
DUMP(BroadcastLH0(a));
DUMP(BroadcastLH1(a));
DUMP(BroadcastLH2(a));
DUMP(BroadcastLH3(a));
auto i64 = i64all(I64(0x123456789abcdef));
DUMP(Hex((byte *)&i64, 16));
}
{
LOG("=========================");
f32x4 x(1, 2, 3, 4);
float rr[5] = { 0 };
float *q = (float *)((byte *)rr + 1);
x.Store32(q);
DDUMP(f32x4(q));
x.Store64(q);
DDUMP(f32x4(q));
x.Store(q);
DDUMP(f32x4(q));
x.Load32(q);
DDUMP(x);
x.Load64(q);
DDUMP(x);
x.Load(q);
DDUMP(x);
}
{
LOG("=========================");
i16x8 x(1, 2, 3, 4, 5, 6, 7, 8);
int16 rr[20] = { 0 };
int16 *q = (int16 *)((byte *)rr + 1);
x.Store32(q);
DDUMP(i16x8(q));
x.Store64(q);
DDUMP(i16x8(q));
x.Store(q);
DDUMP(i16x8(q));
x.Load32(q);
DDUMP(x);
x.Load64(q);
DDUMP(x);
x.Load(q);
DDUMP(x);
}
{
LOG("=========================");
i32x4 x(1, 2, 3, 4);
float rr[5] = { 0 };
float *q = (float *)((byte *)rr + 1);
x.Store32(q);
DDUMP(i32x4(q));
x.Store64(q);
DDUMP(i32x4(q));
x.Store(q);
DDUMP(i32x4(q));
x.Load32(q);
DDUMP(x);
x.Load64(q);
DDUMP(x);
x.Load(q);
DDUMP(x);
}
{
LOG("=========================");
i8x16 x(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
int16 rr[20] = { 0 };
int16 *q = (int16 *)((byte *)rr + 1);
x.Store32(q);
DDUMP(i8x16(q));
x.Store64(q);
DDUMP(i8x16(q));
x.Store(q);
DDUMP(i8x16(q));
x.Load32(q);
DDUMP(x);
x.Load64(q);
DDUMP(x);
x.Load(q);
DDUMP(x);
}
auto LoadLog = [](const String& path) {
String s = Filter(LoadFile(path), [](int c) { return c == '\r' ? 0 : c; });
return s.Mid(max(s.FindAfter("\n"), 0));
};
String log = LoadLog(GetStdLogPath());
String etalon = LoadLog(GetDataFile("Etalon.log"));
SaveFile(GetHomeDirFile("log.txt"), log);
SaveFile(GetHomeDirFile("etalon.txt"), etalon);
ASSERT(log == etalon);
Cout() << "================= OK\r\n";
}

View file

@ -1,10 +0,0 @@
uses
Core;
file
Etalon.log,
SIMD2.cpp;
mainconfig
"" = "";

View file

@ -0,0 +1,10 @@
uses
CtrlLib;
file
UnicodeData.txt,
main.cpp;
mainconfig
"" = "GUI";

30592
upptst/Unicode/UnicodeData.txt Normal file

File diff suppressed because it is too large Load diff

268
upptst/Unicode/main.cpp Normal file
View file

@ -0,0 +1,268 @@
#include <CtrlLib/CtrlLib.h>
using namespace Upp;
namespace Upp {
HFONT GetWin32Font(Font fnt, int angle);
};
int GlyphIndex(HDC hdc, int ch)
{
WString h = ToUtf16(ch);
GCP_RESULTSW gcp_results = { sizeof(GCP_RESULTS) };
gcp_results.nGlyphs = 4;
wchar gi[4];
gcp_results.lpGlyphs = gi;
// RTIMING("GetCharacterPlacement");
GetCharacterPlacementW(hdc, ~h, h.GetCount(), 0, &gcp_results, GCP_GLYPHSHAPE);
return (word)gi[0];
}
int GlyphIndex(int ch, Font fnt)
{
RTIMING("GlyphIndex");
int r = -1;
HFONT hfont = GetWin32Font(fnt, 0);
VERIFY(hfont);
if(hfont) {
static HDC hdc = CreateIC("DISPLAY", NULL, NULL, NULL);
HFONT ohfont;
{
RTIMING("Select");
ohfont = (HFONT) ::SelectObject(hdc, hfont);
}
r = GlyphIndex(hdc, ch);
// ::SelectObject(hdc, ohfont);
// ::DeleteDC(hdc);
}
return r;
}
bool HasCodepoint(int ch, Font fnt)
{
static Vector<int> tofu;
int& q = tofu.At(fnt.GetFace(), Null);
if(IsNull(q))
q = GlyphIndex(1, fnt);
return ch == ' ' || GlyphIndex(ch, fnt) != q;
}
int GetAdvanceWidth(int ch, Font fnt)
{
TIMING("Glyph");
HFONT hfont = GetWin32Font(fnt, 0);
VERIFY(hfont);
int r = -1;
if(hfont) {
HDC hdc = CreateIC("DISPLAY", NULL, NULL, NULL);
HFONT ohfont = (HFONT) ::SelectObject(hdc, hfont);
GLYPHMETRICS gm;
memset(&gm, 0, sizeof(gm));
MAT2 m_matrix;
memset8(&m_matrix, 0, sizeof(m_matrix));
m_matrix.eM11.value = 1;
m_matrix.eM22.value = 1;
ch = GlyphIndex(hdc, ch);
int gsz = GetGlyphOutlineW(hdc, ch, GGO_NATIVE|GGO_METRICS|GGO_GLYPH_INDEX, &gm, 0, NULL, &m_matrix);
if(gsz != GDI_ERROR && gm.gmCellIncX != 75)
r = gm.gmCellIncX;
::SelectObject(hdc, ohfont);
::DeleteDC(hdc);
}
return r;
}
double fx_to_dbl(const FIXED& p) {
return double(p.value) + double(p.fract) * (1.0 / 65536.0);
}
Pointf fx_to_dbl(const Pointf& pp, const POINTFX& p) {
return Pointf(pp.x + fx_to_dbl(p.x), pp.y - fx_to_dbl(p.y));
}
void RenderCharPath2(const char* gbuf, unsigned total_size, FontGlyphConsumer& sw, double xx, double yy)
{
const char* cur_glyph = gbuf;
const char* end_glyph = gbuf + total_size;
Pointf pp(xx, yy);
while(cur_glyph < end_glyph) {
const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
const char* end_poly = cur_glyph + th->cb;
const char* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
sw.Move(fx_to_dbl(pp, th->pfxStart));
while(cur_poly < end_poly) {
const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
if (pc->wType == TT_PRIM_LINE)
for(int i = 0; i < pc->cpfx; i++)
sw.Line(fx_to_dbl(pp, pc->apfx[i]));
if (pc->wType == TT_PRIM_QSPLINE)
for(int u = 0; u < pc->cpfx - 1; u++) {
Pointf b = fx_to_dbl(pp, pc->apfx[u]);
Pointf c = fx_to_dbl(pp, pc->apfx[u + 1]);
if (u < pc->cpfx - 2)
c = Mid(b, c);
sw.Quadratic(b, c);
}
cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx;
}
sw.Close();
cur_glyph += th->cb;
}
}
void RenderGlyph2(FontGlyphConsumer& sw, double x, double y, int ch, Font fnt)
{
HFONT hfont = GetWin32Font(fnt, 0);
VERIFY(hfont);
if(hfont) {
HDC hdc = CreateIC("DISPLAY", NULL, NULL, NULL);
HFONT ohfont = (HFONT) ::SelectObject(hdc, hfont);
GLYPHMETRICS gm;
MAT2 m_matrix;
memset8(&m_matrix, 0, sizeof(m_matrix));
m_matrix.eM11.value = 1;
m_matrix.eM22.value = 1;
ch = GlyphIndex(hdc, ch);
int gsz = GetGlyphOutlineW(hdc, ch, GGO_NATIVE|GGO_UNHINTED|GGO_GLYPH_INDEX, &gm, 0, NULL, &m_matrix);
if(gsz >= 0) {
StringBuffer gb(gsz);
gsz = GetGlyphOutlineW(hdc, ch, GGO_NATIVE|GGO_UNHINTED|GGO_GLYPH_INDEX, &gm, gsz, ~gb, &m_matrix);
if(gsz >= 0)
RenderCharPath2(~gb, gsz, sw, x, y + fnt.GetAscent());
}
::SelectObject(hdc, ohfont);
::DeleteDC(hdc);
}
}
struct MyApp : TopWindow {
SplitterFrame sf;
StaticRect pane;
DropList face;
ArrayCtrl list;
EditString code;
virtual void Paint(Draw& w) {
Font font = Font(~face, 100); // Font().Height(100).FaceName("MingLiU-ExtB");
// Font font = Font().Height(100).FaceName("MingLiU-ExtB");
w.DrawRect(GetSize(), White());
int x = 0;
int y = 40;
int ch = ScanInt(~~code, NULL, 16);
if(SystemDraw *sw = dynamic_cast<SystemDraw *>(&w)) {
WString h = ToUtf16(ch);
String f;
for(wchar ch : h)
f << Format("%x ", ch);
// Get glyph indices for the string
DDUMP(ch);
int cx = GetAdvanceWidth(ch, font);
w.DrawRect(100, 200, cx, 20, WhiteGray());
HFONT hfont = GetWin32Font(font, 0);
DDUMP(hfont);
HDC hdc = sw->BeginGdi();
DDUMP(hdc);
HGDIOBJ orgfont = ::SelectObject(hdc, hfont);
DDUMP(GetLastErrorMessage());
DDUMP(h.GetCount());
::SetTextColor(hdc, sw->GetColor(Black()));
::ExtTextOutW(hdc, 100, 200, 0, NULL, ~h, 2, NULL);
DDUMP(GetLastErrorMessage());
GCP_RESULTSW gcp_results = { sizeof(GCP_RESULTS) };
gcp_results.nGlyphs = 2;
wchar gi[4];
gcp_results.lpGlyphs = gi;
GetCharacterPlacementW(hdc, ~h, h.GetCount(), 0, &gcp_results, GCP_GLYPHSHAPE);
f << ", glyph: " << (int)gi[0];
if(HasCodepoint(ch, font))
f << " EXISTS";
::SelectObject(hdc, orgfont);
DDUMP(GetLastErrorMessage());
sw->EndGdi();
DDUMP(GetLastErrorMessage());
w.DrawText(20, 300, f);
}
struct PaintCharPath : FontGlyphConsumer {
Painter *sw;
virtual void Move(Pointf p) {
sw->Move(p);
}
virtual void Line(Pointf p) {
sw->Line(p);
}
virtual void Quadratic(Pointf p1, Pointf p2) {
sw->Quadratic(p1, p2);
}
virtual void Cubic(Pointf p1, Pointf p2, Pointf p3) {
sw->Cubic(p1, p2, p3);
}
virtual void Close() {
sw->Close();
}
};
ImagePainter ip(200, 200);
ip.Clear(Yellow());
PaintCharPath h;
h.sw = &ip;
RenderGlyph2(h, 0, 0, ch, font);
ip.Fill(Black());
w.DrawImage(100, 400, ip);
}
MyApp() {
pane.Add(face.TopPosZ(0, 20).HSizePos());
pane.Add(code.TopPosZ(20, 20).HSizePos());
pane.Add(list.HSizePos().VSizePosZ(40, 0));
AddFrame(sf.Left(pane, Zx(250)));
list.AddColumn("List");
FileIn in(GetDataFile("UnicodeData.txt"));
while(!in.IsEof())
list.Add(in.GetLine());
AddFrame(InsetFrame());
sf.SizeMin(40).MinSize(40);
Sizeable();
int q = -1;
for(int i = 1; i < Font::GetFaceCount(); i++) {
if(Font::GetFaceInfo(i) & Font::SCALEABLE) {
String n = Font::GetFaceName(i);
DDUMP(n.StartsWith("MingLiU"));
if(n.StartsWith("MingLiU"))
q = i;
face.Add(i, n);
}
}
if(q >= 0)
face <<= q;
list.WhenSel = [=] { code <<= Format("%x", ScanInt(~list.GetKey(), NULL, 16)); Refresh(); };
code << [=] { Refresh(); };
face << [=] {
DLOG("================");
for(int i = 0; i < 0x2ffff; i++) {
Font font = Font(~face, 100);
if(HasCodepoint(i, font))
DDUMPHEX(i);
}
};
code <<= "20010";
}
};
GUI_APP_MAIN
{
MyApp().Run();
}