Skip to content

Commit

Permalink
Add scaling. (#10)
Browse files Browse the repository at this point in the history
Closes #6.
  • Loading branch information
matanlurey authored Aug 31, 2024
1 parent ba4ea33 commit 48fd1a1
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 0 deletions.
25 changes: 25 additions & 0 deletions lib/src/buffer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ part 'buffer/map.dart';
part 'buffer/pixels_float.dart';
part 'buffer/pixels_int.dart';
part 'buffer/pixels.dart';
part 'buffer/scaled.dart';

/// A 2-dimensional _view_ of pixel data [T] in memory.
///
Expand Down Expand Up @@ -171,6 +172,30 @@ abstract base mixin class Buffer<T extends Object?> {
return _ClippedBuffer(this, result);
}

/// Returns a lazy buffer that scales the buffer by the given factor.
///
/// The returned buffer will have the same dimensions as the original buffer
/// multiplied by the scale factor. The scale factor must be greater than 0.
///
/// ## Example
///
/// ```dart
/// final buffer = IntPixels(2, 2, data: Uint32List.fromList([
/// abgr8888.red, abgr8888.green,
/// abgr8888.blue, abgr8888.magenta,
/// ]));
///
/// final scaled = buffer.mapScaled(2);
/// print(scaled.data); // [0xFFFF0000, 0xFFFF0000, 0xFF00FF00, 0xFF00FF00, 0xFF0000FF, 0xFF0000FF, 0xFFFF00FF, 0xFFFF00FF]
/// ```
Buffer<T> mapScaled(int scale) {
RangeError.checkNotNegative(scale, 'scale');
if (scale == 1) {
return this;
}
return _ScaledBuffer(this, scale);
}

/// Returns a lazy iterable of pixels in the buffer from [start] to [end].
///
/// The returned iterable will contain all pixels in the buffer that are
Expand Down
26 changes: 26 additions & 0 deletions lib/src/buffer/scaled.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
part of '../buffer.dart';

final class _ScaledBuffer<T> extends _Buffer<T> {
const _ScaledBuffer(super._source, this._scale);
final int _scale;

@override
Iterable<T> get data {
return Iterable.generate(length, (i) {
final pos = Pos(i % width, i ~/ width);
return getUnsafe(pos);
});
}

@override
T getUnsafe(Pos pos) {
final sourcePos = pos ~/ _scale;
return _source.getUnsafe(sourcePos);
}

@override
int get width => _source.width * _scale;

@override
int get height => _source.height * _scale;
}
34 changes: 34 additions & 0 deletions test/buffer_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,40 @@ void main() {
).throws<ArgumentError>();
});

test('mapScaled', () {
final buffer = IntPixels(
2,
2,
data: Uint32List.fromList([
abgr8888.red,
abgr8888.green,
abgr8888.blue,
abgr8888.cyan,
]),
);
final scaled = buffer.mapScaled(2);
check(scaled.width).equals(4);
check(scaled.height).equals(4);
check(scaled.data).deepEquals([
abgr8888.red,
abgr8888.red,
abgr8888.green,
abgr8888.green,
abgr8888.red,
abgr8888.red,
abgr8888.green,
abgr8888.green,
abgr8888.blue,
abgr8888.blue,
abgr8888.cyan,
abgr8888.cyan,
abgr8888.blue,
abgr8888.blue,
abgr8888.cyan,
abgr8888.cyan,
]);
});

group('compare', () {
test('different width returns difference = 1.0', () {
final a = IntPixels(2, 2);
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 34 additions & 0 deletions test/golden_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,38 @@ void main() {
uncompressedPngEncoder.convert(output),
);
});

test('blit with embedded font and scaling', () {
// We are going to write the word "PXL" in the terminal8x8Font.
// The font is stored in code page 437 tile order.
final $P = Pos(00, 5) * 8;
final $X = Pos(08, 5) * 8;
final $L = Pos(12, 4) * 8;

final output = IntPixels(24 * 4, 8 * 4)..fill(abgr8888.black);
final scaled = terminal8x8Font.mapScaled(4);

output.blit(
scaled,
target: Pos(00, 00),
source: Rect.fromWH(8 * 4, 8 * 4, offset: $P * 4),
);

output.blit(
scaled,
target: Pos(08 * 4, 00),
source: Rect.fromWH(8 * 4, 8 * 4, offset: $X * 4),
);

output.blit(
scaled,
target: Pos(16 * 4, 00),
source: Rect.fromWH(8 * 4, 8 * 4, offset: $L * 4),
);

checkOrUpdateGolden(
'blit_with_embedded_font_and_scaling',
uncompressedPngEncoder.convert(output),
);
});
}

0 comments on commit 48fd1a1

Please sign in to comment.