mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 06:05:58 -06:00
437 lines
9.5 KiB
C++
437 lines
9.5 KiB
C++
#include "MDraw.h"
|
|
|
|
#include <emmintrin.h>
|
|
|
|
void DrawR(PixelBlock& w, int x, int y, Color c)
|
|
{}
|
|
|
|
static const byte n_o[] = {
|
|
0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
|
|
0x00, 0xff, 0x00, 0x00, 0xff, 0x00,
|
|
0x00, 0xff, 0x00, 0x00, 0xff, 0x00,
|
|
0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
|
|
0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
|
|
0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
|
|
0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
|
|
0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
|
|
0x00, 0xff, 0x00, 0x00, 0xff, 0x00,
|
|
0x00, 0xff, 0x00, 0x00, 0xff, 0x00,
|
|
0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
|
|
};
|
|
|
|
void DrawO(PixelBlock& w, int x, int y, Color c)
|
|
{
|
|
const byte *s = n_o;
|
|
dword *a = w.PointAdr(x, y);
|
|
int d = w.LineDelta();
|
|
dword ic = c;
|
|
for(int w = 0; w < 11; w++) {
|
|
for(int q = 0; q < 6; q++) {
|
|
if(*s)
|
|
a[q] = ic;
|
|
s++;
|
|
}
|
|
a += d;
|
|
}
|
|
}
|
|
|
|
String of_packed;
|
|
|
|
void DrawOF(PixelBlock& w, int x, int y, Color c)
|
|
{
|
|
dword *a = w.PointAdr(x, y);
|
|
int d = w.LineDelta();
|
|
dword ic = c;
|
|
const byte *s = of_packed;
|
|
dword *t = a;
|
|
for(;;) {
|
|
byte c = *s++;
|
|
if(c == 0)
|
|
break;
|
|
t += (c >> 3) & 15;
|
|
switch(c & 7) {
|
|
case 7:
|
|
t[7] = ic;
|
|
case 6:
|
|
t[6] = ic;
|
|
case 5:
|
|
t[5] = ic;
|
|
case 4:
|
|
t[4] = ic;
|
|
case 3:
|
|
t[3] = ic;
|
|
case 2:
|
|
t[2] = ic;
|
|
case 1:
|
|
t[1] = ic;
|
|
}
|
|
t += c & 7;
|
|
if(c & 0x80) {
|
|
a += d;
|
|
t = a;
|
|
}
|
|
}
|
|
}
|
|
|
|
void PackOF() {
|
|
StringBuffer pk;
|
|
for(int w = 0; w < 11; w++) {
|
|
int n = 0;
|
|
const byte *ln = n_o + w * 6;
|
|
bool wasnot = true;
|
|
for(int q = 0; q < 6; q++)
|
|
if(ln[q]) {
|
|
int m = 0;
|
|
while(q < 6 && ln[q]) {
|
|
m++;
|
|
q++;
|
|
}
|
|
while(n > 15) {
|
|
pk.Cat((15 << 3));
|
|
n -= 15;
|
|
}
|
|
if(m > 7) {
|
|
pk.Cat((n << 3) | 7);
|
|
m -= 7;
|
|
while(m > 7) {
|
|
pk.Cat(7);
|
|
m -= 7;
|
|
}
|
|
if(m)
|
|
pk.Cat(m);
|
|
}
|
|
else
|
|
pk.Cat((n << 3) | m);
|
|
n = 1;
|
|
wasnot = false;
|
|
}
|
|
else
|
|
n++;
|
|
if(wasnot)
|
|
pk.Cat(0x80);
|
|
else
|
|
*(pk.End() - 1) |= 0x80;
|
|
}
|
|
pk.Cat(0);
|
|
of_packed = pk;
|
|
}
|
|
|
|
int BlendColor1(int a, int c, int cc)
|
|
{
|
|
return (byte)((((a + (a >> 7)) * (c - cc)) >> 8) + cc);
|
|
}
|
|
|
|
#define BLEND(i, d) \
|
|
{ \
|
|
const int alpha = d + (d >> 7); \
|
|
byte *m = (byte *)&a[i]; \
|
|
m[0] += (alpha * (tr - m[0]) >> 8); \
|
|
m[1] += (alpha * (tg - m[1]) >> 8); \
|
|
m[2] += (alpha * (tb - m[2]) >> 8); \
|
|
}
|
|
|
|
|
|
#define SET(i) a[i] = ic
|
|
|
|
void DrawF(PixelBlock& w, int x, int y, Color c)
|
|
{
|
|
dword *a = w.PointAdr(x, y);
|
|
int d = w.LineDelta();
|
|
byte tr = c.GetR();
|
|
byte tg = c.GetG();
|
|
byte tb = c.GetB();
|
|
dword ic = c;
|
|
BLEND(1, 0x80); SET(2); SET(3); BLEND(4, 0x80); a += d;
|
|
SET(1); BLEND(2, 0x10); BLEND(3, 0x10); SET(4); a += d;
|
|
BLEND(0, 0x80); BLEND(1, 0x80); BLEND(4, 0x80); BLEND(5, 0x80); a += d;
|
|
BLEND(0, 0xb0); BLEND(1, 0x70); BLEND(4, 0x70); BLEND(5, 0xb0); a += d;
|
|
// BLEND(0, 0xe0); BLEND(1, 0x30); BLEND(4, 0x30); BLEND(5, 0xe0); a += d;
|
|
SET(0); SET(5); a += d;
|
|
SET(0); SET(5); a += d;
|
|
SET(0); SET(5); a += d;
|
|
// BLEND(0, 0xe0); BLEND(1, 0x30); BLEND(4, 0x30); BLEND(5, 0xe0); a += d;
|
|
BLEND(0, 0xb0); BLEND(1, 0x70); BLEND(4, 0x70); BLEND(5, 0xb0); a += d;
|
|
BLEND(0, 0x80); BLEND(1, 0x80); BLEND(4, 0x80); BLEND(5, 0x80); a += d;
|
|
SET(1); BLEND(2, 0x10); BLEND(3, 0x10); SET(4); a += d;
|
|
BLEND(1, 0x80); SET(2); SET(3); BLEND(4, 0x80); a += d;
|
|
}
|
|
|
|
static const byte o[] = {
|
|
// 0 1 2 3 4 5
|
|
0x00, 0x80, 0xff, 0xff, 0x80, 0x00,
|
|
0x00, 0xff, 0x10, 0x10, 0xff, 0x00,
|
|
0x80, 0x80, 0x00, 0x00, 0xff, 0x80,
|
|
0xb0, 0x70, 0x00, 0x00, 0x70, 0xb0,
|
|
0xe0, 0x30, 0x00, 0x00, 0x30, 0xe0,
|
|
0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
|
|
0xe0, 0x30, 0x00, 0x00, 0x30, 0xe0,
|
|
0xb0, 0x70, 0x00, 0x00, 0x70, 0xb0,
|
|
0x80, 0x80, 0x00, 0x00, 0xff, 0x80,
|
|
0x00, 0xff, 0x10, 0x10, 0xff, 0x00,
|
|
0x00, 0x80, 0xff, 0xff, 0x80, 0x00,
|
|
};
|
|
|
|
void DrawO1(PixelBlock& w, int x, int y, Color c)
|
|
{
|
|
const byte *s = o;
|
|
dword *a = w.PointAdr(x, y);
|
|
int d = w.LineDelta();
|
|
byte tr = c.GetR();
|
|
byte tg = c.GetG();
|
|
byte tb = c.GetB();
|
|
for(int w = 0; w < 11; w++) {
|
|
for(int q = 0; q < 6; q++) {
|
|
int alpha = *s + (*s >> 7);
|
|
dword cc = a[q];
|
|
byte r = (byte)(cc >> 16);
|
|
byte g = (byte)(cc >> 8);
|
|
byte b = (byte)(cc);
|
|
r = (alpha * (tr - r) >> 8) + r;
|
|
g = (alpha * (tg - g) >> 8) + g;
|
|
b = (alpha * (tb - b) >> 8) + b;
|
|
a[q] = (byte(r) << 16) | (byte(g) << 8) | byte(b);
|
|
s++;
|
|
}
|
|
a += d;
|
|
}
|
|
}
|
|
|
|
void DrawO2(PixelBlock& w, int x, int y, Color c)
|
|
{
|
|
const byte *s = o;
|
|
dword *a = w.PointAdr(x, y);
|
|
int d = w.LineDelta();
|
|
byte tr = c.GetR();
|
|
byte tg = c.GetG();
|
|
byte tb = c.GetB();
|
|
for(int w = 0; w < 11; w++) {
|
|
for(int q = 0; q < 6; q++) {
|
|
int alpha = *s + (*s >> 7);
|
|
s++;
|
|
byte *m = (byte *)&a[q];
|
|
m[0] += (alpha * (tr - m[0]) >> 8);
|
|
m[1] += (alpha * (tg - m[1]) >> 8);
|
|
m[2] += (alpha * (tb - m[2]) >> 8);
|
|
}
|
|
a += d;
|
|
}
|
|
}
|
|
|
|
String op;
|
|
|
|
String PackOP(const byte *s, int cx, int cy)
|
|
{
|
|
StringBuffer result;
|
|
for(int i = 0; i < cy; i++) {
|
|
int j = 0;
|
|
while(j < cx) {
|
|
if(*s == 0) {
|
|
int n = 0;
|
|
while(*s == 0 && j < cx) {
|
|
n++;
|
|
j++;
|
|
s++;
|
|
}
|
|
while(n >= 255) {
|
|
result.Cat(0);
|
|
result.Cat(254);
|
|
n -= 254;
|
|
}
|
|
result.Cat(0);
|
|
result.Cat(n);
|
|
}
|
|
else {
|
|
result.Cat(*s++);
|
|
j++;
|
|
}
|
|
}
|
|
result.Cat(0);
|
|
result.Cat(0);
|
|
}
|
|
result.Cat(0);
|
|
result.Cat(255);
|
|
return result;
|
|
}
|
|
|
|
void DrawOP(PixelBlock& w, int x, int y, Color c)
|
|
{
|
|
const byte *s = op;
|
|
dword *a = w.PointAdr(x, y);
|
|
int d = w.LineDelta();
|
|
byte tr = c.GetR();
|
|
byte tg = c.GetG();
|
|
byte tb = c.GetB();
|
|
int q = 0;
|
|
for(;;) {
|
|
byte c = *s++;
|
|
if(c) {
|
|
byte *m = (byte *)&a[q];
|
|
int alpha = c + (c >> 7);
|
|
m[0] += alpha * (tr - m[0]) >> 8;
|
|
m[1] += alpha * (tg - m[1]) >> 8;
|
|
m[2] += alpha * (tb - m[2]) >> 8;
|
|
q++;
|
|
}
|
|
else {
|
|
c = *s++;
|
|
if(c)
|
|
q += c;
|
|
else {
|
|
if(s[0] == 0 && s[1] == 255)
|
|
return;
|
|
a += d;
|
|
q = 0;
|
|
}
|
|
}
|
|
}
|
|
a += d;
|
|
}
|
|
|
|
void DrawOPMMX(PixelBlock& w, int x, int y, Color color)
|
|
{
|
|
const byte *s = op;
|
|
dword *a = w.PointAdr(x, y);
|
|
int d = w.LineDelta();
|
|
byte tr = color.GetR();
|
|
byte tg = color.GetG();
|
|
byte tb = color.GetB();
|
|
int q = 0;
|
|
__m64 zero = _mm_setzero_si64();
|
|
__m64 mc = _mm_unpacklo_pi8(_mm_cvtsi32_si64(color.GetRaw()), zero);
|
|
__m64 mask = _mm_set1_pi16(0xff);
|
|
for(;;) {
|
|
byte c = *s++;
|
|
if(c) {
|
|
__m64 alpha = _mm_cvtsi32_si64(c);
|
|
alpha = _mm_unpacklo_pi16(alpha, alpha);
|
|
alpha = _mm_unpacklo_pi32(alpha, alpha);
|
|
__m64 h = _mm_srli_pi16(alpha, 7);
|
|
alpha = _mm_adds_pi16(alpha, h);
|
|
__m64 m = _mm_cvtsi32_si64(a[q]);
|
|
m = _mm_unpacklo_pi8(m, zero);
|
|
h = _mm_sub_pi16(mc, m);
|
|
h = _mm_mullo_pi16(alpha, h);
|
|
h = _mm_srli_pi16(h, 8);
|
|
m = _mm_add_pi16(m, h);
|
|
m = _mm_and_si64(m, mask);
|
|
m = _mm_packs_pu16(m, m);
|
|
a[q++] = _mm_cvtsi64_si32(m);
|
|
}
|
|
else {
|
|
c = *s++;
|
|
if(c)
|
|
q += c;
|
|
else {
|
|
if(s[0] == 0 && s[1] == 255)
|
|
break;
|
|
a += d;
|
|
q = 0;
|
|
}
|
|
}
|
|
}
|
|
_m_empty();
|
|
}
|
|
|
|
#define N 300
|
|
|
|
void DoTest(Draw& w, const char *name, void (*od)(PixelBlock&, int, int, Color))
|
|
{
|
|
for(int section = 0; section < 2; section++) {
|
|
String ss = section ? "SECTION " : "SETDIB ";
|
|
{
|
|
TimeStop tm;
|
|
PixelBlock b(1024, 768, section);
|
|
for(int i = 0; i < N; i++) {
|
|
if(od) {
|
|
b.DrawRect(0, 0, 512, 768, White);
|
|
b.DrawRect(512, 0, 512, 768, Red);
|
|
for(int x = 0; x < 1024 / 8 - 1; x++)
|
|
for(int y = 0; y < 768 / 16 - 1; y++)
|
|
(*od)(b, 8 * x, 16 * y, x < 512 / 8 ? Black : White);
|
|
}
|
|
b.Put(w, 0, 0);
|
|
Draw::Flush();
|
|
}
|
|
RLOG(ss << name << ": " << tm.Elapsed() / N << " ms");
|
|
}
|
|
{
|
|
TimeStop tm;
|
|
PixelBlock b(1024, 768, section);
|
|
for(int i = 0; i < N; i++) {
|
|
if(od) {
|
|
for(int y = 0; y < 768 / 16 - 1; y++) {
|
|
b.DrawRect(0, 16 * y, 1024, 16, Color(y & 255, y & 255, y & 255));
|
|
for(int x = 0; x < 1024 / 8 - 1; x++)
|
|
(*od)(b, 8 * x, 16 * y, x < 512 / 8 ? Black : White);
|
|
}
|
|
}
|
|
b.Put(w, 0, 0);
|
|
Draw::Flush();
|
|
}
|
|
RLOG(ss << name << " cached: " << tm.Elapsed() / N << " ms");
|
|
}
|
|
}
|
|
}
|
|
|
|
void MDraw::Paint(Draw& w)
|
|
{
|
|
Size sz = GetSize();
|
|
/*
|
|
{
|
|
TimeStop tm;
|
|
for(int i = 0; i < 1000; i++)
|
|
w.DrawRect(0, 0, 1024, 768, Color(i, i, i));
|
|
Draw::Flush();
|
|
RLOG("Painting using GDI: " << tm);
|
|
}
|
|
|
|
{
|
|
TimeStop tm;
|
|
for(int i = 0; i < 1000; i++) {
|
|
PixelBlock b(1024, 768, true);
|
|
b.DrawRect(0, 0, sz.cx, sz.cy, Color(i, i, i));
|
|
b.Put(w, 0, 0);
|
|
}
|
|
Draw::Flush();
|
|
RLOG("Painting using Section: " << tm);
|
|
}
|
|
*/
|
|
/* {
|
|
FontInfo fi = w.GetFontInfo(Arial(15));
|
|
String text = String('0', 1024 / fi['0']);
|
|
TimeStop tm;
|
|
for(int i = 0; i < N; i++) {
|
|
w.DrawRect(0, 0, 1024, 768, White);
|
|
for(int y = 0; y < 768; y += fi.GetHeight())
|
|
w.DrawText(0, y, text, Arial(15), Color(i, i, i));
|
|
Draw::Flush();
|
|
}
|
|
RLOG("GDI: " << tm.Elapsed() / N << " ms");
|
|
}
|
|
*/
|
|
DoTest(w, "R - Just PUT", NULL);
|
|
DoTest(w, "R - Just rect", DrawR);
|
|
DoTest(w, "01 - no antialiasing", DrawO);
|
|
DoTest(w, "0F - no antialiasing packed", DrawOF);
|
|
DoTest(w, "01 - shifts", DrawO1);
|
|
DoTest(w, "02 - loads", DrawO2);
|
|
DoTest(w, "F - fast", DrawF);
|
|
DoTest(w, "0P - packed", DrawOP);
|
|
DoTest(w, "0P - packed MMX", DrawOPMMX);
|
|
|
|
w.DrawRect(0, 0, 100, 100, SBlue);
|
|
}
|
|
|
|
GUI_APP_MAIN
|
|
{
|
|
PackOF();
|
|
DUMP(of_packed.GetLength());
|
|
op = PackOP(o, 6, 11);
|
|
LOGHEXDUMP(op, op.GetLength());
|
|
RDUMP(op.GetLength());
|
|
Ctrl::AutoBackPaintAreaSize = 0;
|
|
MDraw t;
|
|
t.SetRect(0, 0, 1024, 768);
|
|
t.Sizeable().Zoomable();
|
|
t.Run();
|
|
}
|