#include "IconDes.h" namespace Upp { #define IMAGECLASS IconDesImg #define IMAGEFILE #include void IconShow::Paint(Draw& w) { Size sz = GetSize(); static Color color[] = { White(), Black(), WhiteGray(), LtGray(), Gray(), 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 isz = msz; 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) { if(flags & IML_IMAGE_FLAG_UHD) { 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 ncx = sz.cx / n; Image m2, m3; Image dk, s2, s2dk; if(fits) { if(msz.cx && show_downscaled) { m2 = DownSample2x(image); m3 = DownSample3x(image); } if(show_synthetics) { dk = DarkTheme(image); if(flags & IML_IMAGE_FLAG_UHD) { 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 isz = msz; for(int i = 0; i < n; i++) { int x = i * ncx; int cx = (i + 1) * ncx - x; w.DrawRect(x, 0, cx, sz.cy, color[i]); if(msz.cx) { Point pos(x + (cx - isz.cx) / 2, (sz.cy - isz.cy) / 2); if(fits) { if(show_synthetics) { int x2 = pos.x + 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, s2); w.DrawImage(x2, pos.y, s2dk); } 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.Clip(x, 0, isz.cx, sz.cy); w.DrawImage(x + DPI(2), DPI(2), image); w.End(); } } } } void sDrawChRect(Draw& w, int x0, int y, int cx, int cy, bool start = false) { w.DrawRect(x0, y, cx, cy, Color(255, 150, 200)); } void IconDes::Paint(Draw& w) { Size sz = GetSize(); if(!IsCurrent()) { w.DrawRect(sz, SColorPaper()); return; } const Image& image = Current().image; const Image& selection = Current().selection; Point spos = sb; Size isz = image.GetSize(); bool pastepaint = HasCapture() && IsPasting(); magnify = max(magnify, 1); if(magnify == 1) { w.DrawRect(sz, SColorPaper()); ImageBuffer pb(isz); RGBA c1 = GrayColor(102); RGBA c2 = GrayColor(153); 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 & DPI(4)) Swap(cc1, cc2); for(int q = xn; q--;) { Fill(b, cc1, DPI(4)); Swap(cc1, cc2); b += DPI(4); } while(b < pb[y] + isz.cx) *b++ = cc1; } AlphaBlend(pb, image, (int)image.GetLength()); if(!pastepaint) for(int y = 0; y < isz.cy; y++) { const RGBA *m = selection[y]; RGBA *t = pb[y]; const RGBA *e = m + isz.cx; while(m < e) { if(!m->r) t->r = t->g = t->b = ((t->r + t->g + t->b) >> 2); m++; t++; } } w.DrawImage(-spos.x, -spos.y, pb); Rect r = pb.GetSize(); r.Offset(-spos); 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; } 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 > 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()); } } }