Core: Unaligned access reimplemented with memcpy, Draw, ide: iml improvements

This commit is contained in:
Mirek Fidler 2024-07-13 18:58:30 +02:00
parent e4ac7cc776
commit 19dd6c72f1
29 changed files with 352 additions and 466 deletions

View file

@ -201,7 +201,6 @@ CONSOLE_APP_MAIN
CheckFill<uint64>(memset64); CheckFill<uint64>(memset64);
CheckFill<m128n>(memset128); CheckFill<m128n>(memset128);
struct dqword { qword x[2]; };
CheckCopy<byte>(memcpy8); CheckCopy<byte>(memcpy8);
CheckCopy<word>(memcpy16); CheckCopy<word>(memcpy16);
CheckCopy<dword>(memcpy32); CheckCopy<dword>(memcpy32);

View file

@ -133,5 +133,17 @@ CONSOLE_APP_MAIN
lc2 = lc; lc2 = lc;
} }
for(int c = '1'; c <= '9'; c++) {
String h(c, 64);
for(int i = 0; i < h.GetCount(); i++) {
String q = h;
q.Trim(i);
String w = h.Mid(0, i);
ASSERT(GetHashValue(q) == GetHashValue(w));
ASSERT(q == w);
}
}
LOG("============== OK"); LOG("============== OK");
} }

View file

@ -108,10 +108,10 @@ hash_t memhash(const void *ptr, size_t len)
uint64 val1, val2, val3, val4; uint64 val1, val2, val3, val4;
val1 = val2 = val3 = val4 = HASH_CONST1; val1 = val2 = val3 = val4 = HASH_CONST1;
while(len >= 32) { while(len >= 32) {
val1 = HASH_CONST2 * val1 + *(qword *)(s); val1 = HASH_CONST2 * val1 + Peek64(s);
val2 = HASH_CONST2 * val2 + *(qword *)(s + 8); val2 = HASH_CONST2 * val2 + Peek64(s + 8);
val3 = HASH_CONST2 * val3 + *(qword *)(s + 16); val3 = HASH_CONST2 * val3 + Peek64(s + 16);
val4 = HASH_CONST2 * val4 + *(qword *)(s + 24); val4 = HASH_CONST2 * val4 + Peek64(s + 24);
s += 32; s += 32;
len -= 32; len -= 32;
} }
@ -122,19 +122,19 @@ hash_t memhash(const void *ptr, size_t len)
} }
const byte *e = s + len - 8; const byte *e = s + len - 8;
while(s < e) { while(s < e) {
val = HASH_CONST2 * val + *(qword *)(s); val = HASH_CONST2 * val + Peek64(s);
s += 8; s += 8;
} }
return HASH_CONST2 * val + *(qword *)(e); return HASH_CONST2 * val + Peek64(e);
} }
if(len > 4) { if(len > 4) {
val = HASH_CONST2 * val + *(dword *)(s); val = HASH_CONST2 * val + Peek32(s);
val = HASH_CONST2 * val + *(dword *)(s + len - 4); val = HASH_CONST2 * val + Peek32(s + len - 4);
return val; return val;
} }
if(len >= 2) { if(len >= 2) {
val = HASH_CONST2 * val + *(word *)(s); val = HASH_CONST2 * val + Peek16(s);
val = HASH_CONST2 * val + *(word *)(s + len - 2); val = HASH_CONST2 * val + Peek16(s + len - 2);
return val; return val;
} }
return len ? HASH_CONST2 * val + *s : val; return len ? HASH_CONST2 * val + *s : val;
@ -172,8 +172,8 @@ hash_t memhash(const void *ptr, size_t len)
return HASH_CONST2 * val + *(dword *)(e); return HASH_CONST2 * val + *(dword *)(e);
} }
if(len >= 2) { if(len >= 2) {
val = HASH_CONST2 * val + *(word *)(s); val = HASH_CONST2 * val + Peek16(s);
val = HASH_CONST2 * val + *(word *)(s + len - 2); val = HASH_CONST2 * val + Peek16(s + len - 2);
return val; return val;
} }
return len ? HASH_CONST2 * val + *s : val; return len ? HASH_CONST2 * val + *s : val;

View file

@ -2,6 +2,36 @@
void memset8__(void *t, i16x8 data, size_t len); void memset8__(void *t, i16x8 data, size_t len);
inline void Set2__(void *t, dword val)
{
memcpy(t, &val, 2);
}
inline void Set4__(void *t, dword val)
{
memcpy(t, &val, 4);
}
inline void Set8__(void *t, uint64 val)
{
memcpy(t, &val, 8);
}
inline void Cpy2__(void *t, const void *s)
{
memcpy(t, s, 2);
}
inline void Cpy4__(void *t, const void *s)
{
memcpy(t, s, 4);
}
inline void Cpy8__(void *t, const void *s)
{
memcpy(t, s, 8);
}
inline inline
void memset8(void *p, byte data, size_t count) void memset8(void *p, byte data, size_t count)
{ {
@ -13,16 +43,20 @@ void memset8(void *p, byte data, size_t count)
} }
dword val4 = 0x1010101 * data; dword val4 = 0x1010101 * data;
if(count <= 4) { if(count <= 4) {
*(word *)t = *(word *)(t + count - 2) = (word)val4; Set2__(t, val4);
Set2__(t + count - 2, val4);
return; return;
} }
if(count > 16) { if(count > 16) {
memset8__(t, i32all(val4), count); memset8__(t, i32all(val4), count);
return; return;
} }
*(dword *)t = *(dword *)(t + count - 4) = val4; Set4__(t, val4);
if(count > 8) Set4__(t + count - 4, val4);
*(dword *)(t + 4) = *(dword *)(t + count - 8) = val4; if(count > 8) {
Set4__(t + 4, val4);
Set4__(t + count - 8, val4);
}
} }
inline inline
@ -31,7 +65,7 @@ void memset16(void *p, word data, size_t count)
word *t = (word *)p; word *t = (word *)p;
if(count < 2) { if(count < 2) {
if(count) if(count)
t[0] = data; Set2__(t, data);
return; return;
} }
dword val4 = 0x10001 * data; dword val4 = 0x10001 * data;
@ -39,18 +73,18 @@ void memset16(void *p, word data, size_t count)
memset8__(t, i32all(val4), 2 * count); memset8__(t, i32all(val4), 2 * count);
return; return;
} }
*(dword *)(t + count - 2) = val4; Set4__(t + count - 2, val4);
if(count & 8) { if(count & 8) {
i32all(val4).Store(t); i32all(val4).Store(t);
t += 8; t += 8;
} }
if(count & 4) { if(count & 4) {
*(dword *)t = val4; Set4__(t, val4);
*(dword *)(t + 2) = val4; Set4__(t + 2, val4);
t += 4; t += 4;
} }
if(count & 2) if(count & 2)
*(dword *)t = val4; Set4__(t, val4);
} }
inline inline
@ -59,11 +93,13 @@ void memset32(void *p, dword data, size_t count)
dword *t = (dword *)p; dword *t = (dword *)p;
if(count < 4) { if(count < 4) {
if(count & 2) { if(count & 2) {
t[0] = t[1] = t[count - 1] = data; Set4__(t, data);
Set4__(t + 1, data);
Set4__(t + count - 1, data);
return; return;
} }
if(count & 1) if(count & 1)
t[0] = data; Set4__(t, data);
return; return;
} }
i32x4 val4 = i32all(data); i32x4 val4 = i32all(data);
@ -87,7 +123,7 @@ void memset64(void *p, qword data, size_t count)
qword *t = (qword *)p; qword *t = (qword *)p;
if(count < 2) { if(count < 2) {
if(count) if(count)
t[0] = data; Set8__(t, data);
return; return;
} }
i16x8 val2 = i64all(data); i16x8 val2 = i64all(data);
@ -125,18 +161,18 @@ void memcpy8(void *p, const void *q, size_t count)
t[0] = s[0]; t[0] = s[0];
return; return;
} }
*(word *)t = *(word *)s; Cpy2__(t, s);
*(word *)(t + count - 2) = *(word *)(s + count - 2); Cpy2__(t + count - 2, s + count - 2);
return; return;
} }
if(count <= 16) { if(count <= 16) {
if(count <= 8) { if(count <= 8) {
*(dword *)(t) = *(dword *)(s); Cpy4__(t, s);
*(dword *)(t + count - 4) = *(dword *)(s + count - 4); Cpy4__(t + count - 4, s + count - 4);
return; return;
} }
*(uint64 *)t = *(uint64 *)s; Cpy8__(t, s);
*(uint64 *)(t + count - 8) = *(uint64 *)(s + count - 8); Cpy8__(t + count - 8, s + count - 8);
return; return;
} }
if(count <= 32) { // improves String::LSet if(count <= 32) { // improves String::LSet
@ -157,17 +193,17 @@ void memcpy16(void *p, const void *q, size_t count)
if(count <= 4) { if(count <= 4) {
if(count < 2) { if(count < 2) {
if(count) if(count)
t[0] = s[0]; Cpy2__(t, s);
return; return;
} }
*(dword *)t = *(dword *)s; Cpy4__(t, s);
*(dword *)(t + count - 2) = *(dword *)(s + count - 2); Cpy4__(t + count - 2, s + count - 2);
return; return;
} }
if(count <= 16) { if(count <= 16) {
if(count <= 8) { if(count <= 8) {
*(uint64 *)(t) = *(uint64 *)(s); Cpy8__(t, s);
*(uint64 *)(t + count - 4) = *(uint64 *)(s + count - 4); Cpy8__(t + count - 4, s + count - 4);
return; return;
} }
auto Copy128 = [&](size_t at) { i16x8(s + at).Store(t + at); }; auto Copy128 = [&](size_t at) { i16x8(s + at).Store(t + at); };
@ -188,8 +224,8 @@ void memcpy32(void *p, const void *q, size_t count)
if(count <= 4) { if(count <= 4) {
if(count) { if(count) {
if(count > 1) { if(count > 1) {
*(int64 *)t = *(int64 *)s; Cpy8__(t, s);
*(int64 *)(t + count - 2) = *(int64 *)(s + count - 2); Cpy8__(t + count - 2, s + count - 2);
return; return;
} }
*t = *s; *t = *s;
@ -200,9 +236,9 @@ void memcpy32(void *p, const void *q, size_t count)
if(count < 4) { if(count < 4) {
if(count) { if(count) {
if(count > 1) { if(count > 1) {
t[0] = s[0]; Cpy4__(t, s);
t[1] = s[1]; Cpy4__(t + 1, s + 1);
t[count - 1] = s[count - 1]; Cpy4__(t + count - 1, s + count - 1);
return; return;
} }
*t = *s; *t = *s;
@ -236,8 +272,8 @@ void memcpy64(void *p, const void *q, size_t count)
if(count <= 2) { if(count <= 2) {
if(count) { if(count) {
if(count > 1) { if(count > 1) {
*(int64 *)t = *(int64 *)s; Cpy8__(t, s);
*(int64 *)(t + count - 1) = *(int64 *)(s + count - 1); Cpy8__(t + count - 1, s + count - 1);
return; return;
} }
*t = *s; *t = *s;

View file

@ -1,60 +1,9 @@
#if defined(CPU_UNALIGNED) && defined(CPU_LE) #ifndef CPU_LE
NOUBSAN inline int Peek16le(const void *ptr) { return *(const word *)ptr; } #error Only little endian CPUs supported
NOUBSAN inline int Peek32le(const void *ptr) { return *(const dword *)ptr; }
NOUBSAN inline int64 Peek64le(const void *ptr) { return *(const int64 *)ptr; }
NOUBSAN inline void Poke16le(const void *ptr, int val) { *(word *)ptr = val; }
NOUBSAN inline void Poke32le(const void *ptr, int val) { *(dword *)ptr = val; }
NOUBSAN inline void Poke64le(const void *ptr, int64 val) { *(int64 *)ptr = val; }
#else
inline int Peek16le(const void *ptr) { return MAKEWORD(((byte *)ptr)[0], ((byte *)ptr)[1]); }
inline int Peek32le(const void *ptr) { return MAKELONG(Peek16le(ptr), Peek16le((byte *)ptr + 2)); }
inline int64 Peek64le(const void *ptr) { return MAKEQWORD(Peek32le(ptr), Peek32le((byte *)ptr + 4)); }
inline void Poke16le(const void *ptr, int val) { ((byte *)ptr)[0] = LOBYTE(val); ((byte *)ptr)[1] = HIBYTE(val); }
inline void Poke32le(const void *ptr, int val) { Poke16le(ptr, LOWORD(val)); Poke16le((byte *)ptr + 2, HIWORD(val)); }
inline void Poke64le(const void *ptr, int64 val) { Poke32le(ptr, LODWORD(val)); Poke32le((byte *)ptr + 4, HIDWORD(val)); }
#endif
inline int Peek16be(const void *ptr) { return MAKEWORD(((byte *)ptr)[1], ((byte *)ptr)[0]); }
inline int Peek32be(const void *ptr) { return MAKELONG(Peek16be((byte *)ptr + 2), Peek16be(ptr)); }
inline int64 Peek64be(const void *ptr) { return MAKEQWORD(Peek32be((byte *)ptr + 4), Peek32be(ptr)); }
inline void Poke16be(const void *ptr, int val) { ((byte *)ptr)[1] = LOBYTE(val); ((byte *)ptr)[0] = HIBYTE(val); }
inline void Poke32be(const void *ptr, int val) { Poke16be(ptr, HIWORD(val)); Poke16be((byte *)ptr + 2, LOWORD(val)); }
inline void Poke64be(const void *ptr, int64 val) { Poke32be(ptr, HIDWORD(val)); Poke32be((byte *)ptr + 4, LODWORD(val)); }
#ifdef CPU_LITTLE_ENDIAN
#define MAKE2B(b0, b1) MAKEWORD(b0, b1)
#define MAKE4B(b0, b1, b2, b3) MAKELONG(MAKEWORD(b0, b1), MAKEWORD(b2, b3))
#define MAKE8B(b0, b1, b2, b3, b4, b5, b6, b7) MAKEQWORD(MAKE4B(b0, b1, b2, b3), MAKE4B(b4, b5, b6, b7))
inline int Peek16(const void *ptr) { return Peek16le(ptr); }
inline int Peek32(const void *ptr) { return Peek32le(ptr); }
inline int64 Peek64(const void *ptr) { return Peek64le(ptr); }
inline void Poke16(const void *ptr, int val) { Poke16le(ptr, val); }
inline void Poke32(const void *ptr, int val) { Poke32le(ptr, val); }
inline void Poke64(const void *ptr, int64 val) { Poke64le(ptr, val); }
#else
#define MAKE2B(b0, b1) MAKEWORD(b1, b0);
#define MAKE4B(b0, b1, b2, b3) MAKELONG(MAKEWORD(b2, b3), MAKEWORD(b0, b1))
#define MAKE8B(b0, b1, b2, b3, b4, b5, b6, b7) MAKEQWORD(MAKE4B(b7, b6, b5, b4), MAKE4B(b3, b2, b1, b0))
inline int Peek16(const void *ptr) { return Peek16be(ptr); }
inline int Peek32(const void *ptr) { return Peek32be(ptr); }
inline int64 Peek64(const void *ptr) { return Peek64be(ptr); }
inline void Poke16(const void *ptr, int val) { Poke16be(ptr, val); }
inline void Poke32(const void *ptr, int val) { Poke32be(ptr, val); }
inline void Poke64(const void *ptr, int64 val) { Poke64be(ptr, val); }
#endif #endif
#if defined(CPU_X86) && defined(COMPILER_MSC) #if defined(CPU_X86) && defined(COMPILER_MSC)
#ifdef COMPILER_GCC #ifdef COMPILER_GCC
#ifdef CPU_64 #ifdef CPU_64
inline word SwapEndian16(word v) { __asm__("xchgb %b0,%h0" : "=Q" (v) : "0" (v)); return v; } inline word SwapEndian16(word v) { __asm__("xchgb %b0,%h0" : "=Q" (v) : "0" (v)); return v; }
@ -152,6 +101,36 @@ void EndianSwap(int *v, size_t count);
void EndianSwap(int64 *v, size_t count); void EndianSwap(int64 *v, size_t count);
void EndianSwap(uint64 *v, size_t count); void EndianSwap(uint64 *v, size_t count);
// unligned access - memcpy converts to simple load/store with normal compilers
inline int Peek16(const void *ptr) { word x; memcpy(&x, ptr, 2); return x; }
inline int Peek32(const void *ptr) { dword x; memcpy(&x, ptr, 4); return x; }
inline int64 Peek64(const void *ptr) { uint64 x; memcpy(&x, ptr, 8); return x; }
inline void Poke16(void *ptr, int val) { memcpy(ptr, &val, 2); }
inline void Poke32(void *ptr, int val) { memcpy(ptr, &val, 4); }
inline void Poke64(void *ptr, int64 val) { memcpy(ptr, &val, 8); }
inline int Peek16le(const void *ptr) { return Peek16(ptr); }
inline int Peek32le(const void *ptr) { return Peek32(ptr); }
inline int64 Peek64le(const void *ptr) { return Peek64(ptr); }
inline void Poke16le(void *ptr, int val) { Poke16(ptr, val); }
inline void Poke32le(void *ptr, int val) { Poke32(ptr, val); }
inline void Poke64le(void *ptr, int64 val) { Poke64(ptr, val); }
inline int Peek16be(const void *ptr) { return SwapEndian16(Peek16(ptr)); }
inline int Peek32be(const void *ptr) { return SwapEndian32(Peek32(ptr)); }
inline int64 Peek64be(const void *ptr) { return SwapEndian64(Peek64(ptr)); }
inline void Poke16be(void *ptr, int val) { Poke16(ptr, SwapEndian16(val)); }
inline void Poke32be(void *ptr, int val) { Poke32(ptr, SwapEndian32(val)); }
inline void Poke64be(void *ptr, int64 val) { Poke64(ptr, SwapEndian64(val)); }
#define MAKE2B(b0, b1) MAKEWORD(b0, b1)
#define MAKE4B(b0, b1, b2, b3) MAKELONG(MAKEWORD(b0, b1), MAKEWORD(b2, b3))
#define MAKE8B(b0, b1, b2, b3, b4, b5, b6, b7) MAKEQWORD(MAKE4B(b0, b1, b2, b3), MAKE4B(b4, b5, b6, b7))
#ifdef CPU_64 #ifdef CPU_64
#define HASH64 #define HASH64

View file

@ -1729,7 +1729,7 @@ Image GetDirIcon(const String& s)
#endif #endif
if(IsNull(img)) if(IsNull(img))
img = CtrlImg::Dir(); img = CtrlImg::Dir();
return DPI(img); return img;
} }
void FolderDisplay::Paint(Draw& w, const Rect& r, const Value& q, void FolderDisplay::Paint(Draw& w, const Rect& r, const Value& q,
@ -2198,7 +2198,7 @@ void FileSel::AddPlaceRaw(const String& path, const Image& m, const String& name
row = row < 0 ? places.GetCount() : row; row = row < 0 ? places.GetCount() : row;
places.Insert(row); places.Insert(row);
places.Set(row, 0, path); places.Set(row, 0, path);
places.Set(row, 1, DPI(m)); places.Set(row, 1, m);
places.Set(row, 2, name); places.Set(row, 2, name);
places.Set(row, 3, group); places.Set(row, 3, group);
places.SetLineCy(row, max(m.GetSize().cy + 4, GetStdFontCy() + 4)); places.SetLineCy(row, max(m.GetSize().cy + 4, GetStdFontCy() + 4));
@ -2210,7 +2210,7 @@ void FileSel::AddPlaceRaw(const String& path, const Image& m, const String& name
FileSel& FileSel::AddPlace(const String& path, const Image& m, const String& name, const char* group, int row) FileSel& FileSel::AddPlace(const String& path, const Image& m, const String& name, const char* group, int row)
{ {
if(path.GetCount()) if(path.GetCount())
AddPlaceRaw(NormalizePath(path), DPI(m), name, group, row); AddPlaceRaw(NormalizePath(path), m, name, group, row);
return *this; return *this;
} }

View file

@ -54,7 +54,6 @@ void ImageBuffer::InitAttrs()
{ {
spot2 = hotspot = Point(0, 0); spot2 = hotspot = Point(0, 0);
dots = Size(0, 0); dots = Size(0, 0);
resolution = IMAGE_RESOLUTION_NONE;
paintonce = false; paintonce = false;
} }
@ -63,7 +62,6 @@ void ImageBuffer::CopyAttrs(const ImageBuffer& img)
SetHotSpot(img.GetHotSpot()); SetHotSpot(img.GetHotSpot());
Set2ndSpot(img.Get2ndSpot()); Set2ndSpot(img.Get2ndSpot());
SetDots(img.GetDots()); SetDots(img.GetDots());
SetResolution(img.GetResolution());
PaintOnceHint(img.IsPaintOnceHint()); PaintOnceHint(img.IsPaintOnceHint());
} }
@ -195,11 +193,6 @@ Size Image::GetDPI() const
return data ? Size(int(600.*size.cx/dots.cx), int(600.*size.cy/dots.cy)): Size(0, 0); return data ? Size(int(600.*size.cx/dots.cx), int(600.*size.cy/dots.cy)): Size(0, 0);
} }
int Image::GetResolution() const
{
return data ? data->buffer.GetResolution() : IMAGE_RESOLUTION_NONE;
}
int Image::GetKindNoScan() const int Image::GetKindNoScan() const
{ {
return data ? data->buffer.GetKind() : IMAGE_ALPHA; return data ? data->buffer.GetKind() : IMAGE_ALPHA;
@ -282,7 +275,6 @@ bool Image::operator==(const Image& img) const
GetHotSpot() == img.GetHotSpot() && GetHotSpot() == img.GetHotSpot() &&
Get2ndSpot() == img.Get2ndSpot() && Get2ndSpot() == img.Get2ndSpot() &&
GetDots() == img.GetDots() && GetDots() == img.GetDots() &&
GetResolution() == img.GetResolution() &&
memeq_t(~*this, ~img, GetLength()); memeq_t(~*this, ~img, GetLength());
} }
@ -397,7 +389,6 @@ String StoreImageAsString(const Image& img)
if(img.GetKind() == IMAGE_EMPTY) if(img.GetKind() == IMAGE_EMPTY)
return Null; return Null;
int type = img.GetKind() == IMAGE_OPAQUE ? 3 : 4; int type = img.GetKind() == IMAGE_OPAQUE ? 3 : 4;
type |= decode(img.GetResolution(), IMAGE_RESOLUTION_STANDARD, 0x40, IMAGE_RESOLUTION_UHD, 0x80, 0);
StringStream ss; StringStream ss;
ss.Put(type); ss.Put(type);
Size sz = img.GetSize(); Size sz = img.GetSize();
@ -439,7 +430,6 @@ Image LoadImageFromString(const String& src)
return Null; return Null;
StringStream ss(src); StringStream ss(src);
int type = ss.Get(); int type = ss.Get();
int resolution = decode(type & 0xc0, 0x40, IMAGE_RESOLUTION_STANDARD, 0x80, IMAGE_RESOLUTION_UHD, 0);
type &= 0x3f; type &= 0x3f;
Size sz; Size sz;
sz.cx = ss.Get16le(); sz.cx = ss.Get16le();
@ -464,7 +454,6 @@ Image LoadImageFromString(const String& src)
ImageBuffer ib(sz); ImageBuffer ib(sz);
ib.SetHotSpot(p); ib.SetHotSpot(p);
ib.SetDots(dots); ib.SetDots(dots);
ib.SetResolution(resolution);
RGBA *t = ib; RGBA *t = ib;
const RGBA *e = t + ib.GetLength(); const RGBA *e = t + ib.GetLength();
const byte *s = data; const byte *s = data;

View file

@ -42,12 +42,6 @@ inline byte Saturate255(int x) { return byte(~(x >> 24) & (x | (-(x
class Image; class Image;
enum ImageResolutionIntent {
IMAGE_RESOLUTION_NONE = -1,
IMAGE_RESOLUTION_STANDARD = 0,
IMAGE_RESOLUTION_UHD = 1,
};
class ImageBuffer : NoCopy { class ImageBuffer : NoCopy {
std::atomic<int> kind; // atomic because it can be set by 2 threads, in theory std::atomic<int> kind; // atomic because it can be set by 2 threads, in theory
Size size; Size size;
@ -55,7 +49,6 @@ class ImageBuffer : NoCopy {
Point hotspot; Point hotspot;
Point spot2; Point spot2;
Size dots; Size dots;
int8 resolution;
bool paintonce = false; bool paintonce = false;
void Set(Image& img); void Set(Image& img);
@ -86,9 +79,6 @@ public:
void SetDPI(Size sz); void SetDPI(Size sz);
Size GetDPI(); Size GetDPI();
void SetResolution(int i) { resolution = i; }
int GetResolution() const { return resolution; }
void CopyAttrs(const ImageBuffer& img); void CopyAttrs(const ImageBuffer& img);
void CopyAttrs(const Image& img); void CopyAttrs(const Image& img);
@ -178,7 +168,6 @@ public:
Size GetDPI() const; Size GetDPI() const;
int GetKindNoScan() const; int GetKindNoScan() const;
int GetKind() const; int GetKind() const;
int GetResolution() const;
bool IsOpaque() const { return GetKind() == IMAGE_OPAQUE; } bool IsOpaque() const { return GetKind() == IMAGE_OPAQUE; }
const RGBA *Begin() const { return data ? ~data->buffer : NULL; } const RGBA *Begin() const { return data ? ~data->buffer : NULL; }
@ -274,6 +263,7 @@ enum {
IML_IMAGE_FLAG_FIXED_SIZE = 0x4, IML_IMAGE_FLAG_FIXED_SIZE = 0x4,
IML_IMAGE_FLAG_UHD = 0x8, IML_IMAGE_FLAG_UHD = 0x8,
IML_IMAGE_FLAG_DARK = 0x10, IML_IMAGE_FLAG_DARK = 0x10,
IML_IMAGE_FLAG_S3 = 0x20,
}; };
Image MakeImlImage(const String& id, Function<ImageIml (int, const String&)> GetRaw, dword global_flags); Image MakeImlImage(const String& id, Function<ImageIml (int, const String&)> GetRaw, dword global_flags);

View file

@ -30,25 +30,6 @@ Image WithHotSpot(const Image& m, int x1, int y1)
return b; return b;
} }
void SetResolution(Image& m, int res)
{
ImageBuffer b(m);
b.SetResolution(res);
m = b;
}
Image WithResolution(const Image& m, int res)
{
Image h = m;
SetResolution(h, res);
return h;
}
Image WithResolution(const Image& m, const Image& res)
{
return WithResolution(m, res.GetResolution());
}
Image CreateImage(Size sz, const RGBA& rgba) Image CreateImage(Size sz, const RGBA& rgba)
{ {
ImageBuffer ib(sz); ImageBuffer ib(sz);
@ -88,7 +69,6 @@ force_inline Size DstSrc(ImageBuffer& dest, Point& p, const Image& src, Rect& sr
void DstSrcOp(ImageBuffer& dest, Point p, const Image& src, const Rect& srect, void DstSrcOp(ImageBuffer& dest, Point p, const Image& src, const Rect& srect,
void (*op)(RGBA *t, const RGBA *s, int n), bool co) void (*op)(RGBA *t, const RGBA *s, int n), bool co)
{ {
dest.SetResolution(src.GetResolution());
Rect sr = srect; Rect sr = srect;
Size sz = DstSrc(dest, p, src, sr); Size sz = DstSrc(dest, p, src, sr);
if(sz.cx > 0) { if(sz.cx > 0) {
@ -193,7 +173,7 @@ Image Crop(const Image& img, const Rect& rc)
ImageRaster src(img); ImageRaster src(img);
ImageEncoder tgt; ImageEncoder tgt;
Crop(tgt, src, rc); Crop(tgt, src, rc);
return WithResolution(tgt, img); return tgt;
} }
Image AddMargins(const Image& img, int left, int top, int right, int bottom, RGBA color, bool co) Image AddMargins(const Image& img, int left, int top, int right, int bottom, RGBA color, bool co)
@ -274,7 +254,6 @@ void ClampHotSpots(Image& m)
Image ColorMask(const Image& src, Color key) Image ColorMask(const Image& src, Color key)
{ {
ImageBuffer ib(src.GetSize()); ImageBuffer ib(src.GetSize());
ib.SetResolution(src.GetResolution());
const RGBA *s = src; const RGBA *s = src;
const RGBA *e = src + src.GetLength(); const RGBA *e = src + src.GetLength();
RGBA *t = ~ib; RGBA *t = ~ib;
@ -313,7 +292,7 @@ Image CanvasSize(const Image& img, int cx, int cy)
ImageRaster src(img); ImageRaster src(img);
ImageEncoder tgt; ImageEncoder tgt;
CanvasSize(tgt, src, cx, cy); CanvasSize(tgt, src, cx, cy);
return WithResolution(tgt, img); return tgt;
} }
Image AssignAlpha(const Image& img, const Image& alpha) Image AssignAlpha(const Image& img, const Image& alpha)
@ -334,7 +313,6 @@ Image AssignAlpha(const Image& img, const Image& alpha)
} }
} }
ib.SetHotSpots(img); ib.SetHotSpots(img);
ib.SetResolution(img.GetResolution());
return ib; return ib;
} }
@ -378,7 +356,6 @@ Image Equalight(const Image& img, int thold)
t++; t++;
} }
w.SetHotSpots(img); w.SetHotSpots(img);
w.SetResolution(img.GetResolution());
return w; return w;
} }
@ -398,7 +375,6 @@ Image Grayscale(const Image& img)
s++; s++;
} }
w.SetHotSpots(img); w.SetHotSpots(img);
w.SetResolution(img.GetResolution());
return w; return w;
} }
@ -419,7 +395,6 @@ Image Grayscale(const Image& img, int amount)
s++; s++;
} }
w.SetHotSpots(img); w.SetHotSpots(img);
w.SetResolution(img.GetResolution());
return w; return w;
} }
@ -446,7 +421,6 @@ Image Colorize(const Image& img, Color color, int alpha)
} }
Premultiply(w); Premultiply(w);
w.SetHotSpots(img); w.SetHotSpots(img);
w.SetResolution(img.GetResolution());
return w; return w;
} }
@ -474,7 +448,6 @@ Image DarkTheme(const Image& img)
Premultiply(ib); Premultiply(ib);
ib.SetHotSpots(img); ib.SetHotSpots(img);
ib.SetResolution(img.GetResolution());
return ib; return ib;
} }
@ -502,7 +475,6 @@ Image Contrast(const Image& img, int amount)
} }
Premultiply(w); Premultiply(w);
w.SetHotSpots(img); w.SetHotSpots(img);
w.SetResolution(img.GetResolution());
return w; return w;
} }
@ -577,7 +549,7 @@ Image Filter(const Image& img, ImageFilter9& filter)
ImageEncoder tgt; ImageEncoder tgt;
ImageRaster src(img); ImageRaster src(img);
Filter(tgt, src, filter); Filter(tgt, src, filter);
return WithResolution(tgt, img); return tgt;
} }
struct RGBAI { struct RGBAI {
@ -635,7 +607,7 @@ Image Sharpen(const Image& img, int amount)
ImageEncoder tgt; ImageEncoder tgt;
ImageRaster src(img); ImageRaster src(img);
Sharpen(tgt, src, amount); Sharpen(tgt, src, amount);
return WithResolution(tgt, img); return tgt;
} }
struct sEtchFilter : ImageFilter9 { struct sEtchFilter : ImageFilter9 {
@ -680,7 +652,6 @@ Image SetColorKeepAlpha(const Image& img, Color c)
} }
Premultiply(w); Premultiply(w);
w.SetHotSpots(img); w.SetHotSpots(img);
w.SetResolution(img.GetResolution());
return w; return w;
} }
@ -747,7 +718,6 @@ Image RotateClockwise(const Image& img)
Point p1 = img.GetHotSpot(); Point p1 = img.GetHotSpot();
Point p2 = img.Get2ndSpot(); Point p2 = img.Get2ndSpot();
SetNormalizedHotSpots(ib, sz.cy - p1.y - 1, p1.x, sz.cy - p2.y - 1, p2.x); SetNormalizedHotSpots(ib, sz.cy - p1.y - 1, p1.x, sz.cy - p2.y - 1, p2.x);
ib.SetResolution(img.GetResolution());
return ib; return ib;
} }
@ -762,7 +732,6 @@ Image RotateAntiClockwise(const Image& img)
Point p1 = img.GetHotSpot(); Point p1 = img.GetHotSpot();
Point p2 = img.Get2ndSpot(); Point p2 = img.Get2ndSpot();
SetNormalizedHotSpots(ib, p1.y, sz.cx - p1.x - 1, p2.y, sz.cx - p2.x - 1); SetNormalizedHotSpots(ib, p1.y, sz.cx - p1.x - 1, p2.y, sz.cx - p2.x - 1);
ib.SetResolution(img.GetResolution());
return ib; return ib;
} }
@ -776,7 +745,6 @@ Image Rotate180(const Image& orig)
Point p1 = orig.GetHotSpot(); Point p1 = orig.GetHotSpot();
Point p2 = orig.Get2ndSpot(); Point p2 = orig.Get2ndSpot();
SetNormalizedHotSpots(dest, sz.cy - p1.y - 1, sz.cx - p1.x - 1, sz.cy - p2.y - 1, sz.cx - p2.x - 1); SetNormalizedHotSpots(dest, sz.cy - p1.y - 1, sz.cx - p1.x - 1, sz.cy - p2.y - 1, sz.cx - p2.x - 1);
dest.SetResolution(dest.GetResolution());
return dest; return dest;
} }
@ -790,7 +758,6 @@ Image Transpose(const Image& img)
Point p1 = img.GetHotSpot(); Point p1 = img.GetHotSpot();
Point p2 = img.Get2ndSpot(); Point p2 = img.Get2ndSpot();
SetNormalizedHotSpots(ib, p1.y, p1.x, p2.y, p2.x); SetNormalizedHotSpots(ib, p1.y, p1.x, p2.y, p2.x);
ib.SetResolution(img.GetResolution());
return ib; return ib;
} }
@ -804,7 +771,6 @@ Image Transverse(const Image& img)
Point p1 = img.GetHotSpot(); Point p1 = img.GetHotSpot();
Point p2 = img.Get2ndSpot(); Point p2 = img.Get2ndSpot();
SetNormalizedHotSpots(ib, sz.cy - p1.y - 1, sz.cx - p1.x - 1, sz.cy - p2.y - 1, sz.cx - p2.x - 1); SetNormalizedHotSpots(ib, sz.cy - p1.y - 1, sz.cx - p1.x - 1, sz.cy - p2.y - 1, sz.cx - p2.x - 1);
ib.SetResolution(img.GetResolution());
return ib; return ib;
} }
@ -825,7 +791,6 @@ Image MirrorHorz(const Image& img)
Point p1 = img.GetHotSpot(); Point p1 = img.GetHotSpot();
Point p2 = img.Get2ndSpot(); Point p2 = img.Get2ndSpot();
SetNormalizedHotSpots(ib, sz.cx - p1.x - 1, p1.y, sz.cx - p2.x - 1, p2.y); SetNormalizedHotSpots(ib, sz.cx - p1.x - 1, p1.y, sz.cx - p2.x - 1, p2.y);
ib.SetResolution(img.GetResolution());
return ib; return ib;
} }
@ -847,7 +812,6 @@ Image MirrorVert(const Image& img)
Point p1 = img.GetHotSpot(); Point p1 = img.GetHotSpot();
Point p2 = img.Get2ndSpot(); Point p2 = img.Get2ndSpot();
SetNormalizedHotSpots(ib, p1.x, sz.cy - p1.y - 1, p2.x, sz.cy - p2.y - 1); SetNormalizedHotSpots(ib, p1.x, sz.cy - p1.y - 1, p2.x, sz.cy - p2.y - 1);
ib.SetResolution(img.GetResolution());
return ib; return ib;
} }
@ -910,7 +874,6 @@ Image Rotate(const Image& m, int angle)
*t++ = xs >= 0 && xs < isz.cx && ys >= 0 && ys < isz.cy ? m[ys][xs] : RGBAZero(); *t++ = xs >= 0 && xs < isz.cx && ys >= 0 && ys < isz.cy ? m[ys][xs] : RGBAZero();
} }
} }
ib.SetResolution(m.GetResolution());
return ib; return ib;
} }
@ -936,7 +899,6 @@ Image Dither(const Image& m, int dival)
int g = Grayscale(*s++) * 100 / dival; int g = Grayscale(*s++) * 100 / dival;
*t++ = g > dither[y & 7][x & 7] ? White() : Black(); *t++ = g > dither[y & 7][x & 7] ? White() : Black();
} }
ib.SetResolution(m.GetResolution());
return ib; return ib;
} }
@ -1069,7 +1031,6 @@ Image GaussianBlur(const Image& img, int radius, bool co)
DoColumn(i); DoColumn(i);
out.SetHotSpots(src); out.SetHotSpots(src);
out.SetResolution(src.GetResolution());
return out; return out;
}; };

View file

@ -7,10 +7,6 @@ Image WithHotSpots(const Image& m, Point hotspot, Point hotspot2 = Point(0, 0));
Image WithHotSpots(const Image& m, int x1, int y1, int x2, int y2); Image WithHotSpots(const Image& m, int x1, int y1, int x2, int y2);
Image WithHotSpot(const Image& m, int x1, int y1); Image WithHotSpot(const Image& m, int x1, int y1);
void SetResolution(Image& m, int res);
Image WithResolution(const Image& m, int res);
Image WithResolution(const Image& m, const Image& res);
void ScanOpaque(Image& m); void ScanOpaque(Image& m);
void DstSrcOp(ImageBuffer& dest, Point p, const Image& src, const Rect& srect, void DstSrcOp(ImageBuffer& dest, Point p, const Image& src, const Rect& srect,
void (*op)(RGBA *t, const RGBA *s, int n), bool co = false); void (*op)(RGBA *t, const RGBA *s, int n), bool co = false);
@ -244,10 +240,13 @@ Image CachedSetColorKeepAlpha(const Image& img, Color color);
Image CachedSetColorKeepAlphaPaintOnly(const Image& img, Color color); Image CachedSetColorKeepAlphaPaintOnly(const Image& img, Color color);
Image Magnify(const Image& img, const Rect& src, int nx, int ny, bool co); Image Magnify(const Image& img, const Rect& src, int nx, int ny, bool co);
Image Magnify(const Image& img, int nx, int ny); Image Magnify(const Image& img, int nx, int ny, bool co = false);
Image Minify(const Image& img, int nx, int ny, bool co = false); Image Minify(const Image& img, int nx, int ny, bool co = false);
Image MinifyCached(const Image& img, int nx, int ny, bool co = false); Image MinifyCached(const Image& img, int nx, int ny, bool co = false);
Image DownSample3x(const Image& src, bool co = false);
Image DownSample2x(const Image& src, bool co = false);
Image Upscale2x(const Image& src); Image Upscale2x(const Image& src);
Image Downscale2x(const Image& src); Image Downscale2x(const Image& src);
@ -255,7 +254,7 @@ void SetUHDMode(bool b = true);
bool IsUHDMode(); bool IsUHDMode();
void SyncUHDMode(); void SyncUHDMode();
Image DPI(const Image& m); // Image DPI(const Image& m);
Image DPI(const Image& img, int expected); Image DPI(const Image& img, int expected);
inline int DPI(int a) { return IsUHDMode() ? 2 * a : a; } inline int DPI(int a) { return IsUHDMode() ? 2 * a : a; }

View file

@ -9,10 +9,7 @@ Vector<ImageIml> UnpackImlDataUncompressed(const String& data)
while(s + 6 * 2 + 1 <= data.End()) { while(s + 6 * 2 + 1 <= data.End()) {
ImageIml& m = img.Add(); ImageIml& m = img.Add();
ImageBuffer ib(Peek16le(s + 1), Peek16le(s + 3)); ImageBuffer ib(Peek16le(s + 1), Peek16le(s + 3));
m.flags = byte(*s) & 0x3f; m.flags = byte(*s);
ib.SetResolution(decode(byte(*s) >> 6, 0, IMAGE_RESOLUTION_STANDARD,
1, IMAGE_RESOLUTION_UHD,
IMAGE_RESOLUTION_NONE));
ib.SetHotSpot(Point(Peek16le(s + 5), Peek16le(s + 7))); ib.SetHotSpot(Point(Peek16le(s + 5), Peek16le(s + 7)));
ib.Set2ndSpot(Point(Peek16le(s + 9), Peek16le(s + 11))); ib.Set2ndSpot(Point(Peek16le(s + 9), Peek16le(s + 11)));
s += 13; s += 13;
@ -97,9 +94,8 @@ ImageIml Iml::GetRaw(int mode, const String& id)
int ii = -1; int ii = -1;
if(mode == 0) if(mode == 0)
ii = map.Find(id); ii = map.Find(id);
else { else
ii = ex_name[mode - 1].Find(id); ii = ex_name[mode - 1].Find(id);
}
return ii >= 0 ? GetRaw(mode, ii) : ImageIml(); return ii >= 0 ? GetRaw(mode, ii) : ImageIml();
} }
@ -107,10 +103,16 @@ Image MakeImlImage(const String& id, Function<ImageIml(int, const String& id)> G
{ {
Image image; Image image;
int mode = IsUHDMode() * GUI_MODE_UHD + IsDarkTheme() * GUI_MODE_DARK; int mode = IsUHDMode() * GUI_MODE_UHD + IsDarkTheme() * GUI_MODE_DARK;
auto GetImg = [&](int mode, const String& id) {
ImageIml m = GetRaw(mode, id);
if(m.flags & IML_IMAGE_FLAG_S3)
m.image = DownSample3x(m.image);
return m;
};
if(mode == GUI_MODE_NORMAL) { if(mode == GUI_MODE_NORMAL) {
image = GetRaw(GUI_MODE_NORMAL, id).image; image = GetImg(GUI_MODE_NORMAL, id).image;
if(IsNull(image)) { if(IsNull(image)) {
ImageIml im = GetRaw(GUI_MODE_NORMAL, id + "__UHD"); ImageIml im = GetImg(GUI_MODE_NORMAL, id + "__UHD");
image = im.image; image = im.image;
if((im.flags & IML_IMAGE_FLAG_UHD) && !((im.flags | global_flags) & (IML_IMAGE_FLAG_FIXED|IML_IMAGE_FLAG_FIXED_SIZE))) if((im.flags & IML_IMAGE_FLAG_UHD) && !((im.flags | global_flags) & (IML_IMAGE_FLAG_FIXED|IML_IMAGE_FLAG_FIXED_SIZE)))
image = Downscale2x(image); image = Downscale2x(image);
@ -118,24 +120,24 @@ Image MakeImlImage(const String& id, Function<ImageIml(int, const String& id)> G
} }
else { else {
auto Mode = [&](dword m, const char *s) { return mode & m ? String(s) : String(); }; auto Mode = [&](dword m, const char *s) { return mode & m ? String(s) : String(); };
image = GetRaw(GUI_MODE_NORMAL, id + Mode(GUI_MODE_UHD, "__UHD") + Mode(GUI_MODE_DARK, "__DARK")).image; image = GetImg(GUI_MODE_NORMAL, id + Mode(GUI_MODE_UHD, "__UHD") + Mode(GUI_MODE_DARK, "__DARK")).image;
if(IsNull(image)) if(IsNull(image))
image = GetRaw(mode, id).image; // try to load from alternative iml image = GetImg(mode, id).image; // try to load from alternative iml
if(IsNull(image)) { // we do not have specific image for given mode, need to convert if(IsNull(image)) { // we do not have specific image for given mode, need to convert
ImageIml im; ImageIml im;
if(mode & GUI_MODE_UHD) { if(mode & GUI_MODE_UHD) {
im = GetRaw(GUI_MODE_NORMAL, id + "__UHD"); im = GetImg(GUI_MODE_NORMAL, id + "__UHD");
if(IsNull(im.image)) if(IsNull(im.image))
im = GetRaw(GUI_MODE_UHD, id); im = GetImg(GUI_MODE_UHD, id);
} }
if(IsNull(im.image)) if(IsNull(im.image))
if(mode & GUI_MODE_DARK) { if(mode & GUI_MODE_DARK) {
im = GetRaw(0, id + "__DARK"); im = GetImg(0, id + "__DARK");
if(IsNull(im.image)) if(IsNull(im.image))
im = GetRaw(GUI_MODE_DARK, id); im = GetImg(GUI_MODE_DARK, id);
} }
if(IsNull(im.image)) if(IsNull(im.image))
im = GetRaw(GUI_MODE_NORMAL, id); im = GetImg(GUI_MODE_NORMAL, id);
if((mode & GUI_MODE_UHD) && !(im.flags & IML_IMAGE_FLAG_UHD) && !((im.flags | global_flags) & (IML_IMAGE_FLAG_FIXED|IML_IMAGE_FLAG_FIXED_SIZE))) if((mode & GUI_MODE_UHD) && !(im.flags & IML_IMAGE_FLAG_UHD) && !((im.flags | global_flags) & (IML_IMAGE_FLAG_FIXED|IML_IMAGE_FLAG_FIXED_SIZE)))
im.image = Upscale2x(im.image); im.image = Upscale2x(im.image);
if((mode & GUI_MODE_DARK) && !(im.flags & IML_IMAGE_FLAG_DARK) && !((im.flags | global_flags) & (IML_IMAGE_FLAG_FIXED|IML_IMAGE_FLAG_FIXED_COLORS))) if((mode & GUI_MODE_DARK) && !(im.flags & IML_IMAGE_FLAG_DARK) && !((im.flags | global_flags) & (IML_IMAGE_FLAG_FIXED|IML_IMAGE_FLAG_FIXED_COLORS)))
@ -143,8 +145,6 @@ Image MakeImlImage(const String& id, Function<ImageIml(int, const String& id)> G
image = im.image; image = im.image;
} }
if(!IsNull(image) && (mode & GUI_MODE_UHD)) // this is to support legacy code mostly
SetResolution(image, IMAGE_RESOLUTION_UHD);
ScanOpaque(image); ScanOpaque(image);
} }
return image; return image;

View file

@ -204,15 +204,76 @@ Image Magnify(const Image& img, const Rect& src_, int nx, int ny, bool co)
q += ncx; q += ncx;
} }
}); });
b.SetResolution(img.GetResolution());
return b; return b;
} }
Image Magnify(const Image& img, int nx, int ny) Image Magnify(const Image& img, int nx, int ny, bool co)
{ {
if(nx == 1 && ny == 1) if(nx == 1 && ny == 1)
return img; return img;
return Magnify(img, img.GetSize(), nx, ny, false); return Magnify(img, img.GetSize(), nx, ny, co);
}
Image DownSample3x(const Image& src, bool co)
{
Size tsz = src.GetSize() / 3;
if(tsz.cx * tsz.cy == 0)
return Null;
ImageBuffer ib(tsz);
int w = src.GetSize().cx;
int w2 = 2 * w;
CoFor(co, tsz.cy, [&](int y) {
RGBA *t = ib[y];
RGBA *e = t + tsz.cx;
const RGBA *s = src[3 * y];
while(t < e) {
int r, g, b, a;
const RGBA *q;
r = g = b = a = 0;
#define S__SUM(delta) q = s + delta; r += q->r; g += q->g; b += q->b; a += q->a;
S__SUM(0) S__SUM(1) S__SUM(2)
S__SUM(w + 0) S__SUM(w + 1) S__SUM(w + 2)
S__SUM(w2 + 0) S__SUM(w2 + 1) S__SUM(w2 + 2)
#undef S__SUM
t->a = a / 9;
t->r = r / 9;
t->g = g / 9;
t->b = b / 9;
t++;
s += 3;
}
});
return ib;
}
Image DownSample2x(const Image& src, bool co)
{
Size tsz = src.GetSize() / 2;
if(tsz.cx * tsz.cy == 0)
return Null;
ImageBuffer ib(tsz);
int w = src.GetSize().cx;
CoFor(co, tsz.cy, [&](int y) {
RGBA *t = ib[y];
RGBA *e = t + tsz.cx;
const RGBA *s = src[2 * y];
while(t < e) {
int r, g, b, a;
const RGBA *q;
r = g = b = a = 0;
#define S__SUM(delta) q = s + delta; r += q->r; g += q->g; b += q->b; a += q->a;
S__SUM(0) S__SUM(1)
S__SUM(w + 0) S__SUM(w + 1)
#undef S__SUM
t->a = a / 4;
t->r = r / 4;
t->g = g / 4;
t->b = b / 4;
t++;
s += 2;
}
});
return ib;
} }
}; };

View file

@ -242,7 +242,6 @@ Image RescaleFilter(const Image& img, Size sz, const Rect& sr,
#endif #endif
} }
}); });
ib.SetResolution(img.GetResolution());
return ib; return ib;
} }

View file

@ -97,7 +97,6 @@ Image Upscale2x(const Image& src)
s = Filter(s, ef); s = Filter(s, ef);
} }
ImageBuffer h(s); ImageBuffer h(s);
h.SetResolution(IMAGE_RESOLUTION_UHD);
h.SetHotSpot(src.GetHotSpot() * 2); h.SetHotSpot(src.GetHotSpot() * 2);
h.Set2ndSpot(s2 * 2); h.Set2ndSpot(s2 * 2);
return h; return h;
@ -110,7 +109,6 @@ Image Downscale2x(const Image& src)
Size s2 = src.Get2ndSpot(); // see above... Size s2 = src.Get2ndSpot(); // see above...
Image m = RescaleFilter(src, src.GetSize() / 2, s2.cx > 0 || s2.cy > 0 ? FILTER_BILINEAR : FILTER_LANCZOS3); Image m = RescaleFilter(src, src.GetSize() / 2, s2.cx > 0 || s2.cy > 0 ? FILTER_BILINEAR : FILTER_LANCZOS3);
ImageBuffer h(m); ImageBuffer h(m);
h.SetResolution(IMAGE_RESOLUTION_STANDARD);
h.SetHotSpot(s2 / 2); h.SetHotSpot(s2 / 2);
h.Set2ndSpot(src.Get2ndSpot() / 2); h.Set2ndSpot(src.Get2ndSpot() / 2);
return h; return h;
@ -136,19 +134,6 @@ void SyncUHDMode()
SetUHDMode(uhd); SetUHDMode(uhd);
} }
Image DPI(const Image& img)
{
if(IsUHDMode()) {
if(img.GetResolution() == IMAGE_RESOLUTION_STANDARD)
return MakeImage(img, Upscale2x);
}
else {
if(img.GetResolution() == IMAGE_RESOLUTION_UHD)
return MakeImage(img, Downscale2x);
}
return img;
}
Image DPI(const Image& img, int expected) Image DPI(const Image& img, int expected)
{ {
if(img.GetSize().cy <= expected && IsUHDMode()) if(img.GetSize().cy <= expected && IsUHDMode())

View file

@ -114,9 +114,9 @@ is optimization hint that can save some memory in certain situations).&]
[* Magnify]([@(0.0.255) const] Image[@(0.0.255) `&] [*@3 img], [@(0.0.255) const] [* Magnify]([@(0.0.255) const] Image[@(0.0.255) `&] [*@3 img], [@(0.0.255) const]
Rect[@(0.0.255) `&] [*@3 src], [@(0.0.255) int] [*@3 nx], [@(0.0.255) int] Rect[@(0.0.255) `&] [*@3 src], [@(0.0.255) int] [*@3 nx], [@(0.0.255) int]
[*@3 ny], [@(0.0.255) bool] [*@3 co])&] [*@3 ny], [@(0.0.255) bool] [*@3 co])&]
[s5;:Upp`:`:Magnify`(const Upp`:`:Image`&`,int`,int`): [_^Upp`:`:Image^ Image]_[* Magnify [s5;:Upp`:`:Magnify`(const Image`&`,int`,int`,bool`): Image [* Magnify]([@(0.0.255) const
]([@(0.0.255) const]_[_^Upp`:`:Image^ Image][@(0.0.255) `&]_[*@3 img], ] Image[@(0.0.255) `&] [*@3 img], [@(0.0.255) int] [*@3 nx], [@(0.0.255) int]
[@(0.0.255) int]_[*@3 nx], [@(0.0.255) int]_[*@3 ny])&] [*@3 ny], [@(0.0.255) bool] [*@3 co] [@(0.0.255) `=] [@(0.0.255) false])&]
[s2;%% Multiplies the resolution of [%-*@3 img] by factors [%-*@3 nx] [s2;%% Multiplies the resolution of [%-*@3 img] by factors [%-*@3 nx]
and [%-*@3 ny] by simply repeating the pixels (each pixel becomes and [%-*@3 ny] by simply repeating the pixels (each pixel becomes
[%-*@3 nx] x [%-*@3 ny] same color block). If present in overload, [%-*@3 nx] x [%-*@3 ny] same color block). If present in overload,

View file

@ -33,23 +33,6 @@ onst]_[_^Image^ Image][@(0.0.255) `&]_[*@3 m], [@(0.0.255) int]_[*@3 x1],
[s2; [%% Returns ][*@3 m][%% with hotspot ][*@3 x1,][%% ][*@3 y1.]&] [s2; [%% Returns ][*@3 m][%% with hotspot ][*@3 x1,][%% ][*@3 y1.]&]
[s3; &] [s3; &]
[s4; &] [s4; &]
[s5;:Upp`:`:SetResolution`(Upp`:`:Image`&`,int`): [@(0.0.255) void]_[* SetResolution]([_^Upp`:`:Image^ I
mage][@(0.0.255) `&]_[*@3 m], [@(0.0.255) int]_[*@3 res])&]
[s2;%% Sets the resolution of [%-*@3 m] to [%-*@3 res].&]
[s3;%% &]
[s4; &]
[s5;:Upp`:`:WithResolution`(const Upp`:`:Image`&`,int`): [_^Upp`:`:Image^ Image]_[* WithR
esolution]([@(0.0.255) const]_[_^Upp`:`:Image^ Image][@(0.0.255) `&]_[*@3 m],
[@(0.0.255) int]_[*@3 res])&]
[s2;%% Returns [%-*@3 m] with resolution [%-*@3 res].&]
[s3;%% &]
[s4; &]
[s5;:Upp`:`:WithResolution`(const Upp`:`:Image`&`,const Upp`:`:Image`&`): [_^Upp`:`:Image^ I
mage]_[* WithResolution]([@(0.0.255) const]_[_^Upp`:`:Image^ Image][@(0.0.255) `&]_[*@3 m],
[@(0.0.255) const]_[_^Upp`:`:Image^ Image][@(0.0.255) `&]_[*@3 res])&]
[s2;%% Returns [%-*@3 m] with resolution equal to [%-*@3 res].GetResolution().&]
[s3; &]
[s4; &]
[s5;:CreateImage`(Size`,const RGBA`&`): [_^Image^ Image]_[* CreateImage]([_^Size^ Size]_[*@3 s [s5;:CreateImage`(Size`,const RGBA`&`): [_^Image^ Image]_[* CreateImage]([_^Size^ Size]_[*@3 s
z], [@(0.0.255) const]_[_^RGBA^ RGBA][@(0.0.255) `&]_[*@3 rgba])&] z], [@(0.0.255) const]_[_^RGBA^ RGBA][@(0.0.255) `&]_[*@3 rgba])&]
[s2;%% Creates a new Image with Size [%-*@3 sz] filled with color [%-*@3 rgba].&] [s2;%% Creates a new Image with Size [%-*@3 sz] filled with color [%-*@3 rgba].&]
@ -212,7 +195,7 @@ alpha.&]
[s5;:Equalight`(const Image`&`,int`): [_^Image^ Image]_[* Equalight]([@(0.0.255) const]_[_^Image^ I [s5;:Equalight`(const Image`&`,int`): [_^Image^ Image]_[* Equalight]([@(0.0.255) const]_[_^Image^ I
mage][@(0.0.255) `&]_[*@3 img], [@(0.0.255) int]_[*@3 thold]_`=_[@3 10])&] mage][@(0.0.255) `&]_[*@3 img], [@(0.0.255) int]_[*@3 thold]_`=_[@3 10])&]
[s2;%% [%-*@3 img] [%-*@3 thold].&] [s2;%% [%-*@3 img] [%-*@3 thold].&]
[s3;%% &] [s3; &]
[s4; &] [s4; &]
[s5;:Grayscale`(const Image`&`): [_^Image^ Image]_[* Grayscale]([@(0.0.255) const]_[_^Image^ I [s5;:Grayscale`(const Image`&`): [_^Image^ Image]_[* Grayscale]([@(0.0.255) const]_[_^Image^ I
mage][@(0.0.255) `&]_[*@3 img])&] mage][@(0.0.255) `&]_[*@3 img])&]

View file

@ -25,15 +25,6 @@ void IconDes::MaskSelection()
SyncShow(); SyncShow();
} }
IconDes::Slot::Slot()
{
pastepos = Null;
exp = false;
ImageBuffer b;
b.SetResolution(IMAGE_RESOLUTION_STANDARD);
image = b;
}
IconDes::Slot& IconDes::Current() IconDes::Slot& IconDes::Current()
{ {
if(ilist.IsCursor()) if(ilist.IsCursor())
@ -65,11 +56,11 @@ void IconDes::SyncShow()
iconshow.image.Clear(); iconshow.image.Clear();
if(IsCurrent()) { if(IsCurrent()) {
Slot& c = Current(); Slot& c = Current();
Image image = c.image; iconshow.image = c.image;
iconshow.image = image; iconshow.flags = c.flags;
iconshow.show_downscaled = show_downscaled; iconshow.show_downscaled = show_downscaled;
iconshow.show_synthetics = show_synthetics; iconshow.show_synthetics = show_synthetics;
ilist.Set(2, RawToValue(MakeTuple(image, c.flags))); ilist.Set(2, RawToValue(MakeTuple(c.image, c.flags)));
} }
iconshow.Refresh(); iconshow.Refresh();
} }
@ -211,7 +202,7 @@ void IconDes::EllipseTool0(Point p, dword flags, bool fill_empty)
DoTool( DoTool(
[&](IconDraw& iw) { [&](IconDraw& iw) {
iw.DrawEllipse(Rect(startpoint, p).Normalized(), fill_empty, iw.DrawEllipse(Rect(startpoint, p).Normalized(), fill_empty,
doselection ? CurrentColor() : RGBAZero(), pen, GrayColor(255)); doselection ? CurrentColor() : RGBAZero(), pen, CurrentColor());
}, },
[&](Painter& sw) { [&](Painter& sw) {
sw.DrawEllipse(Rect(startpoint, p).Normalized(), sw.DrawEllipse(Rect(startpoint, p).Normalized(),

View file

@ -95,6 +95,7 @@ struct IconShow : public Ctrl {
Image image; Image image;
bool show_downscaled; bool show_downscaled;
bool show_synthetics; bool show_synthetics;
dword flags;
void Paint(Draw& w); void Paint(Draw& w);
@ -107,8 +108,6 @@ void MirrorHorz(Image& img, const Rect& rect);
void MirrorVert(Image& img, const Rect& rect); void MirrorVert(Image& img, const Rect& rect);
String PackImlDataUncompressed(const Vector<ImageIml>& image); String PackImlDataUncompressed(const Vector<ImageIml>& image);
String PackImlData(const Vector<ImageIml>& image); String PackImlData(const Vector<ImageIml>& image);
Image DownSample3x(const Image& src, bool co = false);
Image DownSample2x(const Image& src, bool co = false);
struct IconDraw : DDARasterizer { struct IconDraw : DDARasterizer {
RGBA docolor; RGBA docolor;
@ -146,14 +145,12 @@ private:
Image image; Image image;
Image base_image; Image base_image;
Image selection; Image selection;
Point pastepos; Point pastepos = Null;
Image paste_image; Image paste_image;
String undo; String undo;
String redo; String redo;
bool exp; bool exp = false;
dword flags = 0; dword flags = 0;
Slot();
}; };
enum { enum {
@ -426,8 +423,6 @@ struct ImlImage : ImageIml {
bool LoadIml(const String& data, Array<ImlImage>& img, int& format); bool LoadIml(const String& data, Array<ImlImage>& img, int& format);
String SaveIml(const Array<ImlImage>& iml, int format, const String& eol = "\r\n"); String SaveIml(const Array<ImlImage>& iml, int format, const String& eol = "\r\n");
void SetRes(Image& m, int resolution);
} }
#endif #endif

View file

@ -1,4 +1,4 @@
LAYOUT(ImageLayout, 168, 208) LAYOUT(ImageLayout, 168, 232)
ITEM(Upp::Label, dv___0, SetLabel(t_("Name")).LeftPosZ(8, 40).TopPosZ(8, 19)) ITEM(Upp::Label, dv___0, SetLabel(t_("Name")).LeftPosZ(8, 40).TopPosZ(8, 19))
ITEM(Upp::EditString, name, LeftPosZ(52, 108).TopPosZ(8, 19)) ITEM(Upp::EditString, name, LeftPosZ(52, 108).TopPosZ(8, 19))
ITEM(Upp::Label, dv___2, SetLabel(t_("Size")).LeftPosZ(8, 40).TopPosZ(32, 19)) ITEM(Upp::Label, dv___2, SetLabel(t_("Size")).LeftPosZ(8, 40).TopPosZ(32, 19))
@ -10,9 +10,10 @@ LAYOUT(ImageLayout, 168, 208)
ITEM(Upp::Option, fixed_size, SetLabel(t_("Fixed size")).LeftPosZ(12, 156).TopPosZ(88, 16)) ITEM(Upp::Option, fixed_size, SetLabel(t_("Fixed size")).LeftPosZ(12, 156).TopPosZ(88, 16))
ITEM(Upp::Option, uhd, SetLabel(t_("UHD variant")).LeftPosZ(8, 156).TopPosZ(112, 16)) ITEM(Upp::Option, uhd, SetLabel(t_("UHD variant")).LeftPosZ(8, 156).TopPosZ(112, 16))
ITEM(Upp::Option, dark, SetLabel(t_("Dark variant")).LeftPosZ(8, 156).TopPosZ(128, 16)) ITEM(Upp::Option, dark, SetLabel(t_("Dark variant")).LeftPosZ(8, 156).TopPosZ(128, 16))
ITEM(Upp::Option, exp, SetLabel(t_("Export as icon.ico and .png")).LeftPosZ(8, 160).TopPosZ(152, 16)) ITEM(Upp::Option, s3, SetLabel(t_("Supersampled 3x")).LeftPosZ(8, 156).TopPosZ(152, 16))
ITEM(Upp::Button, ok, SetLabel(t_("OK")).LeftPosZ(28, 64).TopPosZ(176, 24)) ITEM(Upp::Option, exp, SetLabel(t_("Export as icon.ico and .png")).LeftPosZ(8, 160).TopPosZ(176, 16))
ITEM(Upp::Button, cancel, SetLabel(t_("Cancel")).LeftPosZ(96, 64).TopPosZ(176, 24)) ITEM(Upp::Button, ok, SetLabel(t_("OK")).LeftPosZ(28, 64).TopPosZ(200, 24))
ITEM(Upp::Button, cancel, SetLabel(t_("Cancel")).LeftPosZ(96, 64).TopPosZ(200, 24))
END_LAYOUT END_LAYOUT
LAYOUT(ImageSizeLayout, 168, 68) LAYOUT(ImageSizeLayout, 168, 68)

View file

@ -170,7 +170,6 @@ void IconDes::SmoothRescale()
for(;;) { for(;;) {
Size sz(minmax((int)~dlg.cx, 1, 9999), minmax((int)~dlg.cy, 1, 9999)); Size sz(minmax((int)~dlg.cx, 1, 9999), minmax((int)~dlg.cy, 1, 9999));
Image m = RescaleFilter(bk, sz, ~dlg.method); Image m = RescaleFilter(bk, sz, ~dlg.method);
SetRes(m, bk.GetResolution());
if(IsPasting()) { if(IsPasting()) {
c.paste_image = m; c.paste_image = m;
MakePaste(); MakePaste();

View file

@ -160,7 +160,7 @@ String PackImlDataUncompressed(const Vector<ImageIml>& image)
for(const ImageIml& m : image) { for(const ImageIml& m : image) {
const Image& img = m.image; const Image& img = m.image;
StringStream ss; StringStream ss;
ss.Put(((dword)img.GetResolution() << 6) | m.flags); ss.Put(m.flags);
Size sz = img.GetSize(); Size sz = img.GetSize();
ss.Put16le(sz.cx); ss.Put16le(sz.cx);
ss.Put16le(sz.cy); ss.Put16le(sz.cy);
@ -189,64 +189,4 @@ String PackImlData(const Vector<ImageIml>& image)
return ZCompress(PackImlDataUncompressed(image)); return ZCompress(PackImlDataUncompressed(image));
} }
Image DownSample3x(const Image& src, bool co)
{
Size tsz = src.GetSize() / 3;
ImageBuffer ib(tsz);
int w = src.GetSize().cx;
int w2 = 2 * w;
CoFor(co, tsz.cy, [&](int y) {
RGBA *t = ib[y];
RGBA *e = t + tsz.cx;
const RGBA *s = src[3 * y];
while(t < e) {
int r, g, b, a;
const RGBA *q;
r = g = b = a = 0;
#define S__SUM(delta) q = s + delta; r += q->r; g += q->g; b += q->b; a += q->a;
S__SUM(0) S__SUM(1) S__SUM(2)
S__SUM(w + 0) S__SUM(w + 1) S__SUM(w + 2)
S__SUM(w2 + 0) S__SUM(w2 + 1) S__SUM(w2 + 2)
#undef S__SUM
t->a = a / 9;
t->r = r / 9;
t->g = g / 9;
t->b = b / 9;
t++;
s += 3;
}
});
ib.SetResolution(src.GetResolution());
return ib;
}
Image DownSample2x(const Image& src, bool co)
{
Size tsz = src.GetSize() / 2;
ImageBuffer ib(tsz);
int w = src.GetSize().cx;
CoFor(co, tsz.cy, [&](int y) {
RGBA *t = ib[y];
RGBA *e = t + tsz.cx;
const RGBA *s = src[2 * y];
while(t < e) {
int r, g, b, a;
const RGBA *q;
r = g = b = a = 0;
#define S__SUM(delta) q = s + delta; r += q->r; g += q->g; b += q->b; a += q->a;
S__SUM(0) S__SUM(1)
S__SUM(w + 0) S__SUM(w + 1)
#undef S__SUM
t->a = a / 4;
t->r = r / 4;
t->g = g / 4;
t->b = b / 4;
t++;
s += 2;
}
});
ib.SetResolution(src.GetResolution());
return ib;
}
} }

View file

@ -295,106 +295,55 @@ static void PutOctalString(Stream& out, const char *b, const char *e, const Stri
String SaveIml(const Array<ImlImage>& iml, int format, const String& eol) { String SaveIml(const Array<ImlImage>& iml, int format, const String& eol) {
StringStream out; StringStream out;
if(format == 1) { out << "PREMULTIPLIED" << eol;
for(int i = 0; i < iml.GetCount(); i++) { Index<String> names;
const ImlImage& c = iml[i]; Index<String> saved_names;
if(c.exp) for(int i = 0; i < iml.GetCount(); i++) {
out << "IMAGE_META(\"exp\", \"\")" << eol; const ImlImage& c = iml[i];
String name = c.name; names.FindAdd(c.name);
Image buffer = c.image; out << "IMAGE_ID(" << c.name;
if(IsNull(name)) if((c.flags & (IML_IMAGE_FLAG_UHD|IML_IMAGE_FLAG_DARK)) == 0)
name = "im__" + IntStr(i); saved_names.FindAdd(c.name);
out.PutLine(Format("IMAGE_BEGIN(%s)", name)); if(c.flags & IML_IMAGE_FLAG_UHD)
int last = 0; out << "__UHD";
for(int i = 0; i < buffer.GetHeight(); i++) { if(c.flags & IML_IMAGE_FLAG_DARK)
String scan = PackRLE(buffer[i], buffer.GetWidth()); out << "__DARK";
if(!scan.IsEmpty() || i == 0) // force at least 1 scan out << ")";
{ if(c.exp)
for(; last < i; last++) out << " IMAGE_META(\"exp\", \"\")";
out.PutLine("\tIMAGE_SCAN(\"\")"); out << eol;
out.Put("\tIMAGE_SCAN("); }
PutOctalString(out, scan.Begin(), scan.End(), eol, true);
out << ")" << eol; for(String id : names) // allow UHD versions to be downscaled
last = i + 1; if(saved_names.Find(id) < 0)
} out << "IMAGE_ID(" << id << ")" << eol;
int ii = 0;
while(ii < iml.GetCount()) {
int bl = 0;
int bn = 0;
Vector<ImageIml> bimg;
while(bl < 4096 && ii < iml.GetCount()) {
const ImlImage& c = iml[ii++];
ImageIml& m = bimg.Add();
m.image = c.image;
m.flags = c.flags;
bl += (int)c.image.GetLength();
bn++;
}
String bs = PackImlData(bimg);
out << eol << "IMAGE_BEGIN_DATA" << eol;
bs.Cat(0, ((bs.GetCount() + 31) & ~31) - bs.GetCount());
const byte *s = bs;
for(int n = bs.GetCount() / 32; n--;) {
out << "IMAGE_DATA(";
for(int j = 0; j < 32; j++) {
if(j) out << ',';
out << (int)*s++;
} }
out.Put("IMAGE_PACKED(");
out.Put(name);
out.Put(", ");
StringStream datastrm;
Size size = buffer.GetSize();
Point hotspot = buffer.GetHotSpot();
int encoding = AlphaImageInfo::COLOR_RLE;
int version = 1;
datastrm / version;
datastrm % size % hotspot % encoding;
ASSERT(!datastrm.IsError());
String s = datastrm.GetResult();
PutOctalString(out, s.Begin(), s.End(), eol);
out << ")" << eol; out << ")" << eol;
} }
} out << "IMAGE_END_DATA(" << bs.GetCount() << ", " << bn << ")" << eol;
else {
out << "PREMULTIPLIED" << eol;
Index<String> std_name;
for(int i = 0; i < iml.GetCount(); i++) {
const ImlImage& c = iml[i];
if(c.image.GetResolution() == IMAGE_RESOLUTION_STANDARD)
std_name.Add(c.name);
}
Index<String> names;
Index<String> saved_names;
for(int i = 0; i < iml.GetCount(); i++) {
const ImlImage& c = iml[i];
names.FindAdd(c.name);
out << "IMAGE_ID(" << c.name;
if((c.flags & (IML_IMAGE_FLAG_UHD|IML_IMAGE_FLAG_DARK)) == 0)
saved_names.FindAdd(c.name);
if(c.flags & IML_IMAGE_FLAG_UHD)
out << "__UHD";
if(c.flags & IML_IMAGE_FLAG_DARK)
out << "__DARK";
out << ")";
if(c.exp)
out << " IMAGE_META(\"exp\", \"\")";
out << eol;
}
for(String id : names) // allow UHD versions to be downscaled
if(saved_names.Find(id) < 0)
out << "IMAGE_ID(" << id << ")" << eol;
int ii = 0;
while(ii < iml.GetCount()) {
int bl = 0;
int bn = 0;
Vector<ImageIml> bimg;
while(bl < 4096 && ii < iml.GetCount()) {
const ImlImage& c = iml[ii++];
ImageIml& m = bimg.Add();
m.image = c.image;
m.flags = c.flags;
if(c.flags & IML_IMAGE_FLAG_UHD)
SetResolution(m.image, IMAGE_RESOLUTION_UHD);
if(c.flags & (IML_IMAGE_FLAG_FIXED|IML_IMAGE_FLAG_FIXED_SIZE))
SetResolution(m.image, IMAGE_RESOLUTION_NONE);
bl += (int)c.image.GetLength();
bn++;
}
String bs = PackImlData(bimg);
out << eol << "IMAGE_BEGIN_DATA" << eol;
bs.Cat(0, ((bs.GetCount() + 31) & ~31) - bs.GetCount());
const byte *s = bs;
for(int n = bs.GetCount() / 32; n--;) {
out << "IMAGE_DATA(";
for(int j = 0; j < 32; j++) {
if(j) out << ',';
out << (int)*s++;
}
out << ")" << eol;
}
out << "IMAGE_END_DATA(" << bs.GetCount() << ", " << bn << ")" << eol;
}
} }
return out.GetResult(); return out.GetResult();
} }

View file

@ -19,6 +19,8 @@ String IconDes::FormatImageName(const Slot& c)
r << " HD"; r << " HD";
if(c.flags & IML_IMAGE_FLAG_DARK) if(c.flags & IML_IMAGE_FLAG_DARK)
r << " Dk"; r << " Dk";
if(c.flags & IML_IMAGE_FLAG_S3)
r << " S3";
if(c.exp) if(c.exp)
r << " X"; r << " X";
return r; return r;
@ -88,8 +90,11 @@ void IconDes::PrepareImageDlg(WithImageLayout<TopWindow>& dlg)
dlg.uhd <<= !!(flags & IML_IMAGE_FLAG_UHD); dlg.uhd <<= !!(flags & IML_IMAGE_FLAG_UHD);
dlg.dark <<= !!(flags & IML_IMAGE_FLAG_DARK); dlg.dark <<= !!(flags & IML_IMAGE_FLAG_DARK);
dlg.uhd ^= dlg.dark ^= dlg.exp ^= dlg.fixed_colors ^= dlg.fixed_size ^= dlg.fixed ^= dlg.name ^= dlg.s3 <<= !!(flags & IML_IMAGE_FLAG_S3);
[&] { dlg.Break(-1000); };
for(Ctrl& q : dlg)
if(dynamic_cast<Option *>(&q))
q << [&] { dlg.Break(-1000); };
} }
dlg.name.SetFilter(sCharFilterCid); dlg.name.SetFilter(sCharFilterCid);
} }
@ -114,6 +119,8 @@ dword IconDes::GetFlags(WithImageLayout<TopWindow>& dlg)
flags |= IML_IMAGE_FLAG_UHD; flags |= IML_IMAGE_FLAG_UHD;
if(dlg.dark) if(dlg.dark)
flags |= IML_IMAGE_FLAG_DARK; flags |= IML_IMAGE_FLAG_DARK;
if(dlg.s3)
flags |= IML_IMAGE_FLAG_S3;
return flags; return flags;
} }
@ -149,15 +156,6 @@ void IconDes::InsertRemoved(int q)
} }
} }
void SetRes(Image& m, int resolution)
{
ImageBuffer ib(m);
ib.SetResolution(findarg(resolution, IMAGE_RESOLUTION_STANDARD, IMAGE_RESOLUTION_UHD,
IMAGE_RESOLUTION_NONE)
>= 0 ? resolution : IMAGE_RESOLUTION_STANDARD);
m = ib;
}
IconDes::Slot& IconDes::ImageInsert(int ii, const String& name, const Image& m, bool exp) IconDes::Slot& IconDes::ImageInsert(int ii, const String& name, const Image& m, bool exp)
{ {
Slot& c = slot.Insert(ii); Slot& c = slot.Insert(ii);
@ -191,6 +189,7 @@ void IconDes::InsertImage()
} }
Image m = CreateImage(Size(~dlg.cx, ~dlg.cy), Null); Image m = CreateImage(Size(~dlg.cx, ~dlg.cy), Null);
ImageInsert(~dlg.name, m, dlg.exp).flags = GetFlags(dlg); ImageInsert(~dlg.name, m, dlg.exp).flags = GetFlags(dlg);
SyncList();
} }
void IconDes::Slice() void IconDes::Slice()
@ -224,6 +223,7 @@ void IconDes::Slice()
Image m = Crop(src, x, y, ~dlg.cx, ~dlg.cy); Image m = Crop(src, x, y, ~dlg.cx, ~dlg.cy);
ImageInsert(++ii, s + AsString(n++), m, ~dlg.exp).flags = GetFlags(dlg); ImageInsert(++ii, s + AsString(n++), m, ~dlg.exp).flags = GetFlags(dlg);
} }
SyncList();
} }
void IconDes::Duplicate() void IconDes::Duplicate()
@ -242,7 +242,6 @@ void IconDes::InsertPaste()
Exclamation("Clipboard does not contain an image."); Exclamation("Clipboard does not contain an image.");
return; return;
} }
SetRes(m, IMAGE_RESOLUTION_STANDARD);
ImageInsert("", m); ImageInsert("", m);
EditImage(); EditImage();
} }
@ -339,7 +338,6 @@ void IconDes::InsertFile()
id = '_' + id; id = '_' + id;
if(ii) if(ii)
id << "_" << ii; id << "_" << ii;
SetRes(m, IMAGE_RESOLUTION_STANDARD);
ImageInsert(id, m); ImageInsert(id, m);
ii++; ii++;
} }

View file

@ -11,6 +11,11 @@ void IconShow::Paint(Draw& w)
Size sz = GetSize(); Size sz = GetSize();
static Color color[] = { White(), Black(), WhiteGray(), LtGray(), Gray(), static Color color[] = { White(), Black(), WhiteGray(), LtGray(), Gray(),
Yellow(), Brown(), Red(), Green(), Blue(), Cyan(), Magenta() }; Yellow(), Brown(), Red(), Green(), Blue(), Cyan(), Magenta() };
Image image = this->image;
if(show_downscaled || show_synthetics)
if(flags & IML_IMAGE_FLAG_S3)
image = DownSample3x(image, true);
Size msz = image.GetSize(); Size msz = image.GetSize();
Size isz = msz; Size isz = msz;
int gap = DPI(8); int gap = DPI(8);
@ -21,14 +26,20 @@ void IconShow::Paint(Draw& w)
isz.cy += max(isz.cy, (isz.cy + 1) / 2 + (isz.cy + 2) / 3 + gap); isz.cy += max(isz.cy, (isz.cy + 1) / 2 + (isz.cy + 2) / 3 + gap);
} }
if(show_synthetics) { if(show_synthetics) {
isz.cx += 3 * isz.cx + gap; if(flags & IML_IMAGE_FLAG_UHD) {
isz.cy += 2 * isz.cy + gap; isz.cx += isz.cx + gap;
isz.cy += isz.cy + gap;
}
else {
isz.cx += 3 * isz.cx + gap;
isz.cy += 2 * isz.cy + gap;
}
} }
} }
int n = isz.cx ? clamp(sz.cx / isz.cx, 1, __countof(color)) : 1; int n = isz.cx ? clamp(sz.cx / isz.cx, 1, __countof(color)) : 1;
int ncx = sz.cx / n; int ncx = sz.cx / n;
Image m2, m3; Image m2, m3;
Image dk, up2, up2dk; Image dk, s2, s2dk;
if(fits) { if(fits) {
if(msz.cx && show_downscaled) { if(msz.cx && show_downscaled) {
m2 = DownSample2x(image); m2 = DownSample2x(image);
@ -36,8 +47,18 @@ void IconShow::Paint(Draw& w)
} }
if(show_synthetics) { if(show_synthetics) {
dk = DarkTheme(image); dk = DarkTheme(image);
up2 = Upscale2x(image); if(flags & IML_IMAGE_FLAG_UHD) {
up2dk = Upscale2x(DarkTheme(image)); s2 = Downscale2x(image);
s2dk = Downscale2x(DarkTheme(image));
if(IsUHDMode()) {
s2 = Magnify(s2, 2, 2, true);
s2dk = Magnify(s2dk, 2, 2, true);
}
}
else {
s2 = Upscale2x(image);
s2dk = Upscale2x(DarkTheme(image));
}
} }
} }
else else
@ -51,12 +72,12 @@ void IconShow::Paint(Draw& w)
Point pos(x + (cx - isz.cx) / 2, (sz.cy - isz.cy) / 2); Point pos(x + (cx - isz.cx) / 2, (sz.cy - isz.cy) / 2);
if(fits) { if(fits) {
if(show_synthetics) { if(show_synthetics) {
int x2 = pos.x + 2 * msz.cx + gap; int x2 = pos.x + msz.cx + gap;
w.DrawImage(pos.x, pos.y, image); w.DrawImage(pos.x, pos.y, image);
w.DrawImage(x2, pos.y, dk); w.DrawImage(x2, pos.y, dk);
pos.y += msz.cy + gap; pos.y += msz.cy + gap;
w.DrawImage(pos.x, pos.y, up2); w.DrawImage(pos.x, pos.y, s2);
w.DrawImage(x2, pos.y, up2dk); w.DrawImage(x2, pos.y, s2dk);
} }
else { else {
int y = pos.y + (isz.cy - msz.cy) / 2; int y = pos.y + (isz.cy - msz.cy) / 2;

View file

@ -63,7 +63,7 @@ void RichRuler::Paint(Draw& w)
for(i = marker.GetCount() - 1; i >= 0; --i) { for(i = marker.GetCount() - 1; i >= 0; --i) {
const Marker& m = marker[i]; const Marker& m = marker[i];
if(!IsNull(m.pos)) if(!IsNull(m.pos))
HotPaint(w, x0 + m.pos * zoom, m.top ? Zy(1) : sz.cy - Zy(4), DPI(m.image)); HotPaint(w, x0 + m.pos * zoom, m.top ? Zy(1) : sz.cy - Zy(4), m.image);
} }
i = 0; i = 0;
if(tabsize) if(tabsize)

View file

@ -73,7 +73,7 @@ void IdeIconDes::ToolEx(Bar& bar)
String name = GetCurrentName(); String name = GetCurrentName();
TheIde()->FindDesignerItemReferences(name + "()", name); TheIde()->FindDesignerItemReferences(name + "()", name);
}); });
bar.Add("File properties..", IconDesImg::FileProperties(), THISBACK(FileProperties)); // bar.Add("File properties..", IconDesImg::FileProperties(), THISBACK(FileProperties));
} }
} }

View file

@ -242,8 +242,6 @@ void Ide::InsertMenu(Bar& bar)
{ {
if(bar.IsScanKeys()) if(bar.IsScanKeys())
return; return;
bar.Add("Insert color..", THISBACK(InsertColor));
bar.Add("Insert .iml Image..", [=] { InsertImage(); });
int pi = GetPackageIndex(); int pi = GetPackageIndex();
const Workspace& wspc = IdeWorkspace(); const Workspace& wspc = IdeWorkspace();
if(pi >= 0 && pi < wspc.GetCount()) { if(pi >= 0 && pi < wspc.GetCount()) {
@ -273,6 +271,9 @@ void Ide::InsertMenu(Bar& bar)
} }
} }
} }
bar.Separator();
bar.Add("Insert color..", THISBACK(InsertColor));
bar.Add("Insert .iml Image..", [=] { InsertImage(); });
bar.Add("Insert file path..", THISBACK1(InsertFilePath, false)); bar.Add("Insert file path..", THISBACK1(InsertFilePath, false));
bar.Add("Insert file path as C string..", THISBACK1(InsertFilePath, true)); bar.Add("Insert file path as C string..", THISBACK1(InsertFilePath, true));
bar.Add("Insert clipboard as..", [=] { InsertAs(); }); bar.Add("Insert clipboard as..", [=] { InsertAs(); });

View file

@ -77,7 +77,6 @@ void WorkspaceWork::SyncErrorPackages()
break; break;
} }
} }
ff.icon = DPI(ff.icon);
package.Set(i, ff); package.Set(i, ff);
} }
} }

View file

@ -1,12 +1,10 @@
PREMULTIPLIED PREMULTIPLIED
IMAGE_ID(Icon) IMAGE_META("exp", "") IMAGE_ID(Icon) IMAGE_META("exp", "")
IMAGE_ID(IconBuilding) IMAGE_ID(IconBuilding)
IMAGE_ID(IconRunning)
IMAGE_ID(IconDebugging) IMAGE_ID(IconDebugging)
IMAGE_ID(IconRunning)
IMAGE_ID(PackageLarge2) IMAGE_ID(PackageLarge2)
IMAGE_ID(PackageLarge) IMAGE_META("exp", "") IMAGE_ID(PackageLarge) IMAGE_META("exp", "")
IMAGE_ID(IconBuildingLarge) IMAGE_ID(IconBuildingLarge)
IMAGE_ID(IconBuildingLarge2) IMAGE_ID(IconBuildingLarge2)
IMAGE_ID(IconRunningLarge) IMAGE_ID(IconRunningLarge)
@ -182,31 +180,32 @@ IMAGE_ID(GitHub__UHD)
IMAGE_ID(GitHub) IMAGE_ID(GitHub)
IMAGE_BEGIN_DATA IMAGE_BEGIN_DATA
IMAGE_DATA(120,156,237,152,139,109,235,48,12,69,141,78,208,17,50,106,182,232,58,65,23,227,123,78,42,135,150,200,75,234,199,32) IMAGE_DATA(120,156,237,152,129,113,195,32,12,69,125,153,160,35,100,212,108,145,117,114,93,76,173,211,226,200,32,125,9,3,242,229)
IMAGE_DATA(136,104,8,105,42,95,29,125,204,171,88,95,223,219,247,22,16,36,148,170,251,111,183,219,189,144,175,45,226,145,244,187) IMAGE_DATA(130,124,156,155,226,207,51,96,125,108,46,95,203,215,18,16,36,148,170,235,31,143,199,179,144,175,45,226,145,244,171,54)
IMAGE_DATA(54,233,247,216,255,135,245,219,189,108,127,186,123,73,223,255,127,94,175,215,58,61,185,244,210,248,158,90,146,235,185,62) IMAGE_DATA(233,215,88,255,135,245,203,179,44,255,186,103,73,191,127,207,183,219,173,78,79,46,189,212,191,151,150,228,122,174,79,99)
IMAGE_DATA(205,85,42,73,191,49,125,94,111,233,159,23,117,232,201,165,23,203,161,37,107,252,226,252,63,181,228,90,191,189,95,123) IMAGE_DATA(149,74,210,47,76,159,215,91,250,215,65,13,122,114,233,197,178,105,201,234,191,56,254,47,45,185,230,111,189,175,181,254)
IMAGE_DATA(253,243,158,135,54,245,247,92,87,234,203,66,249,120,189,185,160,205,201,240,248,90,102,48,215,12,92,23,26,187,158,252) IMAGE_DATA(117,205,159,54,221,239,190,174,212,151,133,242,254,122,115,65,27,147,238,113,153,102,48,214,12,92,7,234,187,158,252,121)
IMAGE_DATA(121,253,161,63,37,26,211,159,146,163,81,207,63,103,241,181,241,59,249,229,252,219,252,98,253,146,25,56,231,191,208,159) IMAGE_DATA(253,166,223,37,26,211,239,146,227,160,158,159,71,241,181,254,59,249,229,248,219,252,98,254,146,25,56,199,191,208,239,234)
IMAGE_DATA(234,235,214,95,138,101,6,188,44,51,128,15,163,43,25,31,227,160,102,125,218,158,247,191,143,157,209,169,79,58,254,169) IMAGE_DATA(235,230,95,138,105,6,188,188,171,25,184,12,193,26,43,244,64,26,201,152,39,100,90,153,155,244,188,141,26,253,54,34)
IMAGE_DATA(233,209,248,121,31,148,254,151,243,111,143,191,88,191,101,6,243,226,99,205,192,101,8,214,92,161,7,210,72,198,194,16) IMAGE_DATA(172,13,203,12,242,254,219,124,121,252,113,255,139,249,219,189,25,216,227,95,232,139,107,166,25,108,241,177,102,224,58,80)
IMAGE_DATA(168,206,12,68,61,193,100,212,245,199,140,176,54,44,51,200,199,111,243,229,249,199,227,47,214,239,244,154,96,207,127,161) IMAGE_DATA(223,125,43,147,154,140,185,158,242,215,236,10,125,202,196,245,111,33,81,160,62,233,248,89,211,163,254,243,123,80,238,191)
IMAGE_DATA(47,238,121,7,51,184,108,151,25,237,126,74,224,93,99,226,194,37,126,158,120,220,52,169,159,111,142,13,177,21,227,174) IMAGE_DATA(28,127,187,255,197,252,125,228,155,193,117,185,142,104,247,83,2,63,40,3,39,46,241,243,85,152,155,38,181,243,205,190)
IMAGE_DATA(153,23,66,33,241,57,155,27,63,15,176,9,40,252,194,198,142,77,1,177,249,198,193,11,216,68,154,249,18,59,138,175) IMAGE_DATA(33,182,98,220,53,227,66,40,36,62,103,115,227,231,1,22,1,133,95,188,211,108,139,2,98,243,133,131,23,176,136,28)
IMAGE_DATA(177,35,248,136,29,206,215,238,137,224,75,245,237,124,175,175,97,54,218,68,177,15,168,190,38,157,133,170,108,33,71,197) IMAGE_DATA(230,75,236,40,190,198,142,224,35,118,56,95,187,38,130,47,213,31,231,123,125,13,179,173,133,84,247,1,213,215,164,189)
IMAGE_DATA(243,204,129,124,97,163,15,227,151,151,236,145,51,248,34,59,136,175,178,3,248,144,29,206,207,217,145,124,137,221,206,119) IMAGE_DATA(80,149,45,228,168,184,159,217,145,47,44,244,97,252,242,144,61,114,4,95,100,7,241,85,118,0,31,178,195,249,57,59)
IMAGE_DATA(23,200,166,86,255,57,250,97,249,47,102,211,116,255,71,108,205,163,166,240,5,118,24,95,97,143,224,239,109,164,151,194) IMAGE_DATA(146,47,177,143,243,221,5,178,233,168,255,108,247,97,249,47,102,211,112,255,71,108,205,163,134,240,5,118,24,95,97,247)
IMAGE_DATA(188,60,218,208,217,137,175,107,109,190,93,116,54,203,175,218,231,222,27,144,13,242,123,84,244,230,247,10,22,191,235,48) IMAGE_DATA(224,175,109,164,15,223,188,252,181,161,179,19,95,215,218,124,187,232,108,150,95,181,207,189,55,32,27,228,119,175,104,205)
IMAGE_DATA(160,43,94,253,48,170,73,152,178,180,147,111,142,13,177,169,127,94,8,133,196,207,221,89,106,163,194,164,204,205,8,177) IMAGE_DATA(239,25,44,190,231,102,64,83,156,253,48,170,73,152,178,180,145,111,246,13,177,169,125,92,8,133,196,207,221,89,106,163)
IMAGE_DATA(211,61,51,55,67,196,142,226,107,236,8,62,98,135,243,181,123,34,248,82,125,59,223,235,107,152,77,238,118,10,126,237) IMAGE_DATA(194,164,204,197,8,177,211,53,35,23,67,196,142,226,107,236,8,62,98,135,243,181,107,34,248,82,253,113,190,215,215,48)
IMAGE_DATA(203,168,200,22,114,116,198,203,168,202,14,230,151,151,236,145,51,248,34,59,136,175,178,3,248,144,29,206,207,217,145,124) IMAGE_DATA(155,220,237,20,252,218,143,81,145,45,228,232,136,143,81,149,29,204,47,15,217,35,71,240,69,118,16,95,101,7,240,33)
IMAGE_DATA(137,221,206,119,23,200,166,86,255,57,250,97,249,47,102,211,116,255,71,108,205,163,214,97,128,159,191,183,177,14,3,80) IMAGE_DATA(59,156,159,179,35,249,18,251,56,223,93,32,155,142,250,207,118,31,150,255,98,54,13,247,127,196,214,60,106,110,6,248)
IMAGE_DATA(255,116,54,200,239,81,209,155,223,43,88,172,195,128,190,120,245,195,168,38,97,202,210,78,190,57,54,196,166,254,121,33) IMAGE_DATA(249,107,27,115,51,0,221,159,206,6,249,221,43,90,243,123,6,139,185,25,208,22,103,63,140,106,18,166,44,109,228,155)
IMAGE_DATA(20,18,63,119,103,169,141,10,147,50,55,35,196,78,247,204,220,12,17,59,138,175,177,35,248,136,61,139,63,236,234,225) IMAGE_DATA(125,67,108,106,31,23,66,33,241,115,119,150,218,168,48,41,115,49,66,236,116,205,200,197,16,177,163,248,26,59,130,143)
IMAGE_DATA(251,189,71,46,152,239,209,142,224,107,235,128,95,32,6,241,91,95,134,52,126,190,78,63,63,151,151,242,97,31,38,242) IMAGE_DATA(216,163,248,221,142,22,190,223,123,228,130,249,30,109,15,190,54,15,248,3,162,19,255,232,199,144,198,207,231,233,126,191)
IMAGE_DATA(181,239,175,224,191,98,252,197,11,203,135,241,71,204,63,44,131,158,63,246,93,139,42,255,173,205,63,192,29,194,183,252) IMAGE_DATA(158,202,135,247,48,144,175,253,62,131,127,70,255,139,15,150,15,227,247,24,127,88,58,61,127,236,183,22,85,254,91,155)
IMAGE_DATA(103,52,191,170,188,9,95,58,12,136,228,171,218,17,87,127,208,246,247,179,107,29,6,188,127,252,3,73,119,236,15,0) IMAGE_DATA(127,128,219,133,111,249,79,111,126,85,121,19,190,180,25,16,201,87,181,61,142,246,160,229,255,181,107,110,6,188,127,252)
IMAGE_END_DATA(768, 7) IMAGE_DATA(0,159,212,236,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
IMAGE_END_DATA(800, 7)
IMAGE_BEGIN_DATA IMAGE_BEGIN_DATA
IMAGE_DATA(120,156,237,154,237,141,131,48,12,134,163,78,194,116,204,193,22,93,7,221,98,57,81,21,41,23,217,198,224,143,8,238) IMAGE_DATA(120,156,237,154,237,141,131,48,12,134,163,78,194,116,204,193,22,93,7,221,98,57,81,21,41,23,217,198,224,143,8,238)