renderNinepatch
Renders a ninepatch with the given parameters.
Only valid between Window.beginand Window.end.
Parameters
- ninepatch:Ninepatch
- Ninepatch
- rs:RectScale
- RectScale
- opts:NinepatchOptions
- NinepatchOptions
Source
Implementation
pub fn renderNinepatch(ninepatch: Ninepatch, rs: RectScale, opts: NinepatchOptions) Backend.GenericError!void {
if (ninepatch.source.imageFile.bytes.len == 0) return;
if (rs.s == 0) return;
if (rs.r.empty()) return;
if (dvui.clipGet().intersect(rs.r).empty()) return;
const tex = ninepatch.source.getTexture() catch |err| {
dvui.log.err("renderNinepatch() got {any}", .{err});
return;
};
var rect = rs.r;
if (dvui.currentWindow().snap_to_pixels) {
rect.x = @round(rect.x);
rect.y = @round(rect.y);
}
const ts: Size = .{
.w = @floatFromInt(tex.width),
.h = @floatFromInt(tex.width),
};
// scale ninepatch edge size
const e = ninepatch.edge.scale(rs.s, Rect.Physical);
// middle
var r = rect.inset(e);
if (!r.empty()) {
try renderTexture(tex, .{ .r = r, .s = rs.s }, .{
.uv = .{
.x = ninepatch.edge.x / ts.w,
.w = (ts.w - ninepatch.edge.x - ninepatch.edge.w) / ts.w,
.y = ninepatch.edge.y / ts.h,
.h = (ts.h - ninepatch.edge.y - ninepatch.edge.h) / ts.h,
},
.debug = opts.debug,
});
}
// top and bottom edges
r = rect.inset(.{ .x = e.x, .w = e.w });
if (!r.empty()) {
// bottom first, draw as much as possible from bottom up
var height = @min(r.h, e.h);
const bottom = r.y + r.h;
var th = height / rs.s;
try renderTexture(tex, .{ .r = .{
.x = r.x,
.w = r.w,
.y = bottom - height,
.h = height,
}, .s = rs.s }, .{
.uv = .{
.x = ninepatch.edge.x / ts.w,
.w = (ts.w - ninepatch.edge.x - ninepatch.edge.w) / ts.w,
.y = (ts.h - th) / ts.h,
.h = th / ts.h,
},
.debug = opts.debug,
});
// top edge
height = @min(r.h, e.y);
th = height / rs.s;
try renderTexture(tex, .{ .r = .{
.x = r.x,
.w = r.w,
.y = r.y,
.h = height,
}, .s = rs.s }, .{
.uv = .{
.x = ninepatch.edge.x / ts.w,
.w = (ts.w - ninepatch.edge.x - ninepatch.edge.w) / ts.w,
.y = 0,
.h = th / ts.h,
},
.debug = opts.debug,
});
}
// left and right edges
r = rect.inset(.{ .y = e.y, .h = e.h });
if (!r.empty()) {
// right first, draw from right edge
var width = @min(r.w, e.w);
const right = r.x + r.w;
var tw = width / rs.s;
try renderTexture(tex, .{ .r = .{
.x = right - width,
.w = width,
.y = r.y,
.h = r.h,
}, .s = rs.s }, .{
.uv = .{
.x = (ts.w - tw) / ts.w,
.w = tw / ts.w,
.y = ninepatch.edge.y / ts.h,
.h = (ts.h - ninepatch.edge.y - ninepatch.edge.h) / ts.h,
},
.debug = opts.debug,
});
// left
width = @min(r.w, e.x);
tw = width / rs.s;
try renderTexture(tex, .{ .r = .{
.x = r.x,
.w = width,
.y = r.y,
.h = r.h,
}, .s = rs.s }, .{
.uv = .{
.x = 0,
.w = tw / ts.w,
.y = ninepatch.edge.y / ts.h,
.h = (ts.h - ninepatch.edge.y - ninepatch.edge.h) / ts.h,
},
.debug = opts.debug,
});
}
// bottom right corner
{
r = rect;
const width = @min(r.w, e.w);
const tw = width / rs.s;
const height = @min(r.h, e.h);
const th = height / rs.s;
if (!r.empty()) {
try renderTexture(tex, .{ .r = .{
.x = r.x + r.w - width,
.w = width,
.y = r.y + r.h - height,
.h = height,
}, .s = rs.s }, .{
.uv = .{
.x = (ts.w - tw) / ts.w,
.w = tw / ts.w,
.y = (ts.h - th) / ts.h,
.h = th / ts.h,
},
.debug = opts.debug,
});
}
}
// bottom left corner
{
r = rect;
const width = @min(r.w, e.x);
const tw = width / rs.s;
const height = @min(r.h, e.h);
const th = height / rs.s;
if (!r.empty()) {
try renderTexture(tex, .{ .r = .{
.x = r.x,
.w = width,
.y = r.y + r.h - height,
.h = height,
}, .s = rs.s }, .{
.uv = .{
.x = 0,
.w = tw / ts.w,
.y = (ts.h - th) / ts.h,
.h = th / ts.h,
},
.debug = opts.debug,
});
}
}
// top right corner
{
r = rect;
const width = @min(r.w, e.w);
const tw = width / rs.s;
const height = @min(r.h, e.y);
const th = height / rs.s;
if (!r.empty()) {
try renderTexture(tex, .{ .r = .{
.x = r.x + r.w - width,
.w = width,
.y = r.y,
.h = height,
}, .s = rs.s }, .{
.uv = .{
.x = (ts.w - tw) / ts.w,
.w = tw / ts.w,
.y = 0,
.h = th / ts.h,
},
.debug = opts.debug,
});
}
}
// top left corner
{
r = rect;
const width = @min(r.w, e.x);
const tw = width / rs.s;
const height = @min(r.h, e.y);
const th = height / rs.s;
if (!r.empty()) {
try renderTexture(tex, .{ .r = .{
.x = r.x,
.w = width,
.y = r.y,
.h = height,
}, .s = rs.s }, .{
.uv = .{
.x = 0,
.w = tw / ts.w,
.y = 0,
.h = th / ts.h,
},
.debug = opts.debug,
});
}
}
}