Skip to content

Commit

Permalink
Merge v1.0.7
Browse files Browse the repository at this point in the history
- `PCanvasPainter`:
  - Added `zIndex` to define the painter layer. Previously was fixed to `0`.
- Added `PCanvasFactory`:
  - Allows extra platform dependent implementations: - `pixelsToPNG` and `pixelsToDataUrl`
- `PCanvasBitmap.toPNG`:
  - Ensure `singleFrame: true`
  • Loading branch information
gmpassos authored Jan 9, 2023
2 parents 7412689 + c0b1131 commit 56ada5f
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 81 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
## 1.0.7

- `PCanvasPainter`:
- Added `zIndex` to define the painter layer. Previously was fixed to `0`.
- Added `PCanvasFactory`:
- Allows extra platform dependent implementations:
- `pixelsToPNG` and `pixelsToDataUrl`
- `PCanvasBitmap.toPNG`:
- Ensure `singleFrame: true`

## 1.0.6

- `PCanvas`:
Expand Down
50 changes: 36 additions & 14 deletions lib/src/pcanvas_base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,12 @@ abstract class PCanvasPainter {
_pCanvas = pCanvas;
}

/// Returns the `z-index` of the painter layer. Default: 0
///
/// - Elements with [PCanvasElement.zIndex] `<` than [zIndex] will be painted before the painter layer.
/// - Elements with [PCanvasElement.zIndex] `>=` than [zIndex] will be painted after the painter layer.
int get zIndex => 0;

FutureOr<bool>? _loadingFuture;

/// Waits the [loadResources].
Expand Down Expand Up @@ -260,6 +266,27 @@ class PCanvasPainterDummy extends PCanvasPainter {
FutureOr<bool> paint(PCanvas pCanvas) => true;
}

abstract class PCanvasFactory {
PCanvasFactory.impl();

factory PCanvasFactory() {
return createPCanvasFactoryImpl();
}

PCanvas createPCanvas(int width, int height, PCanvasPainter painter,
{PCanvasPixels? initialPixels});

FutureOr<Uint8List> pixelsToPNG(PCanvasPixels pixels) {
var pCanvas = pixels.toPCanvas();
return pCanvas.toPNG();
}

FutureOr<String> pixelsToDataUrl(PCanvasPixels pixels) {
var pCanvas = pixels.toPCanvas();
return pCanvas.toDataUrl();
}
}

typedef PaintFuntion = FutureOr<bool> Function(PCanvas pCanvas);

/// Portable Canvas.
Expand Down Expand Up @@ -288,8 +315,8 @@ abstract class PCanvas

factory PCanvas(int width, int height, PCanvasPainter painter,
{PCanvasPixels? initialPixels}) {
return createPCanvasImpl(width, height, painter,
initialPixels: initialPixels);
return PCanvasFactory()
.createPCanvas(width, height, painter, initialPixels: initialPixels);
}

/// Sets the canvas pixels.
Expand Down Expand Up @@ -519,6 +546,9 @@ abstract class PCanvas
}

FutureOr<bool> _callPainterImpl() {
final painter = this.painter;
final painterZIndex = painter.zIndex;

var hasElements = _elements.isNotEmpty;

List<PCanvasElement>? elementsPrev;
Expand All @@ -527,17 +557,15 @@ abstract class PCanvas
if (hasElements) {
elementsPrev = _elements.where((e) {
var zIndex = e.zIndex;
return zIndex != null && zIndex < 0;
return zIndex != null && zIndex < painterZIndex;
}).toList();

elementsPos = _elements.where((e) {
var zIndex = e.zIndex;
return zIndex == null || zIndex >= 0;
return zIndex == null || zIndex >= painterZIndex;
}).toList();
}

final painter = this.painter;

FutureOr<bool> ret = true;

if (elementsPrev != null) {
Expand Down Expand Up @@ -1033,15 +1061,9 @@ abstract class PCanvasPixels {
return pCanvas;
}

FutureOr<Uint8List> toPNG() {
var pCanvas = toPCanvas();
return pCanvas.toPNG();
}
FutureOr<Uint8List> toPNG() => PCanvasFactory().pixelsToPNG(this);

FutureOr<String> toDataUrl() {
var pCanvas = toPCanvas();
return pCanvas.toDataUrl();
}
FutureOr<String> toDataUrl() => PCanvasFactory().pixelsToDataUrl(this);

@override
String toString() {
Expand Down
62 changes: 2 additions & 60 deletions lib/src/pcanvas_bitmap.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:dio/dio.dart';
import 'package:image/image.dart' as img;

import 'pcanvas_base.dart';
import 'pcanvas_bitmap_extension.dart';

/// An in-memory [PCanvas] implementation.
class PCanvasBitmap extends PCanvas {
Expand Down Expand Up @@ -754,7 +755,7 @@ class PCanvasBitmap extends PCanvas {
PCanvasPixelsABGR.fromBytes(width, height, _bitmap.dataAsUint8List);

@override
FutureOr<Uint8List> toPNG() => img.encodePng(_bitmap);
FutureOr<Uint8List> toPNG() => img.encodePng(_bitmap, singleFrame: true);

@override
String toString() {
Expand Down Expand Up @@ -904,65 +905,6 @@ class _PCanvasImageMemoryAsync extends PCanvasImageMemory {
}
}

extension _PFontExtension on PFont {
img.BitmapFont toBitmapFontFamily() {
if (size >= 36) {
return img.arial48;
} else if (size >= 19) {
return img.arial24;
} else {
return img.arial14;
}
}

img.BitmapFont toBitmapFont() {
var f = toBitmapFontFamily();
if (bold) f.bold = true;
if (italic) f.italic = true;
f.antialias = true;
return f;
}
}

extension _PCanvasPixelsExtension on PCanvasPixels {
img.Color getImageColor(int x, int y) {
var pixels = this;

var p = pixels.pixel(x, y);

int r, g, b, a;

if (pixels is PCanvasPixelsRGBA) {
r = (p >> 24) & 0xff;
g = (p >> 16) & 0xff;
b = (p >> 8) & 0xff;
a = ((p) & 0xff);
} else if (pixels is PCanvasPixelsARGB) {
r = (p >> 16) & 0xff;
g = (p >> 8) & 0xff;
b = (p) & 0xff;
a = ((p >> 24) & 0xff);
} else if (pixels is PCanvasPixelsABGR) {
r = (p) & 0xff;
g = (p >> 8) & 0xff;
b = (p >> 16) & 0xff;
a = ((p >> 24) & 0xff);
} else {
throw StateError("Can't pixels type: ${pixels.runtimeType} > $pixels");
}

return img.ColorUint32.rgba(r, g, b, a);
}
}

extension _ImageExtension on img.Image {
Uint8List get dataAsUint8List {
var imageData = data as img.ImageDataUint8;
var dataUint8 = imageData.data;
return dataUint8;
}
}

// From package `image 3.3.0`.
int _findStringHeight(img.BitmapFont font, String string) {
var stringHeight = 0;
Expand Down
87 changes: 87 additions & 0 deletions lib/src/pcanvas_bitmap_extension.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import 'dart:typed_data';

import 'package:image/image.dart' as img;

import 'pcanvas_base.dart';

extension PFontExtension on PFont {
img.BitmapFont toBitmapFontFamily() {
if (size >= 36) {
return img.arial48;
} else if (size >= 19) {
return img.arial24;
} else {
return img.arial14;
}
}

img.BitmapFont toBitmapFont() {
var f = toBitmapFontFamily();
if (bold) f.bold = true;
if (italic) f.italic = true;
f.antialias = true;
return f;
}
}

extension PCanvasPixelsExtension on PCanvasPixels {
img.Color getImageColor(int x, int y) {
var pixels = this;

var p = pixels.pixel(x, y);

int r, g, b, a;

if (pixels is PCanvasPixelsRGBA) {
r = (p >> 24) & 0xff;
g = (p >> 16) & 0xff;
b = (p >> 8) & 0xff;
a = ((p) & 0xff);
} else if (pixels is PCanvasPixelsARGB) {
r = (p >> 16) & 0xff;
g = (p >> 8) & 0xff;
b = (p) & 0xff;
a = ((p >> 24) & 0xff);
} else if (pixels is PCanvasPixelsABGR) {
r = (p) & 0xff;
g = (p >> 8) & 0xff;
b = (p >> 16) & 0xff;
a = ((p >> 24) & 0xff);
} else {
throw StateError("Can't pixels type: ${pixels.runtimeType} > $pixels");
}

return img.ColorUint32.rgba(r, g, b, a);
}

Uint8List pixelsToImagePNG() {
final pixels = this;

var w = pixels.width;
var h = pixels.height;

var bitmap = img.Image(
width: w,
height: h,
format: img.Format.uint8,
numChannels: 4,
withPalette: false);

for (var y = 0; y < h; ++y) {
for (var x = 0; x < w; ++x) {
var p = pixels.getImageColor(x, y);
bitmap.setPixel(x, y, p);
}
}

return img.encodePng(bitmap, singleFrame: true);
}
}

extension ImageExtension on img.Image {
Uint8List get dataAsUint8List {
var imageData = data as img.ImageDataUint8;
var dataUint8 = imageData.data;
return dataUint8;
}
}
21 changes: 18 additions & 3 deletions lib/src/pcanvas_impl_bitmap.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
import 'dart:typed_data';

import 'pcanvas_base.dart';
import 'pcanvas_bitmap.dart';
import 'pcanvas_bitmap_extension.dart';

class PCanvasFactoryBitmap extends PCanvasFactory {
static final PCanvasFactoryBitmap instance = PCanvasFactoryBitmap._();

PCanvasFactoryBitmap._() : super.impl();

@override
PCanvas createPCanvas(int width, int height, PCanvasPainter painter,
{PCanvasPixels? initialPixels}) =>
PCanvasBitmap(width, height, painter, initialPixels: initialPixels);

@override
Uint8List pixelsToPNG(PCanvasPixels pixels) => pixels.pixelsToImagePNG();
}

PCanvas createPCanvasImpl(int width, int height, PCanvasPainter painter,
{PCanvasPixels? initialPixels}) =>
PCanvasBitmap(width, height, painter, initialPixels: initialPixels);
PCanvasFactory createPCanvasFactoryImpl() => PCanvasFactoryBitmap.instance;
15 changes: 12 additions & 3 deletions lib/src/pcanvas_impl_html.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import 'pcanvas_base.dart';
import 'pcanvas_html.dart';

PCanvas createPCanvasImpl(int width, int height, PCanvasPainter painter,
{PCanvasPixels? initialPixels}) =>
PCanvasHTML(width, height, painter, initialPixels: initialPixels);
class PCanvasFactoryHTML extends PCanvasFactory {
static final PCanvasFactoryHTML instance = PCanvasFactoryHTML._();

PCanvasFactoryHTML._() : super.impl();

@override
PCanvas createPCanvas(int width, int height, PCanvasPainter painter,
{PCanvasPixels? initialPixels}) =>
PCanvasHTML(width, height, painter, initialPixels: initialPixels);
}

PCanvasFactory createPCanvasFactoryImpl() => PCanvasFactoryHTML.instance;
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: pcanvas
description: A portable canvas that can work in many platforms (Flutter, Web, Desktop, in-memory Image).
version: 1.0.6
version: 1.0.7
homepage: https://github.com/gmpassos/pcanvas

environment:
Expand Down

0 comments on commit 56ada5f

Please sign in to comment.