Skip to content
683 changes: 682 additions & 1 deletion lib/components/canvas/_asset_cache.dart

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions lib/components/canvas/image/editor_image.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ sealed class EditorImage extends ChangeNotifier {
final String extension;

final AssetCache assetCache;
final AssetCacheAll assetCacheAll;

bool _isThumbnail = false;
bool get isThumbnail => _isThumbnail;
Expand Down Expand Up @@ -89,6 +90,7 @@ sealed class EditorImage extends ChangeNotifier {
EditorImage({
required this.id,
required this.assetCache,
required this.assetCacheAll,
required this.extension,
required this.pageIndex,
required this.pageSize,
Expand All @@ -113,6 +115,7 @@ sealed class EditorImage extends ChangeNotifier {
bool isThumbnail = false,
required String sbnPath,
required AssetCache assetCache,
required AssetCacheAll assetCacheAll,
}) {
String? extension = json['e'];
if (extension == '.svg') {
Expand All @@ -122,6 +125,7 @@ sealed class EditorImage extends ChangeNotifier {
isThumbnail: isThumbnail,
sbnPath: sbnPath,
assetCache: assetCache,
assetCacheAll: assetCacheAll,
);
} else if (extension == '.pdf') {
return PdfEditorImage.fromJson(
Expand All @@ -130,6 +134,7 @@ sealed class EditorImage extends ChangeNotifier {
isThumbnail: isThumbnail,
sbnPath: sbnPath,
assetCache: assetCache,
assetCacheAll: assetCacheAll,
);
} else {
return PngEditorImage.fromJson(
Expand All @@ -138,6 +143,7 @@ sealed class EditorImage extends ChangeNotifier {
isThumbnail: isThumbnail,
sbnPath: sbnPath,
assetCache: assetCache,
assetCacheAll: assetCacheAll,
);
}
}
Expand Down
40 changes: 33 additions & 7 deletions lib/components/canvas/image/pdf_editor_image.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
part of 'editor_image.dart';

class PdfEditorImage extends EditorImage {
/// index of asset assigned to this pdf file
int assetId;

Uint8List? pdfBytes;
final int pdfPage;

Expand All @@ -15,6 +18,8 @@ class PdfEditorImage extends EditorImage {
PdfEditorImage({
required super.id,
required super.assetCache,
required super.assetCacheAll,
required this.assetId,
required this.pdfBytes,
required this.pdfFile,
required this.pdfPage,
Expand Down Expand Up @@ -45,20 +50,22 @@ class PdfEditorImage extends EditorImage {
bool isThumbnail = false,
required String sbnPath,
required AssetCache assetCache,
required AssetCacheAll assetCacheAll,
}) {
String? extension = json['e'] as String?;
assert(extension == null || extension == '.pdf');

final assetIndex = json['a'] as int?;
final assetIndexJson = json['a'] as int?;
final Uint8List? pdfBytes;
int? assetIndex;
File? pdfFile;
if (assetIndex != null) {
if (assetIndexJson != null) {
if (inlineAssets == null) {
pdfFile =
FileManager.getFile('$sbnPath${Editor.extension}.$assetIndex');
FileManager.getFile('$sbnPath${Editor.extension}.$assetIndexJson');
pdfBytes = assetCache.get(pdfFile);
} else {
pdfBytes = inlineAssets[assetIndex];
pdfBytes = inlineAssets[assetIndexJson];
}
} else {
if (kDebugMode) {
Expand All @@ -67,10 +74,26 @@ class PdfEditorImage extends EditorImage {
pdfBytes = Uint8List(0);
}

assert(pdfBytes != null || pdfFile != null,
'Either pdfBytes or pdfFile must be non-null');

// add to asset cache
if (pdfFile != null) {
assetIndex = assetCacheAll.addSync(pdfFile);
}
else {
assetIndex = assetCacheAll.addSync(pdfBytes!);
}
if (assetIndex<0){
throw Exception('EditorImage.fromJson: pdf image not in assets');
}

return PdfEditorImage(
id: json['id'] ??
-1, // -1 will be replaced by EditorCoreInfo._handleEmptyImageIds()
assetCache: assetCache,
assetCacheAll: assetCacheAll,
assetId: assetIndex,
pdfBytes: pdfBytes,
pdfFile: pdfFile,
pdfPage: json['pdfi'],
Expand Down Expand Up @@ -127,9 +150,10 @@ class PdfEditorImage extends EditorImage {
dstRect = dstRect.topLeft & dstSize;
}

_pdfDocument.value ??= pdfFile != null
? await PdfDocument.openFile(pdfFile!.path)
: await PdfDocument.openData(pdfBytes!);
_pdfDocument.value ??= await assetCacheAll.getPdfDocument(assetId);
// _pdfDocument.value ??= pdfFile != null
// ? await PdfDocument.openFile(pdfFile!.path)
// : await PdfDocument.openData(pdfBytes!);
}

@override
Expand Down Expand Up @@ -184,6 +208,8 @@ class PdfEditorImage extends EditorImage {
PdfEditorImage copy() => PdfEditorImage(
id: id,
assetCache: assetCache,
assetCacheAll: assetCacheAll,
assetId: assetId,
pdfBytes: pdfBytes,
pdfPage: pdfPage,
pdfFile: pdfFile,
Expand Down
94 changes: 69 additions & 25 deletions lib/components/canvas/image/png_editor_image.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
part of 'editor_image.dart';

class PngEditorImage extends EditorImage {
ImageProvider? imageProvider;
/// index of asset assigned to this image
int assetId;

// ImageProvider is given by assetCacheAll using this notifier
final ValueNotifier<ImageProvider?> imageProviderNotifier;

/// Convenience getter to access current ImageProvider
ImageProvider? get imageProvider => imageProviderNotifier.value;



Uint8List? thumbnailBytes;
Size thumbnailSize = Size.zero;
Expand All @@ -14,18 +23,21 @@ class PngEditorImage extends EditorImage {
set isThumbnail(bool isThumbnail) {
super.isThumbnail = isThumbnail;
if (isThumbnail && thumbnailBytes != null) {
imageProvider = MemoryImage(thumbnailBytes!);
final scale = thumbnailSize.width / naturalSize.width;
srcRect = Rect.fromLTWH(srcRect.left * scale, srcRect.top * scale,
srcRect.width * scale, srcRect.height * scale);
// QBtodo - handle this thumbnail
//imageProvider = MemoryImage(thumbnailBytes!);
//final scale = thumbnailSize.width / naturalSize.width;
//srcRect = Rect.fromLTWH(srcRect.left * scale, srcRect.top * scale,
// srcRect.width * scale, srcRect.height * scale);
}
}

PngEditorImage({
required super.id,
required super.assetCache,
required super.assetCacheAll,
required this.assetId,
required super.extension,
required this.imageProvider,
required this.imageProviderNotifier,
required super.pageIndex,
required super.pageSize,
this.maxSize,
Expand All @@ -49,17 +61,18 @@ class PngEditorImage extends EditorImage {
bool isThumbnail = false,
required String sbnPath,
required AssetCache assetCache,
required AssetCacheAll assetCacheAll,
}) {
final assetIndex = json['a'] as int?;
final Uint8List? bytes;
final assetIndexJson = json['a'] as int?;
Uint8List? bytes;
final int? assetIndex;
File? imageFile;
if (assetIndex != null) {
if (assetIndexJson != null) {
if (inlineAssets == null) {
imageFile =
FileManager.getFile('$sbnPath${Editor.extension}.$assetIndex');
bytes = assetCache.get(imageFile);
FileManager.getFile('$sbnPath${Editor.extension}.$assetIndexJson');
} else {
bytes = inlineAssets[assetIndex];
bytes = inlineAssets[assetIndexJson];
}
} else if (json['b'] != null) {
bytes = Uint8List.fromList((json['b'] as List<dynamic>).cast<int>());
Expand All @@ -72,14 +85,28 @@ class PngEditorImage extends EditorImage {
assert(bytes != null || imageFile != null,
'Either bytes or imageFile must be non-null');

// add to asset cache
if (imageFile != null) {
assetIndex = assetCacheAll.addSync(imageFile);
}
else {
final tempFile=assetCacheAll.createRuntimeFile(json['e'] ?? '.jpg',bytes!);
assetIndex = assetCacheAll.addSync(tempFile);
}
if (assetIndex<0){
throw Exception('EditorImage.fromJson: image not in assets');
}



return PngEditorImage(
// -1 will be replaced by [EditorCoreInfo._handleEmptyImageIds()]
id: json['id'] ?? -1,
assetCache: assetCache,
assetCacheAll: assetCacheAll,
assetId: assetIndex,
extension: json['e'] ?? '.jpg',
imageProvider: bytes != null
? MemoryImage(bytes) as ImageProvider
: FileImage(imageFile!),
imageProviderNotifier: assetCacheAll.getImageProviderNotifier(assetIndex),
pageIndex: json['i'] ?? 0,
pageSize: Size.infinite,
invertible: json['v'] ?? true,
Expand Down Expand Up @@ -124,6 +151,7 @@ class PngEditorImage extends EditorImage {
assert(Isolate.current.debugName == 'main');

if (srcRect.shortestSide == 0 || dstRect.shortestSide == 0) {
// when image was picked, its size is not determined. Do it
final Uint8List bytes;
if (imageProvider is MemoryImage) {
bytes = (imageProvider as MemoryImage).bytes;
Expand Down Expand Up @@ -153,7 +181,10 @@ class PngEditorImage extends EditorImage {
height: reducedSize.height.toInt(),
);
if (resizedByteData != null) {
imageProvider = MemoryImage(resizedByteData.buffer.asUint8List());
// store resized bytes to temporary file
final tempImageFile = await assetCacheAll.createRuntimeFile('.png',resizedByteData.buffer.asUint8List());
// replace image
assetCacheAll.replaceImage(tempImageFile, assetId);
}

naturalSize = reducedSize;
Expand Down Expand Up @@ -186,8 +217,10 @@ class PngEditorImage extends EditorImage {

@override
Future<void> precache(BuildContext context) async {
if (imageProvider == null) return;
return await precacheImage(imageProvider!, context);
final provider = imageProviderNotifier.value;
if (provider != null) {
await precacheImage(provider, context);
}
}

@override
Expand All @@ -206,21 +239,32 @@ class PngEditorImage extends EditorImage {
boxFit = BoxFit.fill;
}

return InvertWidget(
invert: invert,
child: Image(
image: imageProvider!,
fit: boxFit,
),
return ValueListenableBuilder<ImageProvider?>(
valueListenable: imageProviderNotifier,
builder: (context, provider, _) {
if (provider == null) {
return const SizedBox.shrink(); // nothing yet
}

return InvertWidget(
invert: invert,
child: Image(
image: provider,
fit: boxFit,
),
);
},
);
}

@override
PngEditorImage copy() => PngEditorImage(
id: id,
assetCache: assetCache,
assetCacheAll: assetCacheAll,
assetId: assetId,
extension: extension,
imageProvider: imageProvider,
imageProviderNotifier: imageProviderNotifier,
pageIndex: pageIndex,
pageSize: Size.infinite,
invertible: invertible,
Expand Down
4 changes: 4 additions & 0 deletions lib/components/canvas/image/svg_editor_image.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class SvgEditorImage extends EditorImage {
SvgEditorImage({
required super.id,
required super.assetCache,
required super.assetCacheAll,
required String? svgString,
required File? svgFile,
required super.pageIndex,
Expand Down Expand Up @@ -45,6 +46,7 @@ class SvgEditorImage extends EditorImage {
bool isThumbnail = false,
required String sbnPath,
required AssetCache assetCache,
required AssetCacheAll assetCacheAll,
}) {
String? extension = json['e'] as String?;
assert(extension == null || extension == '.svg');
Expand All @@ -71,6 +73,7 @@ class SvgEditorImage extends EditorImage {
id: json['id'] ??
-1, // -1 will be replaced by EditorCoreInfo._handleEmptyImageIds()
assetCache: assetCache,
assetCacheAll: assetCacheAll,
svgString: svgString,
svgFile: svgFile,
pageIndex: json['i'] ?? 0,
Expand Down Expand Up @@ -195,6 +198,7 @@ class SvgEditorImage extends EditorImage {
id: id,
// ignore: deprecated_member_use_from_same_package
assetCache: assetCache,
assetCacheAll: assetCacheAll,
svgString: svgData.string,
svgFile: svgData.file,
pageIndex: pageIndex,
Expand Down
Loading
Loading