diff --git a/src/netxs/apps/calc.hpp b/src/netxs/apps/calc.hpp index f127a5cc5b..a35ceb2959 100644 --- a/src/netxs/apps/calc.hpp +++ b/src/netxs/apps/calc.hpp @@ -110,13 +110,13 @@ namespace netxs::ui auto region = item.region.normalize(); auto pos1 = region.coor / step * step; auto pos2 = (region.coor + region.size + step) / step * step; - auto pick = rect{ full.coor + pos1, pos2 - pos1 }.clip(area).clip(clip); + auto pick = rect{ full.coor + pos1, pos2 - pos1 }.trimby(area).trimby(clip); parent_canvas.fill(pick, fill); } if (item.inside) { auto pos1 = item.curpos / step * step; - auto pick = rect{ full.coor + pos1, step }.clip(clip); + auto pick = rect{ full.coor + pos1, step }.trimby(clip); parent_canvas.fill(pick, fill); } }); diff --git a/src/netxs/apps/term.hpp b/src/netxs/apps/term.hpp index 487dbcf60b..ea137760f4 100644 --- a/src/netxs/apps/term.hpp +++ b/src/netxs/apps/term.hpp @@ -805,7 +805,7 @@ namespace netxs::app::terminal } } auto clip = parent_canvas.clip(); - auto dest = clip.clip({ region.coor, { region.size.x, std::min(bground.size().y, *menu_height) }}); + auto dest = clip.trim({ region.coor, { region.size.x, std::min(bground.size().y, *menu_height) }}); parent_canvas.clip(dest); bground.move(region.coor); parent_canvas.plot(bground, cell::shaders::blend); // Menu background. diff --git a/src/netxs/desktopio/application.hpp b/src/netxs/desktopio/application.hpp index f3540718fd..91c676810d 100644 --- a/src/netxs/desktopio/application.hpp +++ b/src/netxs/desktopio/application.hpp @@ -23,7 +23,7 @@ namespace netxs::app namespace netxs::app::shared { - static const auto version = "v0.9.75"; + static const auto version = "v0.9.75b"; static const auto repository = "https://github.com/directvt/vtm"; static const auto usr_config = "~/.config/vtm/settings.xml"s; static const auto sys_config = "/etc/vtm/settings.xml"s; diff --git a/src/netxs/desktopio/canvas.hpp b/src/netxs/desktopio/canvas.hpp index 39c2ec9db0..1ebdda22ab 100644 --- a/src/netxs/desktopio/canvas.hpp +++ b/src/netxs/desktopio/canvas.hpp @@ -2333,9 +2333,8 @@ namespace netxs void plot(core const& block, P fuse) // core: Fill the client area by the specified block with coordinates inside the canvas area. { //todo use block.client instead of block.region - auto local = rect{ client.coor - region.coor, client.size }; - auto joint = local.clip(block.region); - if (joint) + auto joint = rect{ client.coor - region.coor, client.size }; + if (joint.trimby(block.region)) { auto place = joint.coor - block.region.coor; netxs::inbody(*this, block, joint, place, fuse); @@ -2532,17 +2531,17 @@ namespace netxs { auto temp = area; temp.size.y = std::max(0, border.t); // Top - fill(temp.clip(area), fuse); + fill(temp.trim(area), fuse); temp.coor.y += area.size.y - border.b; // Bottom temp.size.y = std::max(0, border.b); - fill(temp.clip(area), fuse); + fill(temp.trim(area), fuse); temp.size.x = std::max(0, border.l); // Left temp.size.y = std::max(0, area.size.y - border.t - border.b); temp.coor.y = area.coor.y + border.t; - fill(temp.clip(area), fuse); + fill(temp.trim(area), fuse); temp.coor.x += area.size.x - border.r; // Right temp.size.x = std::max(0, border.r); - fill(temp.clip(area), fuse); + fill(temp.trim(area), fuse); } template void cage(rect area, twod border_width, P fuse) // core: Draw the cage around specified area. diff --git a/src/netxs/desktopio/consrv.hpp b/src/netxs/desktopio/consrv.hpp index 1a9829149a..8d38217458 100644 --- a/src/netxs/desktopio/consrv.hpp +++ b/src/netxs/desktopio/consrv.hpp @@ -2330,7 +2330,7 @@ struct impl : consrv auto size = block.size(); auto clip = block.clip(); auto dest = rect{ coor, clip.size }; - trim = dest.clip(trim); + trim.trimby(dest); clip -= dest - trim; coor = trim.coor; auto head = block.begin() + clip.coor.y * size.x; diff --git a/src/netxs/desktopio/controls.hpp b/src/netxs/desktopio/controls.hpp index bd031598ce..906dd77cc7 100644 --- a/src/netxs/desktopio/controls.hpp +++ b/src/netxs/desktopio/controls.hpp @@ -259,9 +259,9 @@ namespace netxs::ui if (deed == hids::events::mouse::scroll::down.id) g.zoomdt -= warp; else g.zoomdt += warp; gear.owner.SIGNAL(tier::request, e2::form::prop::viewport, viewport, ()); - auto r = g.zoomsz + g.zoomdt; - r.size = std::max(dot_00, r.size); - auto next = r.clip(viewport); + auto next = g.zoomsz + g.zoomdt; + next.size = std::max(dot_00, next.size); + next.trimby(viewport); auto step = boss.base::extend(next); if (!step.size) // Undo if can't zoom. { @@ -284,9 +284,9 @@ namespace netxs::ui { auto corner = item.corner(area.size); auto side_x = item.hzgrip.shift(corner).normalize_itself() - .shift_itself(area.coor).clip(area); + .shift_itself(area.coor).trim(area); auto side_y = item.vtgrip.shift(corner).normalize_itself() - .shift_itself(area.coor).clip(area); + .shift_itself(area.coor).trim(area); canvas.fill(side_x, fuse); canvas.fill(side_y, fuse); }); @@ -879,7 +879,7 @@ namespace netxs::ui if (state) { auto clip = canvas.core::clip(); - if (auto area = clip.clip(body)) + if (auto area = clip.trim(body)) { auto& test = canvas.peek(body.coor); if (test.wdt() == 2) // Extend cursor to adjacent halves. @@ -3923,7 +3923,7 @@ namespace netxs::ui auto& region_len = region.size[Axis]; auto& object_len = object.size[Axis]; - handle = region.clip(handle); + handle.trimby(region); handle_len = std::max(1, handle_len); drawfx(*this, parent_canvas, handle, object_len, handle_len, region_len, wide); diff --git a/src/netxs/desktopio/geometry.hpp b/src/netxs/desktopio/geometry.hpp index cef40d39a8..ffe225ee6d 100644 --- a/src/netxs/desktopio/geometry.hpp +++ b/src/netxs/desktopio/geometry.hpp @@ -156,7 +156,17 @@ namespace netxs friend auto max(duplet const& p1, duplet const& p2) { return duplet{ std::max(p1.x, p2.x), std::max(p1.y, p2.y) }; } friend auto round(duplet const& p) { return duplet{ std::round(p.x), std::round(p.y) }; } friend auto abs(duplet const& p) { return duplet{ std::abs(p.x), std::abs(p.y) }; } - friend auto clamp(duplet const& p, duplet const& p1, duplet const& p2) { return duplet{ std::clamp(p.x, p1.x, p2.x), std::clamp(p.y, p1.y, p2.y) }; } + friend auto clamp(duplet const& p, duplet const& p1, duplet const& p2) + { + return duplet{ std::clamp(p.x, p1.x, p2.x), + std::clamp(p.y, p1.y, p2.y) }; + } + static constexpr auto sort(duplet p1, duplet p2) + { + if (p1.x > p2.x) std::swap(p1.x, p2.x); + if (p1.y > p2.y) std::swap(p1.y, p2.y); + return std::pair{ p1, p2 }; + } }; // geometry: 2D point. @@ -194,21 +204,6 @@ namespace netxs twod coor; twod size; - // rect: Intersect two rects. - template - constexpr rect clip(rect r) const - { - if constexpr (Relative) r.coor += coor; - auto apex = coor + size; - auto r_apex = r.coor + r.size; - r.coor = std::clamp(r.coor, coor, apex); - r.size = std::clamp(r_apex, coor, apex) - r.coor; - return r; - } - twod clip(twod point) const - { - return std::clamp(point, coor, coor + std::max(dot_00, size - dot_11)); - } bool operator == (rect const&) const = default; explicit operator bool () const { return size.x != 0 && size.y != 0; } auto center () const { return coor + size / 2; } @@ -216,122 +211,84 @@ namespace netxs twod map (twod p) const { return p - coor; } rect shift (twod p) const { return { coor + p, size }; } auto& shift_itself (twod p) { coor += p; return *this; } - rect operator & (rect r) const { return clip(r); } - rect operator | (rect r) const { return unite(r); } + rect operator | (rect r) const { return unite(r, *this); } auto& operator += (rect r) { coor += r.coor; size += r.size; return *this; } auto& operator -= (rect r) { coor -= r.coor; size -= r.size; return *this; } + // rect: Return rect trimmed by r. + template + constexpr rect trim(rect r) const + { + if constexpr (Relative) r.coor += coor; + auto r_apex = r.coor + r.size; + auto [min, max] = twod::sort(coor, coor + size); + r.coor = std::clamp(r.coor, min, max); + r.size = std::clamp(r_apex, min, max) - r.coor; + return r; + } + // rect: Trim by the specified rect. + template + constexpr auto& trimby(rect r) + { + if constexpr (Relative) coor += r.coor; + auto apex = coor + size; + auto [min, max] = twod::sort(r.coor, r.coor + r.size); + coor = std::clamp(coor, min, max); + size = std::clamp(apex, min, max) - coor; + return *this; + } + // rect: Return clamped point. + constexpr twod clamp(twod point) const + { + auto [min, max] = twod::sort(coor, coor + size); + return std::clamp(point, min, max - dot_11); + } // rect: Is the point inside the rect. - bool hittest(twod p) const + constexpr bool hittest(twod p) const { auto test = faux; - if (size.x > 0) - { - auto t = p.x - coor.x; - test = t >= 0 && t < size.x; - } - else - { - auto t = p.x + coor.x; - test = t >= size.x && t < 0; - } + if (size.x > 0) { auto t = p.x - coor.x; test = t >= 0 && t < size.x; } + else { auto t = p.x + coor.x; test = t >= size.x && t < 0; } if (test) { - if (size.y > 0) - { - auto t = p.y - coor.y; - test = t >= 0 && t < size.y; - } - else - { - auto t = p.y + coor.y; - test = t >= size.y && t < 0; - } - return test; + if (size.y > 0) { auto t = p.y - coor.y; test = t >= 0 && t < size.y; } + else { auto t = p.y + coor.y; test = t >= size.y && t < 0; } } - return faux; + return test; } - rect rotate(twod dir) const + // rect: Return rect with specified orientation. + constexpr rect rotate(twod dir) const { - auto r = rect{}; - if ((dir.x ^ size.x) < 0) - { - r.coor.x = coor.x + size.x; - r.size.x = -size.x; - } - else - { - r.coor.x = coor.x; - r.size.x = size.x; - } - - if ((dir.y ^ size.y) < 0) - { - r.coor.y = coor.y + size.y; - r.size.y = -size.y; - } - else - { - r.coor.y = coor.y; - r.size.y = size.y; - } - return r; + auto sx = (dir.x ^ size.x) < 0; + auto sy = (dir.y ^ size.y) < 0; + return {{ sx ? coor.x + size.x : coor.x, sy ? coor.y + size.y : coor.y }, + { sx ? -size.x : size.x, sy ? -size.y : size.y }}; } - rect normalize() const + // rect: Change orientation. + constexpr auto& rotate_itself(twod dir) { - auto r = rect{}; - if (size.x < 0) - { - r.coor.x = coor.x + size.x; - r.size.x = -size.x; - } - else - { - r.coor.x = coor.x; - r.size.x = size.x; - } - - if (size.y < 0) - { - r.coor.y = coor.y + size.y; - r.size.y = -size.y; - } - else - { - r.coor.y = coor.y; - r.size.y = size.y; - } - - return r; + if ((dir.x ^ size.x) < 0) { coor.x += size.x; size.x = -size.x; } + if ((dir.y ^ size.y) < 0) { coor.y += size.y; size.y = -size.y; } + return *this; } - auto& normalize_itself() + // rect: Return rect with top-left orientation. + constexpr rect normalize() const { - if (size.x < 0) - { - coor.x = coor.x + size.x; - size.x = -size.x; - } - else - { - coor.x = coor.x; - size.x = size.x; - } - - if (size.y < 0) - { - coor.y = coor.y + size.y; - size.y = -size.y; - } - else - { - coor.y = coor.y; - size.y = size.y; - } + auto sx = size.x < 0; + auto sy = size.y < 0; + return {{ sx ? coor.x + size.x : coor.x, sy ? coor.y + size.y : coor.y }, + { sx ? -size.x : size.x , sy ? -size.y : size.y }}; + } + // rect: Set top-left orientation. + constexpr auto& normalize_itself() + { + if (size.x < 0) { coor.x += size.x; size.x = -size.x; } + if (size.y < 0) { coor.y += size.y; size.y = -size.y; } return *this; } // rect: Intersect the rect with rect{ dot_00, edge }. - rect trunc(twod edge) const + constexpr rect trunc(twod edge) const { auto r = rect{}; r.coor = std::clamp(coor, dot_00, edge); @@ -339,22 +296,23 @@ namespace netxs return r; } // rect: Return circumscribed rect. - rect unite(rect annex) const + static constexpr rect unite(rect r1, rect r2) { - auto r1 = annex.normalize(); - auto r2 = normalize(); + r1.normalize_itself(); + r2.normalize_itself(); auto tl = std::min(r1.coor, r2.coor); auto br = std::max(r1.coor + r1.size, r2.coor + r2.size ); return { tl, br - tl}; } // rect: Return true in case of normalized rectangles are overlapped. - bool overlap(rect r) const + constexpr bool overlap(rect r) const { return coor.x < r.coor.x + r.size.x && coor.y < r.coor.y + r.size.y && coor.x + size.x > r.coor.x && coor.y + size.y > r.coor.y; } + // rect: To string. auto str() const { return "{" + coor.str() + ", " + size.str() + "}"; diff --git a/src/netxs/desktopio/intmath.hpp b/src/netxs/desktopio/intmath.hpp index 01784f4026..b93dfe5aa9 100644 --- a/src/netxs/desktopio/intmath.hpp +++ b/src/netxs/desktopio/intmath.hpp @@ -830,12 +830,10 @@ namespace netxs { auto& rect1 = canvas.area(); auto& rect2 = bitmap.area(); - - if (auto joint = rect1.clip(rect2)) + if (auto joint = rect1.trim(rect2)) { auto basis = joint.coor - rect2.coor; joint.coor-= rect1.coor; - inbody(canvas, bitmap, joint, basis, handle, online); } } @@ -847,7 +845,7 @@ namespace netxs void onrect(T& canvas, Rect const& region, P handle, NewlineFx online = {}) { auto& place = canvas.area(); - if (auto joint = region.clip(place)) + if (auto joint = region.trim(place)) { auto basis = joint.coor - place.coor; auto frame = place.size.x * basis.y + basis.x + canvas.begin(); diff --git a/src/netxs/desktopio/richtext.hpp b/src/netxs/desktopio/richtext.hpp index b14124dea3..c918e8bae5 100644 --- a/src/netxs/desktopio/richtext.hpp +++ b/src/netxs/desktopio/richtext.hpp @@ -493,7 +493,7 @@ namespace netxs::ui //todo place is wrong if RtoL==true //rect place{ pos, { RtoL ? used, body.size().y } }; auto place = rect{ coord, { used, body.size().y } }; - auto joint = canvas.clip().clip(place); + auto joint = canvas.clip().trim(place); if (joint) { if constexpr (RtoL) @@ -2280,7 +2280,7 @@ namespace netxs::ui auto old_clip = core::clip(); if (trim) { - auto new_clip = core::area().clip(old_clip + delta); + auto new_clip = core::area().trim(old_clip + delta); core::clip(new_clip); } auto new_full = old_full + delta; @@ -2333,7 +2333,7 @@ namespace netxs::ui } } }; - auto nested_clip = trim ? core::clip().clip(object_area) : core::clip(); + auto nested_clip = trim ? core::clip().trim(object_area) : core::clip(); auto proceed = Forced || nested_clip; if (proceed) { diff --git a/src/netxs/desktopio/terminal.hpp b/src/netxs/desktopio/terminal.hpp index 26f4e3b825..74df5713b5 100644 --- a/src/netxs/desktopio/terminal.hpp +++ b/src/netxs/desktopio/terminal.hpp @@ -1994,12 +1994,12 @@ namespace netxs::ui auto east = rect{{ b, curtop.y }, { panel.x - b, size_0.y }}.normalize(); west.coor.x += clip.coor.x; // Compensate scrollback's hz movement. east.coor.x += clip.coor.x; // - west = west.clip(clip); - east = east.clip(clip); + west.trimby(clip); + east.trimby(clip); dest.fill(west, fill); dest.fill(east, fill); } - square = square.clip(clip); + square.trimby(clip); dest.fill(square, fill); }; _shade_selection(mode, work); @@ -2369,7 +2369,7 @@ namespace netxs::ui void do_viewport_copy(face& dest) override { auto full = dest.full(); - auto clip = dest.clip().clip(full); + auto clip = dest.clip().trim(full); dest.clip(clip); dest.plot(canvas, cell::shaders::full); } @@ -4501,7 +4501,7 @@ namespace netxs::ui auto find = selection_active() && match.length() && owner.selmod == mime::textonly; auto fill = [&](auto& area, auto chr) { - if (auto r = clip.clip(area)) + if (auto r = clip.trim(area)) { dest.fill(r, [&](auto& c){ c.txt(chr).fgc(tint::greenlt); }); } @@ -5673,7 +5673,7 @@ namespace netxs::ui void do_viewport_copy(face& dest) override { auto full = dest.full(); - auto clip = dest.clip().clip(full); + auto clip = dest.clip().trim(full); dest.clip(clip); auto vpos = clip.coor.y - y_top; if (vpos >= 0 && vpos < arena) @@ -5852,7 +5852,7 @@ namespace netxs::ui } if (upmid.role == grip::idle) return; auto scrolling_region = rect{{ -dot_mx.x / 2, batch.slide + y_top }, { dot_mx.x, arena }}; - clip = clip.clip(scrolling_region); + clip.trimby(scrolling_region); //todo Clang 15 don't get it //auto [curtop, curend] = selection_take_grips(); auto tempvr = selection_take_grips(); @@ -5865,7 +5865,7 @@ namespace netxs::ui auto area = grip_1 | grip_2; auto proc = [&](auto fx) { - dest.fill(area.clip(clip), fx); + dest.fill(area.trim(clip), fx); }; _shade_selection(mode, proc); } @@ -5895,15 +5895,16 @@ namespace netxs::ui auto width = curtop.y == curend.y ? curend.x - curtop.x + 1 : dot_mx.x; auto bound = rect{ curtop, { width, 1 }}.normalize(); - block = block.clip(bound); + block.trimby(bound); } else if (coord.y == curend.y) { auto bound = rect{ curend, { -dot_mx.x, 1 }}.normalize(); bound.size.x += 1; - block = block.clip(bound); + block.trimby(bound); } - dest.fill(block.clip(clip), fill); + block.trimby(clip); + dest.fill(block, fill); } }; while (head != tail && coor.y < stop) @@ -7505,7 +7506,7 @@ namespace netxs::ui bottom_oversize.coor.y += console.get_basis() + console.panel.y - console.scend; bottom_oversize.size.y = oversz.b; bottom_oversize.size.x += oversz.l + oversz.r; - bottom_oversize = bottom_oversize.clip(clip); + bottom_oversize = bottom_oversize.trim(clip); parent_canvas.fill(bottom_oversize, cell::shaders::xlight); } diff --git a/src/vtm.hpp b/src/vtm.hpp index 9027f0a154..07be2f8510 100644 --- a/src/vtm.hpp +++ b/src/vtm.hpp @@ -402,7 +402,7 @@ namespace netxs::app::vtm void convey(twod delta, rect boundary)//, bool notify = true) { auto& r0 = boss.base::area(); - if (delta && r0.clip(boundary)) + if (delta && r0.trim(boundary)) { auto r1 = r0; auto r2 = boundary; @@ -417,7 +417,7 @@ namespace netxs::app::vtm auto new_coor = c.normalize().coor + r2.coor; boss.moveto(new_coor); } - else if (!r2.clip(r0)) + else if (!r2.trim(r0)) { boss.moveby(delta); } @@ -582,7 +582,7 @@ namespace netxs::app::vtm { auto slot = data.slot; slot.coor -= canvas.coor(); - if (auto area = canvas.area().clip(slot)) + if (auto area = canvas.area().trim(slot)) { if (data.ctrl) { @@ -914,7 +914,7 @@ namespace netxs::app::vtm { SIGNAL(tier::request, e2::form::prop::viewport, viewport, ()); window.SIGNAL(tier::request, e2::form::prop::window::fullsize, object_area, ()); - auto outside = viewport.unite(object_area); + auto outside = viewport | object_area; if (outside != viewport) { auto coor = outside.coor.equals(object_area.coor, object_area.coor, outside.coor + outside.size - viewport.size); @@ -1133,13 +1133,13 @@ namespace netxs::app::vtm if (item != head && item != tail) { auto area = (**item).object->region; - if (!area.clip((**std::prev(item)).object->region)) + if (!area.trim((**std::prev(item)).object->region)) { auto shadow = *item; items.erase(std::next(item).base()); while (--item != head - && !area.clip((**std::prev(item)).object->region)) + && !area.trim((**std::prev(item)).object->region)) { } items.insert(item.base(), shadow); diff --git a/src/vtm.xml b/src/vtm.xml index f966da291a..6ab53dfdfa 100644 --- a/src/vtm.xml +++ b/src/vtm.xml @@ -283,7 +283,7 @@ R"==( - +