diff --git a/uppsrc/Draw/Image.h b/uppsrc/Draw/Image.h index aec27cda2..bba473af3 100644 --- a/uppsrc/Draw/Image.h +++ b/uppsrc/Draw/Image.h @@ -8,7 +8,8 @@ enum ImageKind { IMAGE_OPAQUE, }; -inline void Fill(RGBA *t, RGBA c, size_t n) { memset32(t, *(dword *)&c, n); } +inline void Fill(RGBA *t, RGBA c, size_t n) { memset32(t, *(dword *)&c, n); } +void FillDown(RGBA *t, int linecy, RGBA c, int cy); inline void Copy(RGBA *t, const RGBA *s, int n) { memcpy_t(t, s, n); } int Premultiply(RGBA *t, const RGBA *s, size_t len); @@ -256,6 +257,7 @@ struct ImageIml : Moveable { dword flags = 0; }; +Vector UnpackImlDataUncompressed(const String& data); Vector UnpackImlData(const void *ptr, int len); Vector UnpackImlData(const String& d); diff --git a/uppsrc/Draw/ImageBlit.cpp b/uppsrc/Draw/ImageBlit.cpp index af387b6e8..05238bb27 100644 --- a/uppsrc/Draw/ImageBlit.cpp +++ b/uppsrc/Draw/ImageBlit.cpp @@ -115,6 +115,25 @@ int Premultiply(RGBA *t, const RGBA *s, size_t len) return IMAGE_OPAQUE; } +void FillDown(RGBA *t, int linecy, RGBA c, int cy) +{ + for(int n = cy >> 3; n; n--) { + t[0] = t[linecy] = t[2 * linecy] = t[3 * linecy] = + t[4 * linecy] = t[5 * linecy] = t[6 * linecy] = t[7 * linecy] = c; + t += 8 * linecy; + } + if(cy & 4) { + t[0] = t[linecy] = t[2 * linecy] = t[3 * linecy] = c; + t += 4 * linecy; + } + if(cy & 2) { + t[0] = t[linecy] = c; + t += 2 * linecy; + } + if(cy & 1) + t[0] = c; +} + int um_table__[256]; void sInitUmTable__() diff --git a/uppsrc/Draw/ImageOp.cpp b/uppsrc/Draw/ImageOp.cpp index e6c304825..a15948d30 100644 --- a/uppsrc/Draw/ImageOp.cpp +++ b/uppsrc/Draw/ImageOp.cpp @@ -86,22 +86,28 @@ 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)) + 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) - while(--sz.cy >= 0) - (*op)(dest[p.y++] + p.x, src[sr.top++] + sr.left, sz.cx); + if(sz.cx > 0) { + if(co) + CoFor(sz.cy, [&](int i) { + (*op)(dest[p.y + i] + p.x, src[sr.top + i] + sr.left, sz.cx); + }); + else + while(--sz.cy >= 0) + (*op)(dest[p.y++] + p.x, src[sr.top++] + sr.left, sz.cx); + } } -void Copy(ImageBuffer& dest, Point p, const Image& src, const Rect& srect) +void Copy(ImageBuffer& dest, Point p, const Image& src, const Rect& srect, bool co) { DstSrcOp(dest, p, src, srect, Copy); } -void Over(ImageBuffer& dest, Point p, const Image& src, const Rect& srect) +void Over(ImageBuffer& dest, Point p, const Image& src, const Rect& srect, bool co) { DstSrcOp(dest, p, src, srect, AlphaBlend); } @@ -113,7 +119,7 @@ Image GetOver(const Image& dest, const Image& src) return r; } -Image Copy(const Image& src, const Rect& srect) +Image Copy(const Image& src, const Rect& srect, bool co) { ImageBuffer ib(srect.GetSize()); Copy(ib, Point(0, 0), src, srect); @@ -129,30 +135,30 @@ void Fill(ImageBuffer& dest, const Rect& rect, RGBA color) Fill(dest[y] + r.left, color, cx); } -void OverStraightOpaque(ImageBuffer& dest, Point p, const Image& src, const Rect& srect) +void OverStraightOpaque(ImageBuffer& dest, Point p, const Image& src, const Rect& srect, bool co) { DstSrcOp(dest, p, src, srect, AlphaBlendStraightOpaque); } -void Copy(Image& dest, Point p, const Image& _src, const Rect& srect) +void Copy(Image& dest, Point p, const Image& _src, const Rect& srect, bool co) { Image src = _src; ImageBuffer b(dest); - Copy(b, p, src, srect); + Copy(b, p, src, srect, co); dest = b; } -void Over(Image& dest, Point p, const Image& _src, const Rect& srect) +void Over(Image& dest, Point p, const Image& _src, const Rect& srect, bool co) { Image src = _src; ImageBuffer b(dest); - Over(b, p, src, srect); + Over(b, p, src, srect, co); dest = b; } -void Over(Image& dest, const Image& _src) +void Over(Image& dest, const Image& _src, bool co) { - Over(dest, Point(0, 0), _src, _src.GetSize()); + Over(dest, Point(0, 0), _src, _src.GetSize(), co); } void Fill(Image& dest, const Rect& rect, RGBA color) @@ -162,11 +168,11 @@ void Fill(Image& dest, const Rect& rect, RGBA color) dest = b; } -void OverStraightOpaque(Image& dest, Point p, const Image& _src, const Rect& srect) +void OverStraightOpaque(Image& dest, Point p, const Image& _src, const Rect& srect, bool co) { Image src = _src; ImageBuffer b(dest); - OverStraightOpaque(b, p, src, srect); + OverStraightOpaque(b, p, src, srect, co); dest = b; } @@ -190,7 +196,7 @@ Image Crop(const Image& img, const Rect& rc) return WithResolution(tgt, img); } -Image AddMargins(const Image& img, int left, int top, int right, int bottom, RGBA color) +Image AddMargins(const Image& img, int left, int top, int right, int bottom, RGBA color, bool co) { Size sz = img.GetSize(); ImageBuffer ib(sz.cx + left + right, sz.cy + top + bottom); diff --git a/uppsrc/Draw/ImageOp.h b/uppsrc/Draw/ImageOp.h index c2b7bb1c2..db34d9078 100644 --- a/uppsrc/Draw/ImageOp.h +++ b/uppsrc/Draw/ImageOp.h @@ -13,22 +13,24 @@ 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)); + void (*op)(RGBA *t, const RGBA *s, int n), bool co = false); + +void Copy(ImageBuffer& dest, Point p, const Image& src, const Rect& srect, bool co = false); + +void Over(ImageBuffer& dest, Point p, const Image& src, const Rect& srect, bool co = false); +void Over(Image& dest, Point p, const Image& _src, const Rect& srect, bool co = false); +void Over(Image& dest, const Image& _src, bool co = false); -void Over(ImageBuffer& dest, Point p, const Image& src, const Rect& srect); -void Over(Image& dest, const Image& src); -void Copy(ImageBuffer& dest, Point p, const Image& src, const Rect& srect); void Fill(ImageBuffer& dest, const Rect& rect, RGBA color); -void Copy(Image& dest, Point p, const Image& src, const Rect& srect); -void Over(Image& dest, Point p, const Image& src, const Rect& srect); +void Copy(Image& dest, Point p, const Image& src, const Rect& srect, bool co = false); Image GetOver(const Image& dest, const Image& src); void Fill(Image& dest, const Rect& rect, RGBA color); Image Copy(const Image& src, const Rect& srect); -void OverStraightOpaque(ImageBuffer& dest, Point p, const Image& src, const Rect& srect); -void OverStraightOpaque(Image& dest, Point p, const Image& _src, const Rect& srect); +void OverStraightOpaque(ImageBuffer& dest, Point p, const Image& src, const Rect& srect, bool co = false); +void OverStraightOpaque(Image& dest, Point p, const Image& _src, const Rect& srect, bool co = false); void Crop(RasterEncoder& tgt, Raster& img, const Rect& rc); Image Crop(const Image& img, const Rect& rc); @@ -241,6 +243,7 @@ Image CachedRescalePaintOnly(const Image& m, Size sz, int filter = Null); 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 Minify(const Image& img, int nx, int ny, bool co = false); Image MinifyCached(const Image& img, int nx, int ny, bool co = false); diff --git a/uppsrc/Draw/Iml.cpp b/uppsrc/Draw/Iml.cpp index e0e593d61..6bb3c3b70 100644 --- a/uppsrc/Draw/Iml.cpp +++ b/uppsrc/Draw/Iml.cpp @@ -2,10 +2,9 @@ namespace Upp { -Vector UnpackImlData(const void *ptr, int len) +Vector UnpackImlDataUncompressed(const String& data) { Vector img; - String data = ZDecompress(ptr, len); const char *s = data; while(s + 6 * 2 + 1 <= data.End()) { ImageIml& m = img.Add(); @@ -35,6 +34,11 @@ Vector UnpackImlData(const void *ptr, int len) return img; } +Vector UnpackImlData(const void *ptr, int len) +{ + return UnpackImlDataUncompressed(ZDecompress(ptr, len)); +} + Vector UnpackImlData(const String& d) { return UnpackImlData(~d, d.GetLength()); diff --git a/uppsrc/Draw/Mify.cpp b/uppsrc/Draw/Mify.cpp index cecd1c73f..b4cb99aca 100644 --- a/uppsrc/Draw/Mify.cpp +++ b/uppsrc/Draw/Mify.cpp @@ -179,24 +179,22 @@ Image MinifyCached(const Image& img, int nx, int ny, bool co) return MakeImage(m); } -Image Magnify(const Image& img, int nx, int ny) +Image Magnify(const Image& img, const Rect& src_, int nx, int ny, bool co) { - if(nx == 1 && ny == 1) - return img; - if(nx == 0 || ny == 0) - return Image(); - Size sz = img.GetSize(); + Rect src = src_ & img.GetSize(); bool xdown = nx < 0; nx = abs(nx); - int ncx = xdown ? sz.cx / nx : sz.cx * nx; - ImageBuffer b(ncx, sz.cy * ny); - const RGBA *s = ~img; - const RGBA *e = s + img.GetLength(); - RGBA *t = ~b; - while(s < e) { + Size ssz = src.GetSize(); + if(ssz.cx <= 0 || ssz.cy <= 0 || nx == 0 || ny == 0) + return Image(); + int ncx = xdown ? ssz.cx / nx : ssz.cx * nx; + ImageBuffer b(ncx, ssz.cy * ny); + CoFor(co, ssz.cy, [&](int y) { + const RGBA *s = img[src.top + y] + src.left; + const RGBA *e = s + ssz.cx; + RGBA *t = ~b + y * ncx * ny; RGBA *q = t; - const RGBA *le = s + sz.cx; - while(s < le) { + while(s < e) { Fill(q, *s, nx); q += nx; s++; @@ -205,10 +203,16 @@ Image Magnify(const Image& img, int nx, int ny) memcpy(q, t, ncx * sizeof(RGBA)); q += ncx; } - t = q; - } + }); b.SetResolution(img.GetResolution()); return b; } +Image Magnify(const Image& img, int nx, int ny) +{ + if(nx == 1 && ny == 1) + return img; + return Magnify(img, img.GetSize(), nx, ny, false); +} + }; \ No newline at end of file diff --git a/uppsrc/IconDes/Bar.cpp b/uppsrc/IconDes/Bar.cpp index f1e6f8a91..fb7b0ba34 100644 --- a/uppsrc/IconDes/Bar.cpp +++ b/uppsrc/IconDes/Bar.cpp @@ -32,7 +32,7 @@ void IconDes::SetMagnify(int mag) if( !IsCurrent() ) return; - magnify = minmax(mag, 1, 27); + magnify = minmax(mag, 1, 50); sb = Point(0, 0); SetSb(); @@ -204,11 +204,11 @@ void IconDes::DrawBar(Bar& bar) bar.Add(c, "Supersample 3x", IconDesImg::ResizeDown(), THISBACK(ResizeDown)) .Key(AK_RESIZEDOWN3); bar.Add("Show UHD/Dark syntetics", IconDesImg::ShowOther(), - [=] { show_other = !show_other; show_small = false; SyncShow(); SetBar(); }) - .Check(show_other); + [=] { show_synthetics = !show_synthetics; show_downscaled = false; SyncShow(); SetBar(); }) + .Check(show_synthetics); bar.Add("Show downscaled", IconDesImg::ShowSmall(), - [=] { show_small = !show_small; show_other = false; SyncShow(); SetBar(); }) - .Check(show_small); + [=] { show_downscaled = !show_downscaled; show_synthetics = false; SyncShow(); SetBar(); }) + .Check(show_downscaled); bar.Add("Show secondardy grid", IconDesImg::grid2(), [=] { show_grid2 = !show_grid2; Refresh(); SetBar(); }) .Check(show_grid2); @@ -324,12 +324,12 @@ void IconDes::SerializeSettings(Stream& s) s % ImgFile(); if(version >= 3) { bool b = false; - s % b % show_small; + s % b % show_downscaled; } if(version >= 4) s % paste_mode; if(version >= 5) - s % show_other; + s % show_synthetics; if(version >= 6) s % show_grid2; } diff --git a/uppsrc/IconDes/IconDes.cpp b/uppsrc/IconDes/IconDes.cpp index b0f5293eb..3db0e412b 100644 --- a/uppsrc/IconDes/IconDes.cpp +++ b/uppsrc/IconDes/IconDes.cpp @@ -44,8 +44,8 @@ void IconDes::SyncShow() Slot& c = Current(); Image image = c.image; iconshow.image = image; - iconshow.show_small = show_small; - iconshow.show_other = show_other; + iconshow.show_downscaled = show_downscaled; + iconshow.show_synthetics = show_synthetics; ilist.Set(2, RawToValue(MakeTuple(image, c.flags))); } iconshow.Refresh(); @@ -83,7 +83,7 @@ void IconDes::HorzMouseWheel(Point pt, int zdelta, dword keyflags) void IconDes::Scroll() { magnify = max(magnify, 1); - scroller.Scroll(*this, GetSize(), sb, Size(magnify, magnify)); + Refresh(); } void IconDes::Layout() @@ -465,19 +465,29 @@ void IconDes::SelectRect() SetBar(); } +String PackUndo(const Vector& img) +{ + return FastCompress(PackImlDataUncompressed(img)); +} + +Vector UnpackUndo(const String& data) +{ + return UnpackImlDataUncompressed(FastDecompress(data)); +} + void IconDes::SaveUndo() { if(!IsCurrent()) return; Slot& c = Current(); - Vector undo = UnpackImlData(c.undo); - int maxn = minmax((single_mode ? 4000000 : 400000) / max((int)c.image.GetLength(), 1), 4, 128); + Vector undo = UnpackUndo(c.undo); + int maxn = minmax((single_mode ? 40000000 : 2000000) / max((int)c.image.GetLength(), 1), 4, 128); while(undo.GetCount() > maxn) undo.Remove(0); if(undo.GetCount() && undo.Top().image == c.image) return; undo.Add().image = c.image; - c.undo = PackImlData(undo); + c.undo = PackUndo(undo); c.redo.Clear(); SetBar(); undo.Clear(); @@ -488,14 +498,14 @@ void IconDes::Undo() if(!IsCurrent()) return; Slot& c = Current(); - Vector undo = UnpackImlData(c.undo); + Vector undo = UnpackUndo(c.undo); if(undo.GetCount() == 0) return; - Vector redo = UnpackImlData(c.redo); + Vector redo = UnpackUndo(c.redo); redo.Add().image = c.image; c.image = undo.Pop().image; - c.undo = PackImlData(undo); - c.redo = PackImlData(redo); + c.undo = PackUndo(undo); + c.redo = PackUndo(redo); SyncImage(); SetBar(); } @@ -505,14 +515,14 @@ void IconDes::Redo() if(!IsCurrent()) return; Slot& c = Current(); - Vector redo = UnpackImlData(c.redo); + Vector redo = UnpackUndo(c.redo); if(redo.GetCount() == 0) return; - Vector undo = UnpackImlData(c.undo); + Vector undo = UnpackUndo(c.undo); undo.Add().image = c.image; c.image = redo.Pop().image; - c.undo = PackImlData(undo); - c.redo = PackImlData(redo); + c.undo = PackUndo(undo); + c.redo = PackUndo(redo); SyncImage(); SetBar(); } diff --git a/uppsrc/IconDes/IconDes.h b/uppsrc/IconDes/IconDes.h index 92827d6f4..b7ea7c766 100644 --- a/uppsrc/IconDes/IconDes.h +++ b/uppsrc/IconDes/IconDes.h @@ -93,8 +93,8 @@ public: struct IconShow : public Ctrl { Image image; - bool show_small; - bool show_other; + bool show_downscaled; + bool show_synthetics; void Paint(Draw& w); @@ -105,9 +105,10 @@ void FloodFill(ImageBuffer& img, RGBA color, Point pt, const Rect& rc, int tol void InterpolateImage(Image& img, const Rect& _rc); 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); -Image DownSample2x(const Image& src); +Image DownSample3x(const Image& src, bool co = false); +Image DownSample2x(const Image& src, bool co = false); /* struct IconDraw : ImagePainter { @@ -177,12 +178,11 @@ private: bool doselection = false; bool selectrect = false; int paste_mode; - bool show_other = false; - bool show_small = false; + bool show_synthetics = false; + bool show_downscaled = false; bool show_grid2 = false; ScrollBars sb; - Scroller scroller; ToolBar toolbar; SplitterFrame leftpane; diff --git a/uppsrc/IconDes/Image.cpp b/uppsrc/IconDes/Image.cpp index 350d27f63..f713e1d56 100644 --- a/uppsrc/IconDes/Image.cpp +++ b/uppsrc/IconDes/Image.cpp @@ -40,7 +40,7 @@ void IconDes::KeyMove(int dx, int dy) else { Image h = c.image; c.image = CreateImage(h.GetSize(), Null); - UPP::Copy(c.image, Point(dx, dy), h, h.GetSize()); + UPP::Copy(c.image, Point(dx, dy), h, h.GetSize(), true); } Sync(); } diff --git a/uppsrc/IconDes/ImageOp.cpp b/uppsrc/IconDes/ImageOp.cpp index 93380f2bf..b3ad9438f 100644 --- a/uppsrc/IconDes/ImageOp.cpp +++ b/uppsrc/IconDes/ImageOp.cpp @@ -154,7 +154,7 @@ void MirrorVert(Image& img, const Rect& rect) img = ib; } -String PackImlData(const Vector& image) +String PackImlDataUncompressed(const Vector& image) { StringBuffer block; for(const ImageIml& m : image) { @@ -181,16 +181,21 @@ String PackImlData(const Vector& image) s++; } } - return ZCompress(block); + return block; } -Image DownSample3x(const Image& src) +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; - for(int y = 0; y < tsz.cy; y++) { + CoFor(co, tsz.cy, [&](int y) { RGBA *t = ib[y]; RGBA *e = t + tsz.cx; const RGBA *s = src[3 * y]; @@ -210,17 +215,17 @@ Image DownSample3x(const Image& src) t++; s += 3; } - } + }); ib.SetResolution(src.GetResolution()); return ib; } -Image DownSample2x(const Image& src) +Image DownSample2x(const Image& src, bool co) { Size tsz = src.GetSize() / 2; ImageBuffer ib(tsz); int w = src.GetSize().cx; - for(int y = 0; y < tsz.cy; y++) { + CoFor(co, tsz.cy, [&](int y) { RGBA *t = ib[y]; RGBA *e = t + tsz.cx; const RGBA *s = src[2 * y]; @@ -239,7 +244,7 @@ Image DownSample2x(const Image& src) t++; s += 2; } - } + }); ib.SetResolution(src.GetResolution()); return ib; } diff --git a/uppsrc/IconDes/Paint.cpp b/uppsrc/IconDes/Paint.cpp index 70f626568..1ac9a46be 100644 --- a/uppsrc/IconDes/Paint.cpp +++ b/uppsrc/IconDes/Paint.cpp @@ -9,36 +9,69 @@ namespace Upp { void IconShow::Paint(Draw& w) { Size sz = GetSize(); - static Color color[] = { White(), WhiteGray(), LtGray(), Gray(), Black(), + static Color color[] = { White(), Black(), WhiteGray(), LtGray(), Gray(), Yellow(), Brown(), Red(), Green(), Blue(), Cyan(), Magenta() }; Size msz = image.GetSize(); Size isz = msz; - if(show_small) - isz.cx += isz.cx / 2 + DPI(4); - int n = msz.cx ? minmax(sz.cx / isz.cx, 1, __countof(color)) : 1; - Image m2, m3; - if(msz.cx && show_small) { - m2 = DownSample2x(image); - m3 = DownSample3x(image); + int gap = DPI(8); + double fits = msz.cx * msz.cy < 20000; + if(fits) { + if(show_downscaled) { + isz.cx += (isz.cx + 1) / 2 + gap; + isz.cy += max(isz.cy, (isz.cy + 1) / 2 + (isz.cy + 2) / 3 + gap); + } + if(show_synthetics) { + isz.cx += 3 * isz.cx + gap; + isz.cy += 2 * isz.cy + gap; + } } + int n = sz.cx ? clamp(sz.cx / isz.cx, 1, __countof(color)) : 1; + int ncx = sz.cx / n; + Image m2, m3; + Image dk, up2, up2dk; + if(fits) { + if(msz.cx && show_downscaled) { + m2 = DownSample2x(image); + m3 = DownSample3x(image); + } + if(show_synthetics) { + dk = DarkTheme(image); + up2 = Upscale2x(image); + up2dk = Upscale2x(DarkTheme(image)); + } + } + else + isz = msz; + for(int i = 0; i < n; i++) { - int x = i * sz.cx / n; - int cx = (i + 1) * sz.cx / n - x; + int x = i * ncx; + int cx = (i + 1) * ncx - x; w.DrawRect(x, 0, cx, sz.cy, color[i]); if(msz.cx) { - if(show_other) { - Point c(x + cx / 2, sz.cy / 2); - w.DrawImage(c.x - DPI(8) - isz.cx, c.y - DPI(8) - isz.cy, image); - w.DrawImage(c.x + DPI(8), c.y - DPI(8) - isz.cy, DarkTheme(image)); - w.DrawImage(c.x - DPI(8) - isz.cx, c.y + DPI(8), Upscale2x(image)); - w.DrawImage(c.x + DPI(8), c.y + DPI(8), Upscale2x(DarkTheme(image))); + Point pos(x + (cx - isz.cx) / 2, (sz.cy - isz.cy) / 2); + if(fits) { + if(show_synthetics) { + int x2 = pos.x + 2 * msz.cx + gap; + w.DrawImage(pos.x, pos.y, image); + w.DrawImage(x2, pos.y, dk); + pos.y += msz.cy + gap; + w.DrawImage(pos.x, pos.y, up2); + w.DrawImage(x2, pos.y, up2dk); + } + else { + int y = pos.y + (isz.cy - msz.cy) / 2; + w.DrawImage(pos.x, y, image); + if(show_downscaled) { + int x2 = pos.x + msz.cx + gap; + w.DrawImage(x2, y, m2); + w.DrawImage(x2, y + (msz.cx + 1) / 2 + gap, m3); + } + } } else { - w.DrawImage(x + (cx - isz.cx) / 2, (sz.cy - isz.cy) / 2, image); - if(show_small) { - w.DrawImage(x + (cx - isz.cx) / 2 + msz.cx + DPI(4), (sz.cy - isz.cy) / 2, m2); - w.DrawImage(x + (cx - isz.cx) / 2 + msz.cx + DPI(4), (sz.cy - isz.cy) / 2 + 2 * msz.cy / 3, m3); - } + w.Clip(x, 0, isz.cx, sz.cy); + w.DrawImage(x + DPI(2), DPI(2), image); + w.End(); } } } @@ -59,7 +92,6 @@ void IconDes::Paint(Draw& w) const Image& image = Current().image; const Image& selection = Current().selection; Point spos = sb; - scroller.Set(spos); Size isz = image.GetSize(); bool pastepaint = HasCapture() && IsPasting(); magnify = max(magnify, 1); @@ -68,17 +100,17 @@ void IconDes::Paint(Draw& w) ImageBuffer pb(isz); RGBA c1 = GrayColor(102); RGBA c2 = GrayColor(153); - int xn = isz.cx / 4; + int xn = isz.cx / DPI(4); for(int y = 0; y < isz.cy; y++) { RGBA *b = pb[y]; RGBA cc1 = c1; RGBA cc2 = c2; - if(y & 4) + if(y & DPI(4)) Swap(cc1, cc2); for(int q = xn; q--;) { - b[0] = b[1] = b[2] = b[3] = cc1; + Fill(b, cc1, DPI(4)); Swap(cc1, cc2); - b += 4; + b += DPI(4); } while(b < pb[y] + isz.cx) *b++ = cc1; @@ -99,126 +131,115 @@ void IconDes::Paint(Draw& w) w.DrawImage(-spos.x, -spos.y, pb); Rect r = pb.GetSize(); r.Offset(-spos); - w.DrawRect(r.right, 0, 1, r.bottom + 1, LtRed()); - w.DrawRect(0, r.bottom, r.right, 1, LtRed()); + if(show_grid2) { + w.DrawRect(r.right, 0, 1, r.bottom + 1, LtRed()); + w.DrawRect(0, r.bottom, r.right, 1, LtRed()); + } m1refresh = Null; if(IsPasting()) DrawFrame(w, Rect(Current().pastepos - spos, Current().paste_image.GetSize()), LtRed); return; } - Point hotspot = image.GetHotSpot(); - Point spot2 = image.Get2ndSpot(); - int m = isz.cx * magnify + 1; - Point mpos = magnify * spos; - int grid2 = 0; - if(max(isz.cx, isz.cy) > 16 && show_grid2) { - if(isz.cx % 3 == 0 && isz.cy % 3 == 0) - grid2 = 3; - else - if(isz.cx % 4 == 0 && isz.cy % 4 == 0) - grid2 = 4; - } - auto GridColor = [&](int x, int sz) -> Color { - if(grid2) { - if(x == sz / 2) - return LtMagenta(); - if(x % grid2 == 0) - return LtRed(); - } - return Black(); - }; - for(int y = isz.cy; y >= 0; y--) - w.DrawRect(-mpos.x, magnify * y - mpos.y, m, 1, GridColor(y, isz.cy)); - m = isz.cy * magnify + 1; - for(int x = isz.cx; x >= 0; x--) - w.DrawRect(magnify * x - mpos.x, -mpos.y, 1, m, GridColor(x, isz.cx)); - if(!IsHotSpot()) { - hotspot = Null; - spot2 = Null; - } - w.DrawRect(isz.cx * magnify - mpos.x + 1, 0, 9999, 9999, SColorPaper()); - w.DrawRect(0, isz.cy * magnify - mpos.y + 1, 9999, 9999, SColorPaper()); - int my0 = -magnify * spos.y; - int magnify4 = 4 * magnify; - int md = (magnify + 1) / 2; - int mc = (magnify - 1) / 2; - Image masked = Crop(IconDesImg::Masked(), Size(magnify - 1, magnify - 1)); - for(int y0 = 0; y0 < isz.cy; y0 += 4, my0 += magnify4) { - int mx0 = -magnify * spos.x; - for(int x0 = 0; x0 < isz.cx; x0 += 4, mx0 += magnify4) { - if(w.IsPainting(mx0, my0, magnify4, magnify4)) { - int ex = min(x0 + 4, isz.cx); - int my = my0; - for(int y = y0; y < min(y0 + 4, isz.cy); y++, my += magnify) { - const RGBA *s = image[y] + x0; - const RGBA *k = selection[y] + x0; - const RGBA *pk = y ? selection[y - 1] + x0 : NULL; - const RGBA *nk = y + 1 < isz.cy ? selection[y + 1] + x0 : NULL; - int mx = mx0; - for(int x = x0; x < ex; x++) { - if(s->a == 255) - w.DrawRect(mx + 1, my + 1, magnify - 1, magnify - 1, *s); - else { // paint chequered background - Color c = StraightColor(*s); - Color c1 = Blend(GrayColor(102), c, s->a); - w.DrawRect(mx + 1, my + 1, magnify - 1, magnify - 1, c1); - Color c2 = Blend(GrayColor(153), c, s->a); - w.DrawRect(mx + md, my + 1, mc, mc, c2); - w.DrawRect(mx + 1, my + md, mc, mc, c2); - } - if(!pastepaint) - if(!k->r) { - w.DrawImage(mx + 1, my + 1, masked); - if(x > 0) { - if(pk && pk[-1].r) - sDrawChRect(w, mx + 1, my + 1, 4, 4); - if(k[-1].r) - sDrawChRect(w, mx + 1, my + 1, 4, magnify - 1); - if(nk && nk[-1].r) - sDrawChRect(w, mx + 1, my + magnify - 4, 4, 4, true); - } - if(pk && pk->r) - sDrawChRect(w, mx + 1, my + 1, magnify - 1, 4); - if(nk && nk->r) - sDrawChRect(w, mx + 1, my + magnify - 4, magnify - 1, 4, true); - if(x + 1 < isz.cx) { - if(pk && pk[1].r) - sDrawChRect(w, mx + magnify - 4, my + 1, 4, 4, true); - if(k[1].r) - sDrawChRect(w, mx + magnify - 4, my + 1, 4, magnify - 1, true); - if(nk && nk[1].r) - sDrawChRect(w, mx + magnify - 4, my + magnify - 4, 4, 4); - } - } - if(spot2.x == x && spot2.y == y) - w.DrawImage(mx + 1, my + 1, Rescale(IconDesImg::HotSpotB(), magnify - 1, magnify - 1)); - if(hotspot.x == x && hotspot.y == y) - w.DrawImage(mx + 1, my + 1, Rescale(IconDesImg::HotSpotA(), magnify - 1, magnify - 1)); - s++; - k++; - mx += magnify; - if(pk) - pk++; - if(nk) - nk++; - } - } + + Rect src = Rect((sz + magnify) / magnify).Offseted(spos) & isz; + Size ssz = src.GetSize(); + + ImageBuffer b(src.GetSize() * magnify); + int m2 = magnify / 2; + CoFor(src.GetHeight(), [&](int y) { // paint chequered background + RGBA *q = b[y * magnify]; + int i = 0; + Color c1 = GrayColor(102); + Color c2 = GrayColor(153); + int m = m2; + for(int pass = 0; pass < 2; pass++) { + RGBA *t = q; + for(int i = 0; i < src.GetWidth(); i++) { + Fill(q, c1, magnify); + Fill(q + 1, c2, m2); + q += magnify; } + i++; + while(i < m) { + memcpy_t(q, t, b.GetWidth()); + q += b.GetWidth(); + i++; + } + m = magnify; + Swap(c1, c2); } + }); + + w.DrawImage(0, 0, b); // paint chequered background + w.DrawImage(0, 0, Magnify(image, src, magnify, magnify, true)); // paint actual image + + if(magnify > 6) { + int grid2 = 0; + if(max(isz.cx, isz.cy) > 16 && show_grid2) { + if(isz.cx % 3 == 0 && isz.cy % 3 == 0) + grid2 = 3; + else + if(isz.cx % 4 == 0 && isz.cy % 4 == 0) + grid2 = 4; + } + auto GridColor = [&](int x, int sz) -> Color { + if(grid2) { + if(x == sz / 2) + return LtMagenta(); + if(x % grid2 == 0) + return LtRed(); + } + return Black(); + }; + int m = ssz.cx * magnify + 1; + for(int y = 0; y <= src.GetHeight(); y++) + w.DrawRect(0, magnify * y, m, 1, GridColor(y + src.top, isz.cy)); + m = ssz.cy * magnify + 1; + for(int x = 0; x <= src.GetWidth(); x++) + w.DrawRect(magnify * x, 0, 1, m, GridColor(x + src.left, isz.cx)); } + + if(!pastepaint && !IsNull(selection)) { // paint selection + RGBA c1 = 120 * Black(); + RGBA c2 = 120 * White(); + int ncx = ssz.cx * magnify; + ImageBuffer b(ncx, ssz.cy * magnify); + CoFor(ssz.cy, [&](int y) { + const RGBA *s = selection[src.top + y] + src.left; + const RGBA *e = s + ssz.cx; + RGBA *t = ~b + y * ncx * magnify; + RGBA *q = t; + while(s < e) { + Fill(q, s->r ? RGBAZero() : c1, magnify); + Fill(q + ncx, s->r ? RGBAZero() : c2, magnify); + q += magnify; + s++; + } + + for(int i = 2; i < magnify; i++) { + q += ncx; + memcpy_t(q, t, ncx); + t += ncx; + } + }); + w.DrawImage(0, 0, b); + } + if(IsPasting() && !pastepaint) DrawFatFrame(w, Rect(magnify * (Current().pastepos - spos), magnify * Current().paste_image.GetSize() + Size(1, 1)), Color(200, 200, 255), 3); - if(magnify < 9) - return; - auto PaintHotSpot = [&](Point hotspot, Color c) { // Show hotspots even if not designing them - if(hotspot.x > 0 || hotspot.y > 0) - DrawFatFrame(w, hotspot.x * magnify, hotspot.y * magnify, magnify + 1, magnify + 1, c, 1 + magnify / 8); - }; - PaintHotSpot(image.GetHotSpot(), LtRed()); - PaintHotSpot(image.Get2ndSpot(), LtBlue()); + if(magnify > 8 || IsHotSpot()) { + auto PaintHotSpot = [&](Point hotspot, Color c) { + if(hotspot.x > 0 || hotspot.y > 0) { + hotspot = (hotspot - spos) * magnify; + DrawFatFrame(w, hotspot.x, hotspot.y, magnify + 1, magnify + 1, c, max(DPI(1), 1 + magnify / 8)); + } + }; + PaintHotSpot(image.GetHotSpot(), LtRed()); + PaintHotSpot(image.Get2ndSpot(), LtBlue()); + } } } diff --git a/uppsrc/ide/ide.upp b/uppsrc/ide/ide.upp index 3c25bb5d6..e009bdb72 100644 --- a/uppsrc/ide/ide.upp +++ b/uppsrc/ide/ide.upp @@ -133,7 +133,8 @@ mainconfig "" = "GUI CHECKCLIPBOARD", "" = "GUI PEAKMEM", "" = "GUI HEAPLOG", - "" = "GUI X11"; + "" = "GUI X11", + "" = "GUI DEBUGCODE"; custom() "", "ASDFASDFASDF",