mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 14:16:09 -06:00
238 lines
5.8 KiB
C++
238 lines
5.8 KiB
C++
#include "FontDB.h"
|
|
|
|
Image LetterImg(char c, Font fnt)
|
|
{
|
|
ImagePainter iw(128, 128);
|
|
iw.DrawRect(0, 0, 128, 128, White());
|
|
iw.DrawText(0, 0, &c, fnt, Black(), 1);
|
|
return iw;
|
|
}
|
|
|
|
String FormatBin(dword w)
|
|
{
|
|
String s;
|
|
for(int i = 0; i < 32; i++)
|
|
s << (((1 << i) & w) ? "1" : "0");
|
|
return s;
|
|
}
|
|
|
|
dword ClassifyFontFace(int face)
|
|
{
|
|
Font fnt(face, 100);
|
|
Image I = LetterImg('I', fnt);
|
|
Image V = LetterImg('V', fnt);
|
|
int density = 0;
|
|
int complexity = 0;
|
|
byte cc = 0;
|
|
for(const RGBA *s = I; s < ~I + I.GetLength(); s++) {
|
|
if(s->r == 0)
|
|
density++;
|
|
if(s->r != cc) {
|
|
cc = s->r;
|
|
complexity++;
|
|
}
|
|
}
|
|
for(const RGBA *s = V; s < ~V + V.GetLength(); s++) {
|
|
if(s->r != cc) {
|
|
cc = s->r;
|
|
complexity++;
|
|
}
|
|
}
|
|
int thickness = 0;
|
|
for(const RGBA *s = V[45]; s < V[45] + 100; s++) {
|
|
if(s->r == 0)
|
|
thickness++;
|
|
}
|
|
int ithickness = 0;
|
|
for(const RGBA *s = I[45]; s < I[45] + 100; s++) {
|
|
if(s->r == 0)
|
|
ithickness++;
|
|
}
|
|
int vserif = 0;
|
|
int iserif = 0;
|
|
for(int i = 0; i < 100; i++) {
|
|
int v = 0;
|
|
int w = 0;
|
|
for(const RGBA *s = V[i]; s < V[i] + 100; s++) {
|
|
if(s->r == 0)
|
|
v++;
|
|
}
|
|
for(const RGBA *s = I[i]; s < I[i] + 100; s++) {
|
|
if(s->r == 0)
|
|
w++;
|
|
}
|
|
vserif = max(vserif, v);
|
|
iserif = max(iserif, w);
|
|
}
|
|
dword lower = 0;
|
|
dword all = 0;
|
|
vserif -= thickness;
|
|
iserif -= ithickness;
|
|
vserif = 15 * minmax(vserif, 0, 40) / 40;
|
|
iserif = 15 * minmax(iserif, 0, 20) / 20;
|
|
density = 15 * minmax(density, 0, 2000) / 2000;
|
|
thickness = 15 * minmax(thickness - ithickness, 0, 20) / 20;
|
|
ithickness = 15 * minmax(ithickness, 0, 60) / 60;
|
|
complexity = 15 * minmax(complexity - 600, 0, 600) / 600;
|
|
int vw = 15 * minmax(fnt['V'], 0, 100) / 100;
|
|
return vserif | (iserif << 4) | (density << 8) | (thickness << 12) | (ithickness << 16) |
|
|
(complexity << 20) | (vw << 24);
|
|
}
|
|
|
|
int FontClassDistance(dword a, dword b)
|
|
{
|
|
int d = 0;
|
|
for(int i = 0; i < 8; i++) {
|
|
int q = int(a & 15) - int(b & 15);
|
|
d = d + q * q;
|
|
a >>= 4;
|
|
b >>= 4;
|
|
}
|
|
d++;
|
|
return d;
|
|
}
|
|
|
|
Vector<dword> fclass;
|
|
|
|
void FontDB::Perform()
|
|
{
|
|
Progress pi("Scanning fonts");
|
|
OpenMain();
|
|
pi.SetTotal(Font::GetFaceCount());
|
|
for(int face = 0; face < Font::GetFaceCount(); face++) {
|
|
fclass.Add(ClassifyFontFace(face));
|
|
}
|
|
for(int face = 0; face < Font::GetFaceCount(); face++) {
|
|
if(pi.StepCanceled())
|
|
return;
|
|
Font fnt(face, 100);
|
|
if(fnt.IsScaleable() && fnt.IsUnicode()) {
|
|
pi.SetText(fnt.GetFaceName());
|
|
Image I = LetterImg('I', fnt);
|
|
Image V = LetterImg('V', fnt);
|
|
int density = 0;
|
|
int complexity = 0;
|
|
byte cc = 0;
|
|
for(const RGBA *s = I; s < ~I + I.GetLength(); s++) {
|
|
if(s->r == 0)
|
|
density++;
|
|
if(s->r != cc) {
|
|
cc = s->r;
|
|
complexity++;
|
|
}
|
|
}
|
|
for(const RGBA *s = V; s < ~V + V.GetLength(); s++) {
|
|
if(s->r != cc) {
|
|
cc = s->r;
|
|
complexity++;
|
|
}
|
|
}
|
|
int thickness = 0;
|
|
for(const RGBA *s = V[45]; s < V[45] + 100; s++) {
|
|
if(s->r == 0)
|
|
thickness++;
|
|
}
|
|
int ithickness = 0;
|
|
for(const RGBA *s = I[45]; s < I[45] + 100; s++) {
|
|
if(s->r == 0)
|
|
ithickness++;
|
|
}
|
|
int vserif = 0;
|
|
int iserif = 0;
|
|
for(int i = 0; i < 100; i++) {
|
|
int v = 0;
|
|
int w = 0;
|
|
for(const RGBA *s = V[i]; s < V[i] + 100; s++) {
|
|
if(s->r == 0)
|
|
v++;
|
|
}
|
|
for(const RGBA *s = I[i]; s < I[i] + 100; s++) {
|
|
if(s->r == 0)
|
|
w++;
|
|
}
|
|
vserif = max(vserif, v);
|
|
iserif = max(iserif, w);
|
|
}
|
|
dword lower = 0;
|
|
dword all = 0;
|
|
#if 0
|
|
Progress pi(fnt.GetFaceName() << " glyphs");
|
|
pi.SetTotal(65536);
|
|
for(int i = 0; i < 65536;) {
|
|
if(pi.SetPosCanceled(i)) {
|
|
Execute();
|
|
return;
|
|
}
|
|
if(fnt.IsNormal(i)) {
|
|
if(i < 8192)
|
|
lower |= 1 << (i / 256);
|
|
all |= 1 << (i / 2048);
|
|
i = (i + 256) & 0xffff00;
|
|
}
|
|
else
|
|
i++;
|
|
}
|
|
#endif
|
|
vserif -= thickness;
|
|
iserif -= ithickness;
|
|
vserif = 15 * minmax(vserif, 0, 40) / 40;
|
|
iserif = 15 * minmax(iserif, 0, 20) / 20;
|
|
density = 15 * minmax(density, 0, 2000) / 2000;
|
|
thickness = 15 * minmax(thickness - ithickness, 0, 20) / 20;
|
|
ithickness = 15 * minmax(ithickness, 0, 60) / 60;
|
|
complexity = 15 * minmax(complexity - 600, 0, 600) / 600;
|
|
int vw = 15 * minmax(fnt['V'], 0, 100) / 100;
|
|
int qc = ClassifyFontFace(face);
|
|
int q = 0;
|
|
int min = INT_MAX;
|
|
for(int i = 0; i < fclass.GetCount(); i++) {
|
|
dword w = Font::GetFaceInfo(i);
|
|
if((w & Font::SCALEABLE) && !(w & Font::LOCAL) && i != face && (w & Font::FIXEDPITCH) == fnt.IsFixedPitch()) {
|
|
int d = FontClassDistance(qc, fclass[i]);
|
|
if(d < min) {
|
|
q = i;
|
|
min = d;
|
|
}
|
|
}
|
|
}
|
|
list.Add(fnt.GetFaceName(), Rescale(I, 40, 40), Rescale(V, 40, 40),
|
|
density, complexity, thickness, ithickness, vserif, iserif, vw,
|
|
FormatIntHex(qc), Font::GetFaceName(q),
|
|
FormatBin(lower), FormatBin(all));
|
|
}
|
|
}
|
|
pi.Close();
|
|
Execute();
|
|
}
|
|
|
|
FontDB::FontDB()
|
|
{
|
|
for(int i = 0; i < Font::GetFaceCount(); i++) {
|
|
DDUMP(Font::GetFaceName(i));
|
|
DDUMP(Font::GetFaceInfo(i) & Font::SCALEABLE);
|
|
DDUMP(Font::GetFaceInfo(i) & Font::LOCAL);
|
|
}
|
|
Add(list.SizePos());
|
|
list.AddColumn("Face");
|
|
list.AddColumn("V").SetDisplay(CenteredImageDisplay());
|
|
list.AddColumn("I").SetDisplay(CenteredImageDisplay());
|
|
list.AddColumn("Density");
|
|
list.AddColumn("Complexity");
|
|
list.AddColumn("VT");
|
|
list.AddColumn("IT");
|
|
list.AddColumn("VS");
|
|
list.AddColumn("IS");
|
|
list.AddColumn("VW");
|
|
list.AddColumn("Number");
|
|
list.AddColumn("Similar");
|
|
// list.AddColumn("Lower");
|
|
// list.AddColumn("Upper");
|
|
list.ColumnWidths("114 57 55 56 35 33 27 30 40 37 111 338");
|
|
list.SetLineCy(40);
|
|
}
|
|
|
|
GUI_APP_MAIN
|
|
{
|
|
FontDB().Perform();
|
|
}
|
|
|