mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-17 14:16:10 -06:00
294 lines
7.2 KiB
Text
294 lines
7.2 KiB
Text
g = Memory at 007A18D8, size 0x45 = 69
|
||
+0 0x007A18D8 0A 0C 15 15 01 80 B8 E5 F9 E7 BD 81 02 D5 45 DA .....€¸åùç½<C3A7>.ÕEÚ
|
||
+16 0x007A18E8 01 A5 41 E6 9B 84 98 E5 41 A9 DA 41 93 03 9C 41 .¥A曄˜åA©ÚA“.œA
|
||
+32 0x007A18F8 DC ED 47 EE FB 47 FD F0 41 8C 06 DE 41 B2 06 AB ÜíGîûGýðAŒ.ÞA².«
|
||
+48 0x007A1908 41 F7 AA 86 92 CD 41 DA 80 DB 45 F7 96 01 81 BB A÷ª†’ÍAÚ€ÛE÷–.<2E>»
|
||
+64 0x007A1918 E4 F9 F1 D3 94 äùñÓ”
|
||
|
||
|
||
g = Memory at 006618D8, size 0x46 = 70
|
||
+0 0x006618D8 0A 0C 15 15 01 80 B8 E5 F9 E7 BD 81 02 D5 45 DA .....€¸åùç½<C3A7>.ÕEÚ
|
||
+16 0x006618E8 01 A5 41 E6 9B 84 98 E5 41 A9 DA 41 93 03 9C 41 .¥A曄˜åA©ÚA“.œA
|
||
+32 0x006618F8 DC ED 47 EE FB 47 FD F0 41 8C 06 DE 41 B2 06 AB ÜíGîûGýðAŒ.ÞA².«
|
||
+48 0x00661908 41 F7 AA 86 92 CD 41 DA 80 DB 45 F7 96 01 81 BB A÷ª†’ÍAÚ€ÛE÷–.<2E>»
|
||
+64 0x00661918 E4 F9 F1 D3 94 01 äùñÓ”.
|
||
|
||
#include <CtrlLib/CtrlLib.h>
|
||
#include <Painter/Painter.h>
|
||
#include "glyph.h"
|
||
|
||
using namespace Upp;
|
||
|
||
#define IMAGECLASS GlyphImg
|
||
#define IMAGEFILE <Glyph/glyph.iml>
|
||
#include <Draw/iml_header.h>
|
||
|
||
#define IMAGECLASS GlyphImg
|
||
#define IMAGEFILE <Glyph/glyph.iml>
|
||
#include <Draw/iml_source.h>
|
||
|
||
bool IsUniform(const RGBA *s, RGBA c, int add, int n)
|
||
{
|
||
while(n-- > 0) {
|
||
if(*s != c)
|
||
return false;
|
||
s += add;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
Image AutoCrop(const Image& m, RGBA c)
|
||
{
|
||
Size isz = m.GetSize();
|
||
Rect r = isz;
|
||
for(r.top = 0; r.top < isz.cy && IsUniform(m[r.top], c, 1, isz.cx); r.top++)
|
||
;
|
||
for(r.bottom = isz.cy - 1; r.bottom >= r.top && IsUniform(m[r.bottom], c, 1, isz.cx); r.bottom--)
|
||
;
|
||
if(r.bottom <= r.top)
|
||
return Null;
|
||
int h = r.GetHeight();
|
||
const RGBA *p = m[r.top];
|
||
for(r.left = 0; r.left < isz.cy && IsUniform(p + r.left, c, isz.cx, h); r.left++)
|
||
;
|
||
for(r.right = isz.cx; r.right >= r.left && IsUniform(p + r.right, c, isz.cx, h); r.right--)
|
||
;
|
||
r.right++;
|
||
r.bottom++;
|
||
return WithHotSpot(Crop(m, r), 20, 20);
|
||
}
|
||
|
||
Image RenderGlyph(Font fnt, int chr)
|
||
{
|
||
int cx = fnt[chr];
|
||
int cy = fnt.GetLineHeight();
|
||
ImageBuffer ib(2 * cx, 2 * cy);
|
||
BufferPainter sw(ib, MODE_ANTIALIASED);
|
||
sw.Clear(RGBAZero());
|
||
sw.DrawText(cx / 2, cy / 2, WString(chr, 1), fnt, Black());
|
||
ib.SetHotSpot(Point(20, 20));
|
||
return ib;
|
||
}
|
||
|
||
String CompressGlyph(const Image& m)
|
||
{
|
||
const RGBA *s = m;
|
||
const RGBA *e = s + m.GetLength();
|
||
StringStream r;
|
||
Size sz = m.GetSize();
|
||
r / sz.cx / sz.cy;
|
||
Point p = m.GetHotSpot();
|
||
r / p.x / p.y;
|
||
while(s < e) {
|
||
const RGBA *b = s;
|
||
if(s->a == 0 || s->a == 255) {
|
||
byte a = s->a;
|
||
s++;
|
||
while(s < e && s - b < 63 && s->a == a)
|
||
s++;
|
||
if(a == 0 && s >= e)
|
||
return r;
|
||
r.Put((a & 0x40) | (s - b));
|
||
}
|
||
else {
|
||
r.Put((s->a >> 1) | 0x80);
|
||
s++;
|
||
}
|
||
}
|
||
return r;
|
||
}
|
||
|
||
Image DecompressGlyph(const String& g, Color c)
|
||
{
|
||
StringStream r(g);
|
||
Size sz;
|
||
r / sz.cx / sz.cy;
|
||
ImageBuffer ib(sz);
|
||
Point p;
|
||
ib.SetHotSpot(p);
|
||
r / p.x / p.y;
|
||
RGBA *t = ib;
|
||
RGBA *te = ib.End();
|
||
RGBA full = c;
|
||
while(!r.IsEof()) {
|
||
byte b = r.Get();
|
||
ASSERT(t < te);
|
||
if(b & 0x80)
|
||
*t++ = (((b & 0x7f) << 1) | ((b & 0x40) >> 6)) * c;
|
||
else {
|
||
int n = b & 63;
|
||
ASSERT(t + n <= te);
|
||
Fill(t, b & 0x40 ? full : RGBAZero(), n);
|
||
t += n;
|
||
}
|
||
}
|
||
Fill(t, RGBAZero(), te - t);
|
||
return ib;
|
||
}
|
||
|
||
struct ColorRenderer : MiniRenderer
|
||
{
|
||
Draw *draw;
|
||
Color color;
|
||
|
||
virtual void PutHorz(int x, int y, int cx) {
|
||
draw->DrawRect(x, y, cx, 1, color);
|
||
}
|
||
virtual void PutVert(int x, int y, int cy) {
|
||
draw->DrawRect(x, y, 1, cy, color);
|
||
}
|
||
};
|
||
|
||
struct MyApp : TopWindow {
|
||
Point p;
|
||
|
||
virtual void Paint(Draw& w);
|
||
virtual void MouseMove(Point p, dword keyflags);
|
||
virtual Image CursorImage(Point p, dword keyflags);
|
||
|
||
};
|
||
|
||
Image MyApp::CursorImage(Point p, dword keyflags)
|
||
{
|
||
return GlyphImg::cursor();
|
||
}
|
||
|
||
void MyApp::MouseMove(Point p_, dword keyflags)
|
||
{
|
||
p = p_;
|
||
Refresh();
|
||
}
|
||
|
||
|
||
void DrawLine(Draw& w, Point p1, Point p2)
|
||
{
|
||
DLOG("----------------");
|
||
int dirx = sgn(p2.x - p1.x);
|
||
int diry = sgn(p2.y - p1.y);
|
||
int dx = abs(p2.x - p1.x);
|
||
int dy = abs(p2.y - p1.y);
|
||
int x = p1.x;
|
||
int y = p1.y;
|
||
int x0 = x;
|
||
int y0 = y;
|
||
if(dx < dy) {
|
||
int dda = dy >> 1;
|
||
int n = dy;
|
||
for(;;) {
|
||
if(x != x0) {
|
||
if(y0 < y)
|
||
w.DrawRect(x0, y0, 1, y - y0, LtBlue());
|
||
else
|
||
w.DrawRect(x0, y + 1, 1, y0 - y, LtBlue());
|
||
x0 = x;
|
||
y0 = y;
|
||
}
|
||
y += diry;
|
||
if(n-- <= 0)
|
||
break;
|
||
dda -= dx;
|
||
if(dda < 0) {
|
||
dda += dy;
|
||
x += dirx;
|
||
}
|
||
}
|
||
if(y0 < y)
|
||
w.DrawRect(x0, y0, 1, y - y0, LtBlue());
|
||
else
|
||
w.DrawRect(x0, y + 1, 1, y0 - y, LtBlue());
|
||
}
|
||
else {
|
||
int dda = dx >> 1;
|
||
int n = dx;
|
||
for(;;) {
|
||
if(y != y0) {
|
||
if(x0 < x)
|
||
w.DrawRect(x0, y0, x - x0, 1, LtBlue());
|
||
else
|
||
w.DrawRect(x + 1, y0, x0 - x, 1, LtBlue());
|
||
x0 = x;
|
||
y0 = y;
|
||
}
|
||
x += dirx;
|
||
if(n-- <= 0)
|
||
break;
|
||
dda -= dy;
|
||
if(dda < 0) {
|
||
dda += dx;
|
||
y += diry;
|
||
}
|
||
}
|
||
if(x0 < x)
|
||
w.DrawRect(x0, y0, x - x0, 1, LtBlue());
|
||
else
|
||
w.DrawRect(x + 1, y0, x0 - x, 1, LtBlue());
|
||
}
|
||
}
|
||
|
||
|
||
void MyApp::Paint(Draw& w)
|
||
{
|
||
w.DrawRect(GetSize(), White());
|
||
// DWORD gdiCount = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS);
|
||
// w.DrawText(400, 0, AsString(gdiCount));
|
||
|
||
w.DrawImage(0, 0, RenderGlyph(Arial(20), 'e'));
|
||
|
||
String g = CompressGlyph(AutoCrop(RenderGlyph(Arial(20), 'e'), RGBAZero()));
|
||
w.DrawImage(20, 0, DecompressGlyph(g, White()));
|
||
w.DrawImage(0, 50, DecompressGlyph(g, Black()));
|
||
|
||
Point p0(300, 300);
|
||
|
||
w.DrawLine(p0, p, 0, LtGray());
|
||
w.DrawRect(p0.x - 1, p0.y - 1, 3, 3, LtGray());
|
||
|
||
ColorRenderer r;
|
||
r.draw = &w;
|
||
r.color = Red();
|
||
r.Line(p0, p);
|
||
|
||
// __BREAK__;
|
||
}
|
||
|
||
GUI_APP_MAIN
|
||
{
|
||
{
|
||
for(int i = 0; i < 10000; i++) {
|
||
RTIMING("RenderGlyph");
|
||
RenderGlyph(Arial(20), 'e');
|
||
}
|
||
String g = CompressGlyph(AutoCrop(RenderGlyph(Arial(20), 'e'), RGBAZero()));
|
||
RDUMPHEX(g);
|
||
for(int i = 0; i < 10000; i++) {
|
||
RTIMING("DecompressGlyph");
|
||
DecompressGlyph(g, White());
|
||
}
|
||
}
|
||
for(const char *s = "compres"; *s; s++)
|
||
for(int n = 10; n <= 100; n += 10) {
|
||
RLOG("-------------");
|
||
RLOG(n << ' ' << *s);
|
||
Size sz = AutoCrop(RenderGlyph(StdFont(n), *s), RGBAZero()).GetSize();
|
||
RDUMP(sz);
|
||
RDUMP(sz.cx * sz.cy);
|
||
RDUMP(CompressGlyph(AutoCrop(RenderGlyph(StdFont(n), *s), RGBAZero())).GetLength());
|
||
}
|
||
MyApp().Run();
|
||
}
|
||
|
||
String txt = LoadFile(GetDataFile("text.qtf"));
|
||
{
|
||
RTIMING("SDraw");
|
||
ParseQTF(txt).Paint(Zoom(2, 10), fw, 0, 0, sz.cx);
|
||
}
|
||
{
|
||
RTIMING("Draw");
|
||
// ParseQTF(txt).Paint(Zoom(2, 10), w, 0, 0, sz.cx);
|
||
}
|
||
|
||
TIMING Painter : 2.11 s - 11.39 ms ( 2.11 s / 185 ), min: 7.00 ms, max: 16.00 ms, nesting: 1 - 185
|
||
TIMING Draw : 117.99 ms - 637.79 us (118.00 ms / 185 ), min: 0.00 ns, max: 7.00 ms, nesting: 1 - 185
|
||
TIMING Render glyph : 5.99 ms - 49.95 us ( 6.00 ms / 120 ), min: 0.00 ns, max: 1.00 ms, nesting: 1 - 120
|
||
TIMING Paint glyph : 944.23 ms - 6.49 us (951.00 ms / 145410 ), min: 0.00 ns, max: 3.00 ms, nesting: 1 - 145410
|
||
TIMING SDraw : 1.10 s - 5.94 ms ( 1.10 s / 185 ), min: 4.00 ms, max: 18.00 ms, nesting: 1 - 185
|