This commit is contained in:
Vadim 2024-05-14 14:44:26 +02:00
parent f23752b5dd
commit d2a953e1f5
3 changed files with 162 additions and 12 deletions

View file

@ -0,0 +1,135 @@
import 'dart:io';
import 'package:image/image.dart';
import 'models/screenshot_args.dart';
import 'models/screenshot_device.dart';
import 'models/screenshot_layout.dart';
import 'utils/parse_configs.dart';
final _configs = parseScreenshotConfigs();
extension ScreenshotImage on Image {
Image convertToStoreScreenshot({
required ScreenshotArgs args,
required ScreenshotLayout layout,
}) {
if (_configs[args.name] == null) {
return this;
}
print(args.deviceName);
return _addSystemOverlay(
screenshotDevices[args.deviceName]!,
isDark: args.isDark,
)
._addDeviceFrame(
screenshotDevices[args.deviceName]!,
ColorRgba8(
args.backgroundColor.r,
args.backgroundColor.g,
args.backgroundColor.b,
args.backgroundColor.a,
),
)
._applyLayout(layout)
._addText(
layout,
_configs[args.name]!.title,
_configs[args.name]!.subtitle,
);
}
Image _addSystemOverlay(ScreenshotDevice device, {required bool isDark}) {
final path = isDark ? device.systemOverlayPathDark : device.systemOverlayPathLight;
final statusBar = copyResize(
decodePng(File(path).readAsBytesSync())!,
width: width,
);
return compositeImage(this, statusBar);
}
Image _addDeviceFrame(ScreenshotDevice device, Color backgroundColor) {
final screenshotRounded = copyCrop(
this,
x: 0,
y: 0,
width: width,
height: height,
);
final frame = decodePng(File(device.deviceFramePath).readAsBytesSync())!;
final expandedScreenshot = copyExpandCanvas(
copyExpandCanvas(
screenshotRounded,
newWidth: screenshotRounded.width + device.screenshotFrameOffset.dx,
newHeight: screenshotRounded.height + device.screenshotFrameOffset.dy,
position: ExpandCanvasPosition.bottomRight,
backgroundColor: backgroundColor,
),
newWidth: frame.width,
newHeight: frame.height,
position: ExpandCanvasPosition.topLeft,
backgroundColor: backgroundColor,
);
return compositeImage(expandedScreenshot, frame);
}
Image _applyLayout(ScreenshotLayout layout) {
final scaledScreenshot = copyResize(
this,
width: layout.size.width - (layout.contentPadding.left + layout.contentPadding.right),
);
return copyExpandCanvas(
copyExpandCanvas(
scaledScreenshot,
newWidth: scaledScreenshot.width + layout.contentPadding.right,
newHeight: scaledScreenshot.height + layout.contentPadding.bottom,
position: ExpandCanvasPosition.topLeft,
backgroundColor: getPixel(0, 0),
),
newWidth: layout.size.width,
newHeight: layout.size.height,
position: ExpandCanvasPosition.bottomRight,
backgroundColor: getPixel(0, 0),
);
}
Image _addText(ScreenshotLayout layout, String title, String subtitle) {
final titleFont = BitmapFont.fromZip(File(layout.titleFontPath).readAsBytesSync());
final subtitleFont = BitmapFont.fromZip(File(layout.subtitleFontPath).readAsBytesSync());
final textImage = fill(
Image(
height: titleFont.lineHeight + 36 + subtitleFont.lineHeight * 2,
width: layout.size.width - (layout.contentPadding.left + layout.contentPadding.right),
),
color: getPixel(0, 0),
);
drawString(
textImage,
title,
font: titleFont,
y: 0,
);
int subtitleDy = titleFont.lineHeight + 36;
subtitle.split('\n').forEach((line) {
drawString(
textImage,
line,
font: subtitleFont,
y: subtitleDy,
);
subtitleDy += subtitleFont.lineHeight;
});
return compositeImage(
this,
textImage,
dstX: layout.contentPadding.left,
dstY: layout.contentPadding.top,
);
}
}

View file

@ -1,17 +1,5 @@
enum ScreenshotDevicePlatform { android, ios }
final screenshotDevicesIos = [
ScreenshotDevice.fromDisplayName(
displayName: 'iPhone 8 Plus',
platform: ScreenshotDevicePlatform.ios,
),
ScreenshotDevice.fromDisplayName(
displayName: 'iPhone 13 Pro',
platform: ScreenshotDevicePlatform.ios,
screenshotFrameOffset: (dx: 72, dy: 60),
),
];
class ScreenshotDevice {
final String name;
final ScreenshotDevicePlatform platform;
@ -35,3 +23,16 @@ class ScreenshotDevice {
'screenshots/assets/system_overlays/${platform.name}/${name}_system_overlay_dark.png';
String get deviceFramePath => 'screenshots/assets/frames/${platform.name}/${name}_frame.png';
}
final screenshotDevices = <String, ScreenshotDevice>{for (final d in _screenshotDevicesIos) d.name: d};
final List<ScreenshotDevice> _screenshotDevicesIos = [
ScreenshotDevice.fromDisplayName(
displayName: 'iPhone 8 Plus',
platform: ScreenshotDevicePlatform.ios,
),
ScreenshotDevice.fromDisplayName(
displayName: 'iPhone 13 Pro',
platform: ScreenshotDevicePlatform.ios,
screenshotFrameOffset: (dx: 72, dy: 60),
),
];

View file

@ -0,0 +1,14 @@
import 'dart:convert';
import 'dart:io';
import '../models/screenshot_config.dart';
Map<String, ScreenshotConfig> parseScreenshotConfigs([String locale = 'en']) {
final configPath = 'screenshots/assets/content/screenshot_titles_$locale.json';
final data = jsonDecode(File(configPath).readAsStringSync()) as Map<String, dynamic>;
final entries = (data['screenshots'] as List).map((value) {
final config = ScreenshotConfig.fromJson(value as Map<String, dynamic>);
return MapEntry(config.screenshotName, config);
});
return Map.fromEntries(entries);
}