Refactor blocks

This commit is contained in:
Elias Batek 2024-04-24 03:00:47 +02:00
parent 23e3d59538
commit 486195859c
1 changed files with 161 additions and 164 deletions

View File

@ -219,191 +219,188 @@ private struct OriginRectangle {
} }
} }
private {
@safe pure nothrow @nogc: @safe pure nothrow @nogc:
// misc
private {
Point pos(Rectangle r) => r.upperLeft; Point pos(Rectangle r) => r.upperLeft;
} }
// Alpha-blending functions // ==== Alpha-blending functions ====
@safe pure nothrow @nogc {
/// ///
public void alphaBlend(scope Pixel[] target, scope const Pixel[] source) @trusted public void alphaBlend(scope Pixel[] target, scope const Pixel[] source) @trusted
in (source.length == target.length) { in (source.length == target.length) {
foreach (immutable idx, ref pxtarget; target) { foreach (immutable idx, ref pxtarget; target) {
alphaBlend(pxtarget, source.ptr[idx]); alphaBlend(pxtarget, source.ptr[idx]);
}
}
///
public void alphaBlend(ref Pixel pxTarget, const Pixel pxSource) @trusted {
pragma(inline, true);
immutable alphaSource = (pxSource.a | (pxSource.a << 8));
immutable alphaTarget = (0xFFFF - alphaSource);
foreach (immutable ib, ref px; pxTarget.components) {
immutable d = cast(ubyte)(((px * alphaTarget) + 0x8080) >> 16);
immutable s = cast(ubyte)(((pxSource.components.ptr[ib] * alphaSource) + 0x8080) >> 16);
px = cast(ubyte)(d + s);
}
} }
} }
// Drawing functions ///
@safe pure nothrow @nogc { public void alphaBlend(ref Pixel pxTarget, const Pixel pxSource) @trusted {
pragma(inline, true);
/++ immutable alphaSource = (pxSource.a | (pxSource.a << 8));
Draws a single pixel immutable alphaTarget = (0xFFFF - alphaSource);
+/
void drawPixel(Pixmap target, Point pos, Pixel color) { foreach (immutable ib, ref px; pxTarget.components) {
immutable size_t offset = linearOffset(target.width, pos); immutable d = cast(ubyte)(((px * alphaTarget) + 0x8080) >> 16);
immutable s = cast(ubyte)(((pxSource.components.ptr[ib] * alphaSource) + 0x8080) >> 16);
px = cast(ubyte)(d + s);
}
}
// ==== Drawing functions ====
/++
Draws a single pixel
+/
void drawPixel(Pixmap target, Point pos, Pixel color) {
immutable size_t offset = linearOffset(target.width, pos);
target.data[offset] = color;
}
/++
Draws a rectangle
+/
void drawRectangle(Pixmap target, Rectangle rectangle, Pixel color) {
alias r = rectangle;
immutable tRect = OriginRectangle(
Size(target.width, target.height),
);
// out of bounds?
if (!tRect.intersect(r)) {
return;
}
immutable drawingTarget = Point(
(r.pos.x >= 0) ? r.pos.x : 0,
(r.pos.y >= 0) ? r.pos.y : 0,
);
immutable drawingEnd = Point(
(r.right < tRect.right) ? r.right : tRect.right,
(r.bottom < tRect.bottom) ? r.bottom : tRect.bottom,
);
immutable int drawingWidth = drawingEnd.x - drawingTarget.x;
foreach (y; drawingTarget.y .. drawingEnd.y) {
target.sliceAt(Point(drawingTarget.x, y), drawingWidth)[] = color;
}
}
/++
Draws a line
+/
void drawLine(Pixmap target, Point a, Point b, Pixel color) {
import std.math : round, sqrt;
// TODO: line width
// TODO: anti-aliasing (looks awful without it!)
float deltaX = b.x - a.x;
float deltaY = b.y - a.y;
int steps = sqrt(deltaX * deltaX + deltaY * deltaY).typeCast!int;
float[2] step = [
(deltaX / steps),
(deltaY / steps),
];
foreach (i; 0 .. steps) {
// dfmt off
immutable Point p = a + Point(
round(step[0] * i).typeCast!int,
round(step[1] * i).typeCast!int,
);
// dfmt on
immutable offset = linearOffset(p, target.width);
target.data[offset] = color; target.data[offset] = color;
} }
/++ immutable offsetEnd = linearOffset(b, target.width);
Draws a rectangle target.data[offsetEnd] = color;
+/ }
void drawRectangle(Pixmap target, Rectangle rectangle, Pixel color) {
alias r = rectangle;
immutable tRect = OriginRectangle( /++
Size(target.width, target.height), Draws an image (a source pixmap) on a target pixmap
);
// out of bounds? Params:
if (!tRect.intersect(r)) { target = target pixmap to draw on
return; image = source pixmap
} pos = top-left destination position (on the target pixmap)
+/
void drawPixmap(Pixmap target, Pixmap image, Point pos) {
alias source = image;
immutable drawingTarget = Point( immutable tRect = OriginRectangle(
(r.pos.x >= 0) ? r.pos.x : 0, Size(target.width, target.height),
(r.pos.y >= 0) ? r.pos.y : 0, );
);
immutable drawingEnd = Point( immutable sRect = Rectangle(pos, source.size);
(r.right < tRect.right) ? r.right : tRect.right,
(r.bottom < tRect.bottom) ? r.bottom : tRect.bottom,
);
immutable int drawingWidth = drawingEnd.x - drawingTarget.x; // out of bounds?
if (!tRect.intersect(sRect)) {
foreach (y; drawingTarget.y .. drawingEnd.y) { return;
target.sliceAt(Point(drawingTarget.x, y), drawingWidth)[] = color;
}
} }
/++ immutable drawingTarget = Point(
Draws a line (pos.x >= 0) ? pos.x : 0,
+/ (pos.y >= 0) ? pos.y : 0,
void drawLine(Pixmap target, Point a, Point b, Pixel color) { );
import std.math : round, sqrt;
// TODO: line width immutable drawingEnd = Point(
// TODO: anti-aliasing (looks awful without it!) (sRect.right < tRect.right) ? sRect.right : tRect.right,
(sRect.bottom < tRect.bottom) ? sRect.bottom : tRect.bottom,
);
float deltaX = b.x - a.x; immutable drawingSource = Point(drawingTarget.x, 0) - Point(sRect.pos.x, sRect.pos.y);
float deltaY = b.y - a.y; immutable int drawingWidth = drawingEnd.x - drawingTarget.x;
int steps = sqrt(deltaX * deltaX + deltaY * deltaY).typeCast!int;
float[2] step = [ foreach (y; drawingTarget.y .. drawingEnd.y) {
(deltaX / steps), target.sliceAt(Point(drawingTarget.x, y), drawingWidth)[] =
(deltaY / steps), source.sliceAt(Point(drawingSource.x, y + drawingSource.y), drawingWidth);
]; }
}
foreach (i; 0 .. steps) {
// dfmt off /++
immutable Point p = a + Point( Draws a sprite from a spritesheet
round(step[0] * i).typeCast!int, +/
round(step[1] * i).typeCast!int, void drawSprite(Pixmap target, const SpriteSheet sheet, int spriteIndex, Point pos) {
); immutable tRect = OriginRectangle(
// dfmt on Size(target.width, target.height),
);
immutable offset = linearOffset(p, target.width);
target.data[offset] = color; immutable spriteOffset = sheet.getSpritePixelOffset2D(spriteIndex);
} immutable sRect = Rectangle(pos, sheet.spriteSize);
immutable offsetEnd = linearOffset(b, target.width); // out of bounds?
target.data[offsetEnd] = color; if (!tRect.intersect(sRect)) {
} return;
}
/++
Draws an image (a source pixmap) on a target pixmap immutable drawingTarget = Point(
(pos.x >= 0) ? pos.x : 0,
Params: (pos.y >= 0) ? pos.y : 0,
target = target pixmap to draw on );
image = source pixmap
pos = top-left destination position (on the target pixmap) immutable drawingEnd = Point(
+/ (sRect.right < tRect.right) ? sRect.right : tRect.right,
void drawPixmap(Pixmap target, Pixmap image, Point pos) { (sRect.bottom < tRect.bottom) ? sRect.bottom : tRect.bottom,
alias source = image; );
immutable tRect = OriginRectangle( immutable drawingSource =
Size(target.width, target.height), spriteOffset
); + Point(drawingTarget.x, 0)
- Point(sRect.pos.x, sRect.pos.y);
immutable sRect = Rectangle(pos, source.size); immutable int drawingWidth = drawingEnd.x - drawingTarget.x;
// out of bounds? foreach (y; drawingTarget.y .. drawingEnd.y) {
if (!tRect.intersect(sRect)) { target.sliceAt(Point(drawingTarget.x, y), drawingWidth)[]
return; = sheet.pixmap.sliceAt(Point(drawingSource.x, y + drawingSource.y), drawingWidth);
}
immutable drawingTarget = Point(
(pos.x >= 0) ? pos.x : 0,
(pos.y >= 0) ? pos.y : 0,
);
immutable drawingEnd = Point(
(sRect.right < tRect.right) ? sRect.right : tRect.right,
(sRect.bottom < tRect.bottom) ? sRect.bottom : tRect.bottom,
);
immutable drawingSource = Point(drawingTarget.x, 0) - Point(sRect.pos.x, sRect.pos.y);
immutable int drawingWidth = drawingEnd.x - drawingTarget.x;
foreach (y; drawingTarget.y .. drawingEnd.y) {
target.sliceAt(Point(drawingTarget.x, y), drawingWidth)[] =
source.sliceAt(Point(drawingSource.x, y + drawingSource.y), drawingWidth);
}
}
/++
Draws a sprite from a spritesheet
+/
void drawSprite(Pixmap target, const SpriteSheet sheet, int spriteIndex, Point pos) {
immutable tRect = OriginRectangle(
Size(target.width, target.height),
);
immutable spriteOffset = sheet.getSpritePixelOffset2D(spriteIndex);
immutable sRect = Rectangle(pos, sheet.spriteSize);
// out of bounds?
if (!tRect.intersect(sRect)) {
return;
}
immutable drawingTarget = Point(
(pos.x >= 0) ? pos.x : 0,
(pos.y >= 0) ? pos.y : 0,
);
immutable drawingEnd = Point(
(sRect.right < tRect.right) ? sRect.right : tRect.right,
(sRect.bottom < tRect.bottom) ? sRect.bottom : tRect.bottom,
);
immutable drawingSource =
spriteOffset
+ Point(drawingTarget.x, 0)
- Point(sRect.pos.x, sRect.pos.y);
immutable int drawingWidth = drawingEnd.x - drawingTarget.x;
foreach (y; drawingTarget.y .. drawingEnd.y) {
target.sliceAt(Point(drawingTarget.x, y), drawingWidth)[]
= sheet.pixmap.sliceAt(Point(drawingSource.x, y + drawingSource.y), drawingWidth);
}
} }
} }