From 19dd6c72f10b0ed55f0d6a4f15744de1f2aca481 Mon Sep 17 00:00:00 2001 From: Mirek Fidler Date: Sat, 13 Jul 2024 18:58:30 +0200 Subject: [PATCH] Core: Unaligned access reimplemented with memcpy, Draw, ide: iml improvements --- autotest/Mem/Mem.cpp | 1 - autotest/StringTest/StringTest.cpp | 12 ++ uppsrc/Core/Mem.cpp | 24 ++-- uppsrc/Core/Mem.h | 96 ++++++++++----- uppsrc/Core/Ops.h | 87 ++++++-------- uppsrc/CtrlLib/FileSel.cpp | 6 +- uppsrc/Draw/Image.cpp | 11 -- uppsrc/Draw/Image.h | 12 +- uppsrc/Draw/ImageOp.cpp | 47 +------- uppsrc/Draw/ImageOp.h | 11 +- uppsrc/Draw/Iml.cpp | 34 +++--- uppsrc/Draw/Mify.cpp | 67 ++++++++++- uppsrc/Draw/RescaleFilter.cpp | 1 - uppsrc/Draw/Uhd.cpp | 15 --- uppsrc/Draw/src.tpp/ImageMaker_en-us.tpp | 6 +- uppsrc/Draw/src.tpp/ImageOp_en-us.tpp | 19 +-- uppsrc/IconDes/IconDes.cpp | 17 +-- uppsrc/IconDes/IconDes.h | 11 +- uppsrc/IconDes/IconDes.lay | 9 +- uppsrc/IconDes/Image.cpp | 1 - uppsrc/IconDes/ImageOp.cpp | 62 +--------- uppsrc/IconDes/ImlFile.cpp | 143 ++++++++--------------- uppsrc/IconDes/List.cpp | 24 ++-- uppsrc/IconDes/Paint.cpp | 37 ++++-- uppsrc/RichEdit/Ruler.cpp | 2 +- uppsrc/ide/IconDes/IconDes.cpp | 2 +- uppsrc/ide/Insert.cpp | 5 +- uppsrc/ide/UppWspc.cpp | 1 - uppsrc/ide/ide.iml | 55 +++++---- 29 files changed, 352 insertions(+), 466 deletions(-) diff --git a/autotest/Mem/Mem.cpp b/autotest/Mem/Mem.cpp index 662801d79..904cb87d8 100644 --- a/autotest/Mem/Mem.cpp +++ b/autotest/Mem/Mem.cpp @@ -201,7 +201,6 @@ CONSOLE_APP_MAIN CheckFill(memset64); CheckFill(memset128); - struct dqword { qword x[2]; }; CheckCopy(memcpy8); CheckCopy(memcpy16); CheckCopy(memcpy32); diff --git a/autotest/StringTest/StringTest.cpp b/autotest/StringTest/StringTest.cpp index eba7b610d..2b1175161 100644 --- a/autotest/StringTest/StringTest.cpp +++ b/autotest/StringTest/StringTest.cpp @@ -133,5 +133,17 @@ CONSOLE_APP_MAIN 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"); } diff --git a/uppsrc/Core/Mem.cpp b/uppsrc/Core/Mem.cpp index 006ca5952..10762a3cf 100644 --- a/uppsrc/Core/Mem.cpp +++ b/uppsrc/Core/Mem.cpp @@ -108,10 +108,10 @@ hash_t memhash(const void *ptr, size_t len) uint64 val1, val2, val3, val4; val1 = val2 = val3 = val4 = HASH_CONST1; while(len >= 32) { - val1 = HASH_CONST2 * val1 + *(qword *)(s); - val2 = HASH_CONST2 * val2 + *(qword *)(s + 8); - val3 = HASH_CONST2 * val3 + *(qword *)(s + 16); - val4 = HASH_CONST2 * val4 + *(qword *)(s + 24); + val1 = HASH_CONST2 * val1 + Peek64(s); + val2 = HASH_CONST2 * val2 + Peek64(s + 8); + val3 = HASH_CONST2 * val3 + Peek64(s + 16); + val4 = HASH_CONST2 * val4 + Peek64(s + 24); s += 32; len -= 32; } @@ -122,19 +122,19 @@ hash_t memhash(const void *ptr, size_t len) } const byte *e = s + len - 8; while(s < e) { - val = HASH_CONST2 * val + *(qword *)(s); + val = HASH_CONST2 * val + Peek64(s); s += 8; } - return HASH_CONST2 * val + *(qword *)(e); + return HASH_CONST2 * val + Peek64(e); } if(len > 4) { - val = HASH_CONST2 * val + *(dword *)(s); - val = HASH_CONST2 * val + *(dword *)(s + len - 4); + val = HASH_CONST2 * val + Peek32(s); + val = HASH_CONST2 * val + Peek32(s + len - 4); return val; } if(len >= 2) { - val = HASH_CONST2 * val + *(word *)(s); - val = HASH_CONST2 * val + *(word *)(s + len - 2); + val = HASH_CONST2 * val + Peek16(s); + val = HASH_CONST2 * val + Peek16(s + len - 2); return 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); } if(len >= 2) { - val = HASH_CONST2 * val + *(word *)(s); - val = HASH_CONST2 * val + *(word *)(s + len - 2); + val = HASH_CONST2 * val + Peek16(s); + val = HASH_CONST2 * val + Peek16(s + len - 2); return val; } return len ? HASH_CONST2 * val + *s : val; diff --git a/uppsrc/Core/Mem.h b/uppsrc/Core/Mem.h index dfcf87c0b..6f49e9998 100644 --- a/uppsrc/Core/Mem.h +++ b/uppsrc/Core/Mem.h @@ -2,6 +2,36 @@ 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 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; if(count <= 4) { - *(word *)t = *(word *)(t + count - 2) = (word)val4; + Set2__(t, val4); + Set2__(t + count - 2, val4); return; } if(count > 16) { memset8__(t, i32all(val4), count); return; } - *(dword *)t = *(dword *)(t + count - 4) = val4; - if(count > 8) - *(dword *)(t + 4) = *(dword *)(t + count - 8) = val4; + Set4__(t, val4); + Set4__(t + count - 4, val4); + if(count > 8) { + Set4__(t + 4, val4); + Set4__(t + count - 8, val4); + } } inline @@ -31,7 +65,7 @@ void memset16(void *p, word data, size_t count) word *t = (word *)p; if(count < 2) { if(count) - t[0] = data; + Set2__(t, data); return; } dword val4 = 0x10001 * data; @@ -39,18 +73,18 @@ void memset16(void *p, word data, size_t count) memset8__(t, i32all(val4), 2 * count); return; } - *(dword *)(t + count - 2) = val4; + Set4__(t + count - 2, val4); if(count & 8) { i32all(val4).Store(t); t += 8; } if(count & 4) { - *(dword *)t = val4; - *(dword *)(t + 2) = val4; + Set4__(t, val4); + Set4__(t + 2, val4); t += 4; } if(count & 2) - *(dword *)t = val4; + Set4__(t, val4); } inline @@ -59,11 +93,13 @@ void memset32(void *p, dword data, size_t count) dword *t = (dword *)p; if(count < 4) { if(count & 2) { - t[0] = t[1] = t[count - 1] = data; + Set4__(t, data); + Set4__(t + 1, data); + Set4__(t + count - 1, data); return; } if(count & 1) - t[0] = data; + Set4__(t, data); return; } i32x4 val4 = i32all(data); @@ -87,7 +123,7 @@ void memset64(void *p, qword data, size_t count) qword *t = (qword *)p; if(count < 2) { if(count) - t[0] = data; + Set8__(t, data); return; } i16x8 val2 = i64all(data); @@ -125,18 +161,18 @@ void memcpy8(void *p, const void *q, size_t count) t[0] = s[0]; return; } - *(word *)t = *(word *)s; - *(word *)(t + count - 2) = *(word *)(s + count - 2); + Cpy2__(t, s); + Cpy2__(t + count - 2, s + count - 2); return; } if(count <= 16) { if(count <= 8) { - *(dword *)(t) = *(dword *)(s); - *(dword *)(t + count - 4) = *(dword *)(s + count - 4); + Cpy4__(t, s); + Cpy4__(t + count - 4, s + count - 4); return; } - *(uint64 *)t = *(uint64 *)s; - *(uint64 *)(t + count - 8) = *(uint64 *)(s + count - 8); + Cpy8__(t, s); + Cpy8__(t + count - 8, s + count - 8); return; } 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 < 2) { if(count) - t[0] = s[0]; + Cpy2__(t, s); return; } - *(dword *)t = *(dword *)s; - *(dword *)(t + count - 2) = *(dword *)(s + count - 2); + Cpy4__(t, s); + Cpy4__(t + count - 2, s + count - 2); return; } if(count <= 16) { if(count <= 8) { - *(uint64 *)(t) = *(uint64 *)(s); - *(uint64 *)(t + count - 4) = *(uint64 *)(s + count - 4); + Cpy8__(t, s); + Cpy8__(t + count - 4, s + count - 4); return; } 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) { if(count > 1) { - *(int64 *)t = *(int64 *)s; - *(int64 *)(t + count - 2) = *(int64 *)(s + count - 2); + Cpy8__(t, s); + Cpy8__(t + count - 2, s + count - 2); return; } *t = *s; @@ -200,9 +236,9 @@ void memcpy32(void *p, const void *q, size_t count) if(count < 4) { if(count) { if(count > 1) { - t[0] = s[0]; - t[1] = s[1]; - t[count - 1] = s[count - 1]; + Cpy4__(t, s); + Cpy4__(t + 1, s + 1); + Cpy4__(t + count - 1, s + count - 1); return; } *t = *s; @@ -236,8 +272,8 @@ void memcpy64(void *p, const void *q, size_t count) if(count <= 2) { if(count) { if(count > 1) { - *(int64 *)t = *(int64 *)s; - *(int64 *)(t + count - 1) = *(int64 *)(s + count - 1); + Cpy8__(t, s); + Cpy8__(t + count - 1, s + count - 1); return; } *t = *s; diff --git a/uppsrc/Core/Ops.h b/uppsrc/Core/Ops.h index ef40bbad2..db0f63b77 100644 --- a/uppsrc/Core/Ops.h +++ b/uppsrc/Core/Ops.h @@ -1,60 +1,9 @@ -#if defined(CPU_UNALIGNED) && defined(CPU_LE) -NOUBSAN inline int Peek16le(const void *ptr) { return *(const word *)ptr; } -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); } - +#ifndef CPU_LE +#error Only little endian CPUs supported #endif #if defined(CPU_X86) && defined(COMPILER_MSC) + #ifdef COMPILER_GCC #ifdef CPU_64 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(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 #define HASH64 diff --git a/uppsrc/CtrlLib/FileSel.cpp b/uppsrc/CtrlLib/FileSel.cpp index 87fcbc8d1..238dbc482 100644 --- a/uppsrc/CtrlLib/FileSel.cpp +++ b/uppsrc/CtrlLib/FileSel.cpp @@ -1729,7 +1729,7 @@ Image GetDirIcon(const String& s) #endif if(IsNull(img)) img = CtrlImg::Dir(); - return DPI(img); + return img; } 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; places.Insert(row); places.Set(row, 0, path); - places.Set(row, 1, DPI(m)); + places.Set(row, 1, m); places.Set(row, 2, name); places.Set(row, 3, group); 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) { if(path.GetCount()) - AddPlaceRaw(NormalizePath(path), DPI(m), name, group, row); + AddPlaceRaw(NormalizePath(path), m, name, group, row); return *this; } diff --git a/uppsrc/Draw/Image.cpp b/uppsrc/Draw/Image.cpp index c58efdd56..89fc4b197 100644 --- a/uppsrc/Draw/Image.cpp +++ b/uppsrc/Draw/Image.cpp @@ -54,7 +54,6 @@ void ImageBuffer::InitAttrs() { spot2 = hotspot = Point(0, 0); dots = Size(0, 0); - resolution = IMAGE_RESOLUTION_NONE; paintonce = false; } @@ -63,7 +62,6 @@ void ImageBuffer::CopyAttrs(const ImageBuffer& img) SetHotSpot(img.GetHotSpot()); Set2ndSpot(img.Get2ndSpot()); SetDots(img.GetDots()); - SetResolution(img.GetResolution()); 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); } -int Image::GetResolution() const -{ - return data ? data->buffer.GetResolution() : IMAGE_RESOLUTION_NONE; -} - int Image::GetKindNoScan() const { return data ? data->buffer.GetKind() : IMAGE_ALPHA; @@ -282,7 +275,6 @@ bool Image::operator==(const Image& img) const GetHotSpot() == img.GetHotSpot() && Get2ndSpot() == img.Get2ndSpot() && GetDots() == img.GetDots() && - GetResolution() == img.GetResolution() && memeq_t(~*this, ~img, GetLength()); } @@ -397,7 +389,6 @@ String StoreImageAsString(const Image& img) if(img.GetKind() == IMAGE_EMPTY) return Null; int type = img.GetKind() == IMAGE_OPAQUE ? 3 : 4; - type |= decode(img.GetResolution(), IMAGE_RESOLUTION_STANDARD, 0x40, IMAGE_RESOLUTION_UHD, 0x80, 0); StringStream ss; ss.Put(type); Size sz = img.GetSize(); @@ -439,7 +430,6 @@ Image LoadImageFromString(const String& src) return Null; StringStream ss(src); int type = ss.Get(); - int resolution = decode(type & 0xc0, 0x40, IMAGE_RESOLUTION_STANDARD, 0x80, IMAGE_RESOLUTION_UHD, 0); type &= 0x3f; Size sz; sz.cx = ss.Get16le(); @@ -464,7 +454,6 @@ Image LoadImageFromString(const String& src) ImageBuffer ib(sz); ib.SetHotSpot(p); ib.SetDots(dots); - ib.SetResolution(resolution); RGBA *t = ib; const RGBA *e = t + ib.GetLength(); const byte *s = data; diff --git a/uppsrc/Draw/Image.h b/uppsrc/Draw/Image.h index bba473af3..2d63a4758 100644 --- a/uppsrc/Draw/Image.h +++ b/uppsrc/Draw/Image.h @@ -42,12 +42,6 @@ inline byte Saturate255(int x) { return byte(~(x >> 24) & (x | (-(x class Image; -enum ImageResolutionIntent { - IMAGE_RESOLUTION_NONE = -1, - IMAGE_RESOLUTION_STANDARD = 0, - IMAGE_RESOLUTION_UHD = 1, -}; - class ImageBuffer : NoCopy { std::atomic kind; // atomic because it can be set by 2 threads, in theory Size size; @@ -55,7 +49,6 @@ class ImageBuffer : NoCopy { Point hotspot; Point spot2; Size dots; - int8 resolution; bool paintonce = false; void Set(Image& img); @@ -86,9 +79,6 @@ public: void SetDPI(Size sz); Size GetDPI(); - void SetResolution(int i) { resolution = i; } - int GetResolution() const { return resolution; } - void CopyAttrs(const ImageBuffer& img); void CopyAttrs(const Image& img); @@ -178,7 +168,6 @@ public: Size GetDPI() const; int GetKindNoScan() const; int GetKind() const; - int GetResolution() const; bool IsOpaque() const { return GetKind() == IMAGE_OPAQUE; } const RGBA *Begin() const { return data ? ~data->buffer : NULL; } @@ -274,6 +263,7 @@ enum { IML_IMAGE_FLAG_FIXED_SIZE = 0x4, IML_IMAGE_FLAG_UHD = 0x8, IML_IMAGE_FLAG_DARK = 0x10, + IML_IMAGE_FLAG_S3 = 0x20, }; Image MakeImlImage(const String& id, Function GetRaw, dword global_flags); diff --git a/uppsrc/Draw/ImageOp.cpp b/uppsrc/Draw/ImageOp.cpp index a15948d30..dd5af9f06 100644 --- a/uppsrc/Draw/ImageOp.cpp +++ b/uppsrc/Draw/ImageOp.cpp @@ -30,25 +30,6 @@ Image WithHotSpot(const Image& m, int x1, int y1) 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) { 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 (*op)(RGBA *t, const RGBA *s, int n), bool co) { - dest.SetResolution(src.GetResolution()); Rect sr = srect; Size sz = DstSrc(dest, p, src, sr); if(sz.cx > 0) { @@ -193,7 +173,7 @@ Image Crop(const Image& img, const Rect& rc) ImageRaster src(img); ImageEncoder tgt; 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) @@ -274,7 +254,6 @@ void ClampHotSpots(Image& m) Image ColorMask(const Image& src, Color key) { ImageBuffer ib(src.GetSize()); - ib.SetResolution(src.GetResolution()); const RGBA *s = src; const RGBA *e = src + src.GetLength(); RGBA *t = ~ib; @@ -313,7 +292,7 @@ Image CanvasSize(const Image& img, int cx, int cy) ImageRaster src(img); ImageEncoder tgt; CanvasSize(tgt, src, cx, cy); - return WithResolution(tgt, img); + return tgt; } Image AssignAlpha(const Image& img, const Image& alpha) @@ -334,7 +313,6 @@ Image AssignAlpha(const Image& img, const Image& alpha) } } ib.SetHotSpots(img); - ib.SetResolution(img.GetResolution()); return ib; } @@ -378,7 +356,6 @@ Image Equalight(const Image& img, int thold) t++; } w.SetHotSpots(img); - w.SetResolution(img.GetResolution()); return w; } @@ -398,7 +375,6 @@ Image Grayscale(const Image& img) s++; } w.SetHotSpots(img); - w.SetResolution(img.GetResolution()); return w; } @@ -419,7 +395,6 @@ Image Grayscale(const Image& img, int amount) s++; } w.SetHotSpots(img); - w.SetResolution(img.GetResolution()); return w; } @@ -446,7 +421,6 @@ Image Colorize(const Image& img, Color color, int alpha) } Premultiply(w); w.SetHotSpots(img); - w.SetResolution(img.GetResolution()); return w; } @@ -474,7 +448,6 @@ Image DarkTheme(const Image& img) Premultiply(ib); ib.SetHotSpots(img); - ib.SetResolution(img.GetResolution()); return ib; } @@ -502,7 +475,6 @@ Image Contrast(const Image& img, int amount) } Premultiply(w); w.SetHotSpots(img); - w.SetResolution(img.GetResolution()); return w; } @@ -577,7 +549,7 @@ Image Filter(const Image& img, ImageFilter9& filter) ImageEncoder tgt; ImageRaster src(img); Filter(tgt, src, filter); - return WithResolution(tgt, img); + return tgt; } struct RGBAI { @@ -635,7 +607,7 @@ Image Sharpen(const Image& img, int amount) ImageEncoder tgt; ImageRaster src(img); Sharpen(tgt, src, amount); - return WithResolution(tgt, img); + return tgt; } struct sEtchFilter : ImageFilter9 { @@ -680,7 +652,6 @@ Image SetColorKeepAlpha(const Image& img, Color c) } Premultiply(w); w.SetHotSpots(img); - w.SetResolution(img.GetResolution()); return w; } @@ -747,7 +718,6 @@ Image RotateClockwise(const Image& img) Point p1 = img.GetHotSpot(); Point p2 = img.Get2ndSpot(); SetNormalizedHotSpots(ib, sz.cy - p1.y - 1, p1.x, sz.cy - p2.y - 1, p2.x); - ib.SetResolution(img.GetResolution()); return ib; } @@ -762,7 +732,6 @@ Image RotateAntiClockwise(const Image& img) Point p1 = img.GetHotSpot(); Point p2 = img.Get2ndSpot(); SetNormalizedHotSpots(ib, p1.y, sz.cx - p1.x - 1, p2.y, sz.cx - p2.x - 1); - ib.SetResolution(img.GetResolution()); return ib; } @@ -776,7 +745,6 @@ Image Rotate180(const Image& orig) Point p1 = orig.GetHotSpot(); 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); - dest.SetResolution(dest.GetResolution()); return dest; } @@ -790,7 +758,6 @@ Image Transpose(const Image& img) Point p1 = img.GetHotSpot(); Point p2 = img.Get2ndSpot(); SetNormalizedHotSpots(ib, p1.y, p1.x, p2.y, p2.x); - ib.SetResolution(img.GetResolution()); return ib; } @@ -804,7 +771,6 @@ Image Transverse(const Image& img) Point p1 = img.GetHotSpot(); 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); - ib.SetResolution(img.GetResolution()); return ib; } @@ -825,7 +791,6 @@ Image MirrorHorz(const Image& img) Point p1 = img.GetHotSpot(); Point p2 = img.Get2ndSpot(); SetNormalizedHotSpots(ib, sz.cx - p1.x - 1, p1.y, sz.cx - p2.x - 1, p2.y); - ib.SetResolution(img.GetResolution()); return ib; } @@ -847,7 +812,6 @@ Image MirrorVert(const Image& img) Point p1 = img.GetHotSpot(); Point p2 = img.Get2ndSpot(); SetNormalizedHotSpots(ib, p1.x, sz.cy - p1.y - 1, p2.x, sz.cy - p2.y - 1); - ib.SetResolution(img.GetResolution()); 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(); } } - ib.SetResolution(m.GetResolution()); return ib; } @@ -936,7 +899,6 @@ Image Dither(const Image& m, int dival) int g = Grayscale(*s++) * 100 / dival; *t++ = g > dither[y & 7][x & 7] ? White() : Black(); } - ib.SetResolution(m.GetResolution()); return ib; } @@ -1069,7 +1031,6 @@ Image GaussianBlur(const Image& img, int radius, bool co) DoColumn(i); out.SetHotSpots(src); - out.SetResolution(src.GetResolution()); return out; }; diff --git a/uppsrc/Draw/ImageOp.h b/uppsrc/Draw/ImageOp.h index db34d9078..aeeaf4297 100644 --- a/uppsrc/Draw/ImageOp.h +++ b/uppsrc/Draw/ImageOp.h @@ -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 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 DstSrcOp(ImageBuffer& dest, Point p, const Image& src, const Rect& srect, 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 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 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 Downscale2x(const Image& src); @@ -255,7 +254,7 @@ void SetUHDMode(bool b = true); bool IsUHDMode(); void SyncUHDMode(); -Image DPI(const Image& m); +// Image DPI(const Image& m); Image DPI(const Image& img, int expected); inline int DPI(int a) { return IsUHDMode() ? 2 * a : a; } diff --git a/uppsrc/Draw/Iml.cpp b/uppsrc/Draw/Iml.cpp index 2586ff2dc..88218df4d 100644 --- a/uppsrc/Draw/Iml.cpp +++ b/uppsrc/Draw/Iml.cpp @@ -9,10 +9,7 @@ Vector UnpackImlDataUncompressed(const String& data) while(s + 6 * 2 + 1 <= data.End()) { ImageIml& m = img.Add(); ImageBuffer ib(Peek16le(s + 1), Peek16le(s + 3)); - m.flags = byte(*s) & 0x3f; - ib.SetResolution(decode(byte(*s) >> 6, 0, IMAGE_RESOLUTION_STANDARD, - 1, IMAGE_RESOLUTION_UHD, - IMAGE_RESOLUTION_NONE)); + m.flags = byte(*s); ib.SetHotSpot(Point(Peek16le(s + 5), Peek16le(s + 7))); ib.Set2ndSpot(Point(Peek16le(s + 9), Peek16le(s + 11))); s += 13; @@ -97,9 +94,8 @@ ImageIml Iml::GetRaw(int mode, const String& id) int ii = -1; if(mode == 0) ii = map.Find(id); - else { + else ii = ex_name[mode - 1].Find(id); - } return ii >= 0 ? GetRaw(mode, ii) : ImageIml(); } @@ -107,10 +103,16 @@ Image MakeImlImage(const String& id, Function G { Image image; 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) { - image = GetRaw(GUI_MODE_NORMAL, id).image; + image = GetImg(GUI_MODE_NORMAL, id).image; if(IsNull(image)) { - ImageIml im = GetRaw(GUI_MODE_NORMAL, id + "__UHD"); + ImageIml im = GetImg(GUI_MODE_NORMAL, id + "__UHD"); image = im.image; if((im.flags & IML_IMAGE_FLAG_UHD) && !((im.flags | global_flags) & (IML_IMAGE_FLAG_FIXED|IML_IMAGE_FLAG_FIXED_SIZE))) image = Downscale2x(image); @@ -118,24 +120,24 @@ Image MakeImlImage(const String& id, Function G } else { 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)) - 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 ImageIml im; if(mode & GUI_MODE_UHD) { - im = GetRaw(GUI_MODE_NORMAL, id + "__UHD"); + im = GetImg(GUI_MODE_NORMAL, id + "__UHD"); if(IsNull(im.image)) - im = GetRaw(GUI_MODE_UHD, id); + im = GetImg(GUI_MODE_UHD, id); } if(IsNull(im.image)) if(mode & GUI_MODE_DARK) { - im = GetRaw(0, id + "__DARK"); + im = GetImg(0, id + "__DARK"); if(IsNull(im.image)) - im = GetRaw(GUI_MODE_DARK, id); + im = GetImg(GUI_MODE_DARK, id); } 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))) 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))) @@ -143,8 +145,6 @@ Image MakeImlImage(const String& id, Function G image = im.image; } - if(!IsNull(image) && (mode & GUI_MODE_UHD)) // this is to support legacy code mostly - SetResolution(image, IMAGE_RESOLUTION_UHD); ScanOpaque(image); } return image; diff --git a/uppsrc/Draw/Mify.cpp b/uppsrc/Draw/Mify.cpp index b4cb99aca..8b660196e 100644 --- a/uppsrc/Draw/Mify.cpp +++ b/uppsrc/Draw/Mify.cpp @@ -204,15 +204,76 @@ Image Magnify(const Image& img, const Rect& src_, int nx, int ny, bool co) q += ncx; } }); - b.SetResolution(img.GetResolution()); 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) 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; } }; \ No newline at end of file diff --git a/uppsrc/Draw/RescaleFilter.cpp b/uppsrc/Draw/RescaleFilter.cpp index 1d17012f2..08b372f51 100644 --- a/uppsrc/Draw/RescaleFilter.cpp +++ b/uppsrc/Draw/RescaleFilter.cpp @@ -242,7 +242,6 @@ Image RescaleFilter(const Image& img, Size sz, const Rect& sr, #endif } }); - ib.SetResolution(img.GetResolution()); return ib; } diff --git a/uppsrc/Draw/Uhd.cpp b/uppsrc/Draw/Uhd.cpp index 004d04047..2a282e57f 100644 --- a/uppsrc/Draw/Uhd.cpp +++ b/uppsrc/Draw/Uhd.cpp @@ -97,7 +97,6 @@ Image Upscale2x(const Image& src) s = Filter(s, ef); } ImageBuffer h(s); - h.SetResolution(IMAGE_RESOLUTION_UHD); h.SetHotSpot(src.GetHotSpot() * 2); h.Set2ndSpot(s2 * 2); return h; @@ -110,7 +109,6 @@ Image Downscale2x(const Image& src) Size s2 = src.Get2ndSpot(); // see above... Image m = RescaleFilter(src, src.GetSize() / 2, s2.cx > 0 || s2.cy > 0 ? FILTER_BILINEAR : FILTER_LANCZOS3); ImageBuffer h(m); - h.SetResolution(IMAGE_RESOLUTION_STANDARD); h.SetHotSpot(s2 / 2); h.Set2ndSpot(src.Get2ndSpot() / 2); return h; @@ -136,19 +134,6 @@ void SyncUHDMode() 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) { if(img.GetSize().cy <= expected && IsUHDMode()) diff --git a/uppsrc/Draw/src.tpp/ImageMaker_en-us.tpp b/uppsrc/Draw/src.tpp/ImageMaker_en-us.tpp index c530a2ca6..5cfc2e16a 100644 --- a/uppsrc/Draw/src.tpp/ImageMaker_en-us.tpp +++ b/uppsrc/Draw/src.tpp/ImageMaker_en-us.tpp @@ -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] Rect[@(0.0.255) `&] [*@3 src], [@(0.0.255) int] [*@3 nx], [@(0.0.255) int] [*@3 ny], [@(0.0.255) bool] [*@3 co])&] -[s5;:Upp`:`:Magnify`(const Upp`:`:Image`&`,int`,int`): [_^Upp`:`:Image^ Image]_[* Magnify -]([@(0.0.255) const]_[_^Upp`:`:Image^ Image][@(0.0.255) `&]_[*@3 img], -[@(0.0.255) int]_[*@3 nx], [@(0.0.255) int]_[*@3 ny])&] +[s5;:Upp`:`:Magnify`(const Image`&`,int`,int`,bool`): Image [* Magnify]([@(0.0.255) const +] Image[@(0.0.255) `&] [*@3 img], [@(0.0.255) int] [*@3 nx], [@(0.0.255) int] +[*@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] and [%-*@3 ny] by simply repeating the pixels (each pixel becomes [%-*@3 nx] x [%-*@3 ny] same color block). If present in overload, diff --git a/uppsrc/Draw/src.tpp/ImageOp_en-us.tpp b/uppsrc/Draw/src.tpp/ImageOp_en-us.tpp index 1be809e1f..1c2a602e9 100644 --- a/uppsrc/Draw/src.tpp/ImageOp_en-us.tpp +++ b/uppsrc/Draw/src.tpp/ImageOp_en-us.tpp @@ -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.]&] [s3; &] [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 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].&] @@ -212,7 +195,7 @@ alpha.&] [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])&] [s2;%% [%-*@3 img] [%-*@3 thold].&] -[s3;%% &] +[s3; &] [s4; &] [s5;:Grayscale`(const Image`&`): [_^Image^ Image]_[* Grayscale]([@(0.0.255) const]_[_^Image^ I mage][@(0.0.255) `&]_[*@3 img])&] diff --git a/uppsrc/IconDes/IconDes.cpp b/uppsrc/IconDes/IconDes.cpp index fd541fc6c..ec25f3822 100644 --- a/uppsrc/IconDes/IconDes.cpp +++ b/uppsrc/IconDes/IconDes.cpp @@ -25,15 +25,6 @@ void IconDes::MaskSelection() SyncShow(); } -IconDes::Slot::Slot() -{ - pastepos = Null; - exp = false; - ImageBuffer b; - b.SetResolution(IMAGE_RESOLUTION_STANDARD); - image = b; -} - IconDes::Slot& IconDes::Current() { if(ilist.IsCursor()) @@ -65,11 +56,11 @@ void IconDes::SyncShow() iconshow.image.Clear(); if(IsCurrent()) { Slot& c = Current(); - Image image = c.image; - iconshow.image = image; + iconshow.image = c.image; + iconshow.flags = c.flags; iconshow.show_downscaled = show_downscaled; iconshow.show_synthetics = show_synthetics; - ilist.Set(2, RawToValue(MakeTuple(image, c.flags))); + ilist.Set(2, RawToValue(MakeTuple(c.image, c.flags))); } iconshow.Refresh(); } @@ -211,7 +202,7 @@ void IconDes::EllipseTool0(Point p, dword flags, bool fill_empty) DoTool( [&](IconDraw& iw) { iw.DrawEllipse(Rect(startpoint, p).Normalized(), fill_empty, - doselection ? CurrentColor() : RGBAZero(), pen, GrayColor(255)); + doselection ? CurrentColor() : RGBAZero(), pen, CurrentColor()); }, [&](Painter& sw) { sw.DrawEllipse(Rect(startpoint, p).Normalized(), diff --git a/uppsrc/IconDes/IconDes.h b/uppsrc/IconDes/IconDes.h index 94cfc493b..0403f6941 100644 --- a/uppsrc/IconDes/IconDes.h +++ b/uppsrc/IconDes/IconDes.h @@ -95,6 +95,7 @@ struct IconShow : public Ctrl { Image image; bool show_downscaled; bool show_synthetics; + dword flags; void Paint(Draw& w); @@ -107,8 +108,6 @@ void MirrorHorz(Image& img, const Rect& rect); void MirrorVert(Image& img, const Rect& rect); String PackImlDataUncompressed(const Vector& image); String PackImlData(const Vector& image); -Image DownSample3x(const Image& src, bool co = false); -Image DownSample2x(const Image& src, bool co = false); struct IconDraw : DDARasterizer { RGBA docolor; @@ -146,14 +145,12 @@ private: Image image; Image base_image; Image selection; - Point pastepos; + Point pastepos = Null; Image paste_image; String undo; String redo; - bool exp; + bool exp = false; dword flags = 0; - - Slot(); }; enum { @@ -426,8 +423,6 @@ struct ImlImage : ImageIml { bool LoadIml(const String& data, Array& img, int& format); String SaveIml(const Array& iml, int format, const String& eol = "\r\n"); -void SetRes(Image& m, int resolution); - } #endif diff --git a/uppsrc/IconDes/IconDes.lay b/uppsrc/IconDes/IconDes.lay index 8afa40d30..31a44dfee 100644 --- a/uppsrc/IconDes/IconDes.lay +++ b/uppsrc/IconDes/IconDes.lay @@ -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::EditString, name, LeftPosZ(52, 108).TopPosZ(8, 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, 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, exp, SetLabel(t_("Export as icon.ico and .png")).LeftPosZ(8, 160).TopPosZ(152, 16)) - ITEM(Upp::Button, ok, SetLabel(t_("OK")).LeftPosZ(28, 64).TopPosZ(176, 24)) - ITEM(Upp::Button, cancel, SetLabel(t_("Cancel")).LeftPosZ(96, 64).TopPosZ(176, 24)) + ITEM(Upp::Option, s3, SetLabel(t_("Supersampled 3x")).LeftPosZ(8, 156).TopPosZ(152, 16)) + ITEM(Upp::Option, exp, SetLabel(t_("Export as icon.ico and .png")).LeftPosZ(8, 160).TopPosZ(176, 16)) + 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 LAYOUT(ImageSizeLayout, 168, 68) diff --git a/uppsrc/IconDes/Image.cpp b/uppsrc/IconDes/Image.cpp index f713e1d56..a1ff239e5 100644 --- a/uppsrc/IconDes/Image.cpp +++ b/uppsrc/IconDes/Image.cpp @@ -170,7 +170,6 @@ void IconDes::SmoothRescale() for(;;) { Size sz(minmax((int)~dlg.cx, 1, 9999), minmax((int)~dlg.cy, 1, 9999)); Image m = RescaleFilter(bk, sz, ~dlg.method); - SetRes(m, bk.GetResolution()); if(IsPasting()) { c.paste_image = m; MakePaste(); diff --git a/uppsrc/IconDes/ImageOp.cpp b/uppsrc/IconDes/ImageOp.cpp index b3ad9438f..4aeeb1dce 100644 --- a/uppsrc/IconDes/ImageOp.cpp +++ b/uppsrc/IconDes/ImageOp.cpp @@ -160,7 +160,7 @@ String PackImlDataUncompressed(const Vector& image) for(const ImageIml& m : image) { const Image& img = m.image; StringStream ss; - ss.Put(((dword)img.GetResolution() << 6) | m.flags); + ss.Put(m.flags); Size sz = img.GetSize(); ss.Put16le(sz.cx); ss.Put16le(sz.cy); @@ -189,64 +189,4 @@ String PackImlData(const Vector& 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; -} - } diff --git a/uppsrc/IconDes/ImlFile.cpp b/uppsrc/IconDes/ImlFile.cpp index e606531f6..c4a71e8ef 100644 --- a/uppsrc/IconDes/ImlFile.cpp +++ b/uppsrc/IconDes/ImlFile.cpp @@ -295,106 +295,55 @@ static void PutOctalString(Stream& out, const char *b, const char *e, const Stri String SaveIml(const Array& iml, int format, const String& eol) { StringStream out; - if(format == 1) { - for(int i = 0; i < iml.GetCount(); i++) { - const ImlImage& c = iml[i]; - if(c.exp) - out << "IMAGE_META(\"exp\", \"\")" << eol; - String name = c.name; - Image buffer = c.image; - if(IsNull(name)) - name = "im__" + IntStr(i); - out.PutLine(Format("IMAGE_BEGIN(%s)", name)); - int last = 0; - for(int i = 0; i < buffer.GetHeight(); i++) { - String scan = PackRLE(buffer[i], buffer.GetWidth()); - if(!scan.IsEmpty() || i == 0) // force at least 1 scan - { - for(; last < i; last++) - out.PutLine("\tIMAGE_SCAN(\"\")"); - out.Put("\tIMAGE_SCAN("); - PutOctalString(out, scan.Begin(), scan.End(), eol, true); - out << ")" << eol; - last = i + 1; - } + out << "PREMULTIPLIED" << eol; + Index names; + Index 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 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; } - } - else { - out << "PREMULTIPLIED" << eol; - Index 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 names; - Index 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 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; - } + out << "IMAGE_END_DATA(" << bs.GetCount() << ", " << bn << ")" << eol; } return out.GetResult(); } diff --git a/uppsrc/IconDes/List.cpp b/uppsrc/IconDes/List.cpp index 90d6b84da..6bcbe20ec 100644 --- a/uppsrc/IconDes/List.cpp +++ b/uppsrc/IconDes/List.cpp @@ -19,6 +19,8 @@ String IconDes::FormatImageName(const Slot& c) r << " HD"; if(c.flags & IML_IMAGE_FLAG_DARK) r << " Dk"; + if(c.flags & IML_IMAGE_FLAG_S3) + r << " S3"; if(c.exp) r << " X"; return r; @@ -88,8 +90,11 @@ void IconDes::PrepareImageDlg(WithImageLayout& dlg) dlg.uhd <<= !!(flags & IML_IMAGE_FLAG_UHD); dlg.dark <<= !!(flags & IML_IMAGE_FLAG_DARK); - dlg.uhd ^= dlg.dark ^= dlg.exp ^= dlg.fixed_colors ^= dlg.fixed_size ^= dlg.fixed ^= dlg.name ^= - [&] { dlg.Break(-1000); }; + dlg.s3 <<= !!(flags & IML_IMAGE_FLAG_S3); + + for(Ctrl& q : dlg) + if(dynamic_cast