createBitmapFromIcon static method

Future<Uint8List> createBitmapFromIcon({
  1. required IconData icon,
  2. required Color color,
  3. required double size,
})

Converts a Flutter IconData into a PNG byte array that MapLibre can render natively. Draws a colored rounded rectangle with a white border, drop shadow, and white icon.

Implementation

static Future<Uint8List> createBitmapFromIcon({
  required IconData icon,
  required Color color,
  required double size,
}) async {
  final pictureRecorder = ui.PictureRecorder();
  final canvas = Canvas(pictureRecorder);

  final double padding = size * 0.15;
  final double canvasSize = size + (padding * 2);

  final rrect = RRect.fromLTRBR(
    padding,
    padding,
    size + padding,
    size + padding,
    Radius.circular(size * 0.25)
  );

  // Draw shadow
  final shadowPaint = Paint()
    ..color = Colors.black.withValues(alpha: 0.3)
    ..maskFilter = MaskFilter.blur(BlurStyle.normal, size * 0.05);
  canvas.drawRRect(rrect.shift(Offset(0, size * 0.05)), shadowPaint);

  // Draw rounded rectangle background
  final paintBg = Paint()..color = color;
  canvas.drawRRect(rrect, paintBg);

  // Draw white border
  final paintBorder = Paint()
    ..color = Colors.white
    ..style = PaintingStyle.stroke
    ..strokeWidth = size * 0.08;
  canvas.drawRRect(rrect, paintBorder);

  // Draw icon in white
  final textPainter = TextPainter(textDirection: TextDirection.ltr);
  textPainter.text = TextSpan(
    text: String.fromCharCode(icon.codePoint),
    style: TextStyle(
      fontSize: size * 0.55,
      fontFamily: icon.fontFamily,
      package: icon.fontPackage,
      color: Colors.white,
    ),
  );

  textPainter.layout();

  // Center the icon text inside the rounded rectangle
  final offset = Offset(
    padding + (size - textPainter.width) / 2,
    padding + (size - textPainter.height) / 2,
  );
  textPainter.paint(canvas, offset);

  final picture = pictureRecorder.endRecording();
  final image = await picture.toImage(canvasSize.toInt(), canvasSize.toInt());
  final byteData = await image.toByteData(format: ui.ImageByteFormat.png);

  return byteData!.buffer.asUint8List();
}