Skip to content

Commit

Permalink
Updated AssetGenImage to also support parsing metadata into the gener…
Browse files Browse the repository at this point in the history
…ated output.
  • Loading branch information
bramp committed Jan 12, 2024
1 parent e7e515c commit d5fdc31
Show file tree
Hide file tree
Showing 19 changed files with 105 additions and 43 deletions.
4 changes: 3 additions & 1 deletion examples/example/lib/gen/assets.gen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,12 @@ class MyAssets {
}

class AssetGenImage {
const AssetGenImage(this._assetName);
const AssetGenImage(this._assetName, {this.size = null});

final String _assetName;

final Size? size;

Image image({
Key? key,
AssetBundle? bundle,
Expand Down
4 changes: 3 additions & 1 deletion examples/example_resources/lib/gen/assets.gen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,12 @@ class ResAssets {
}

class AssetGenImage {
const AssetGenImage(this._assetName);
const AssetGenImage(this._assetName, {this.size = null});

final String _assetName;

final Size? size;

Image image({
Key? key,
AssetBundle? bundle,
Expand Down
4 changes: 3 additions & 1 deletion packages/command/example/lib/gen/assets.gen.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion packages/core/lib/generators/assets_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ String generateAssets(
final classesBuffer = StringBuffer();

final integrations = <Integration>[
ImageIntegration(config.packageParameterLiteral),
ImageIntegration(config.packageParameterLiteral,
parseMetadata: config.flutterGen.parseMetadata),
if (config.flutterGen.integrations.flutterSvg)
SvgIntegration(config.packageParameterLiteral,
parseMetadata: config.flutterGen.parseMetadata),
Expand Down
36 changes: 30 additions & 6 deletions packages/core/lib/generators/integrations/image_integration.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import 'dart:io';

import 'package:flutter_gen_core/generators/integrations/integration.dart';
import 'package:flutter_gen_core/settings/asset_type.dart';
import 'package:image_size_getter/file_input.dart';
import 'package:image_size_getter/image_size_getter.dart';

/// The main image integration, supporting all image asset types. See
/// [isSupport] for the exact supported mime types.
///
/// This integration is by enabled by default.
class ImageIntegration extends Integration {
ImageIntegration(String packageName) : super(packageName);
ImageIntegration(String packageName, {super.parseMetadata})
: super(packageName);

String get packageParameter => isPackage ? ' = package' : '';

Expand All @@ -20,11 +25,13 @@ class ImageIntegration extends Integration {
String get classOutput => _classDefinition;

String get _classDefinition => '''class AssetGenImage {
const AssetGenImage(this._assetName);
const AssetGenImage(this._assetName, {this.size = null});
final String _assetName;
${isPackage ? "\n static const String package = '$packageName';" : ''}
final Size? size;
Image image({
Key? key,
AssetBundle? bundle,
Expand Down Expand Up @@ -101,14 +108,19 @@ ${isPackage ? "\n static const String package = '$packageName';" : ''}
String get className => 'AssetGenImage';

@override
String classInstantiate(AssetType asset) =>
'AssetGenImage(\'${asset.posixStylePath}\')';
String classInstantiate(AssetType asset) {
ImageMetadata? info = parseMetadata ? _getMetadata(asset) : null;

return 'AssetGenImage(\'${asset.posixStylePath}\''
'${(info != null) ? ', size: Size(${info.width}, ${info.height})' : ''}'
')';
}

@override
bool isSupport(AssetType type) {
bool isSupport(AssetType asset) {
/// Flutter official supported image types. See
/// https://api.flutter.dev/flutter/widgets/Image-class.html
switch (type.mime) {
switch (asset.mime) {
case 'image/jpeg':
case 'image/png':
case 'image/gif':
Expand All @@ -123,4 +135,16 @@ ${isPackage ? "\n static const String package = '$packageName';" : ''}

@override
bool get isConstConstructor => true;

/// Extract metadata from the asset.
ImageMetadata? _getMetadata(AssetType asset) {
try {
final size = ImageSizeGetter.getSize(FileInput(File(asset.fullPath)));
return ImageMetadata(size.width.toDouble(), size.height.toDouble());
} catch (e) {
stderr
.writeln('[WARNING] Failed to parse \'${asset.path}\' metadata: $e');
}
return null;
}
}
15 changes: 14 additions & 1 deletion packages/core/lib/generators/integrations/integration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ import 'package:flutter_gen_core/settings/asset_type.dart';
/// A base class for all integrations. An integration is a class that
/// generates code for a specific asset type.
abstract class Integration {
Integration(this.packageName);
Integration(this.packageName, {this.parseMetadata = false});

/// The package name for this asset. If empty, the asset is not in a package.
final String packageName;
late final bool isPackage = packageName.isNotEmpty;

bool isEnabled = false;

final bool parseMetadata;

List<String> get requiredImports;

String get classOutput;
Expand All @@ -29,3 +31,14 @@ abstract class Integration {
/// if the asset is a library asset.
const String deprecationMessagePackage =
"@Deprecated('Do not specify package for a generated library asset')";

/// Useful metadata about the a parsed Asset file. Which is used when
/// [parseMetadata] is true.
/// Currently only contains the width and height, but could contain more in
/// future.
class ImageMetadata {
final double width;
final double height;

ImageMetadata(this.width, this.height);
}
22 changes: 6 additions & 16 deletions packages/core/lib/generators/integrations/svg_integration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@ import 'package:flutter_gen_core/settings/asset_type.dart';
import 'package:vector_graphics_compiler/vector_graphics_compiler.dart';

class SvgIntegration extends Integration {
SvgIntegration(String packageName, {this.parseMetadata = false})
SvgIntegration(String packageName, {super.parseMetadata})
: super(packageName);

String get packageExpression => isPackage ? ' = package' : '';

final bool parseMetadata;

@override
List<String> get requiredImports => [
'package:flutter/widgets.dart',
Expand All @@ -26,9 +24,10 @@ class SvgIntegration extends Integration {
const SvgGenImage(this._assetName, {this.size = null});
final String _assetName;
final Size? size;
${isPackage ? "\n static const String package = '$packageName';" : ''}
final Size? size;
SvgPicture svg({
Key? key,
bool matchTextDirection = false,
Expand Down Expand Up @@ -84,21 +83,21 @@ ${isPackage ? "\n static const String package = '$packageName';" : ''}
@override
String classInstantiate(AssetType asset) {
// Query extra information about the SVG
SvgInfo? info = parseMetadata ? _getMetadata(asset) : null;
ImageMetadata? info = parseMetadata ? _getMetadata(asset) : null;

return 'SvgGenImage(\'${asset.posixStylePath}\''
'${(info != null) ? ', size: Size(${info.width}, ${info.height})' : ''}'
')';
}

SvgInfo? _getMetadata(AssetType asset) {
ImageMetadata? _getMetadata(AssetType asset) {
try {
// The SVG file is read fully, then parsed with the vector_graphics
// library. This is quite a heavy way to extract just the dimenions, but
// it's also the same way it will be eventually rendered by Flutter.
final svg = File(asset.fullPath).readAsStringSync();
final vec = parseWithoutOptimizers(svg);
return SvgInfo(vec.width, vec.height);
return ImageMetadata(vec.width, vec.height);
} catch (e) {
stderr.writeln(
'[WARNING] Failed to parse SVG \'${asset.path}\' metadata: $e');
Expand All @@ -113,12 +112,3 @@ ${isPackage ? "\n static const String package = '$packageName';" : ''}
@override
bool get isConstConstructor => true;
}

/// Useful metadata about the a parsed SVG file.
/// Currently only contains the width and height.
class SvgInfo {
final double width;
final double height;

SvgInfo(this.width, this.height);
}
1 change: 1 addition & 0 deletions packages/core/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ dependencies:
args: ^2.0.0
pub_semver: ^2.0.0
vector_graphics_compiler: ^1.1.9
image_size_getter: ^2.1.2

dev_dependencies:
lints: any # Ignoring the version to allow editing across SDK versions.
Expand Down
5 changes: 4 additions & 1 deletion packages/core/test_resources/actual_data/assets.gen.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit d5fdc31

Please sign in to comment.