Skip to content

Commit

Permalink
v0.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
dnfield committed Jun 18, 2018
2 parents 34a060b + bf2087a commit ae1b1c6
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 50 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- Unsupported style elements will report an error
- Unresolvable definitions will report an error
- Fixed `matchesTextDirection`
- Support for `text-anchor`

## 0.3.3

Expand Down
3 changes: 2 additions & 1 deletion example/main.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_svg/avd.dart';
import 'package:flutter_svg/flutter_svg.dart';

Expand Down Expand Up @@ -46,7 +47,7 @@ const List<String> uriNames = const <String>[

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
Expand Down
57 changes: 57 additions & 0 deletions lib/src/svg/parsers.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,65 @@
import 'dart:math';
import 'dart:ui';

import 'package:flutter_svg/src/vector_drawable.dart';
import 'package:vector_math/vector_math_64.dart';

final Map<String, double> _kTextSizeMap = <String, double>{
'xx-small': 10 * window.devicePixelRatio,
'x-small': 12 * window.devicePixelRatio,
'small': 14 * window.devicePixelRatio,
'medium': 18 * window.devicePixelRatio,
'large': 22 * window.devicePixelRatio,
'x-large': 26 * window.devicePixelRatio,
'xx-large': 32 * window.devicePixelRatio,
};

double parseFontSize(String raw, {double parentValue}) {
if (raw == null || raw == '') {
return null;
}

double ret = double.tryParse(raw);
if (ret != null) {
return ret;
}

raw = raw.toLowerCase().trim();
ret = _kTextSizeMap[raw];
if (ret != null) {
return ret;
}

if (raw == 'larger') {
if (parentValue == null) {
return _kTextSizeMap['large'];
}
return parentValue * 1.2;
}

if (raw == 'smaller') {
if (parentValue == null) {
return _kTextSizeMap['small'];
}
return parentValue / 1.2;
}

throw new StateError('Could not parse font-size: $raw');
}

DrawableTextAnchorPosition parseTextAnchor(String raw) {
switch (raw) {
case 'middle':
return DrawableTextAnchorPosition.middle;
case 'start':
return DrawableTextAnchorPosition.start;
case 'end':
return DrawableTextAnchorPosition.end;
default:
return DrawableTextAnchorPosition.start;
}
}

const String _transformCommandAtom = ' *([^(]+)\\(([^)]*)\\)';
final RegExp _transformValidator = new RegExp('^($_transformCommandAtom)*\$');
final RegExp _transformCommand = new RegExp(_transformCommandAtom);
Expand Down
21 changes: 11 additions & 10 deletions lib/src/svg_parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ Drawable parseSvgElement(XmlElement el, DrawableDefinitionServer definitions,
void _unhandledElement(XmlElement el, String key) {
if (el.name.local == 'style') {
FlutterError.reportError(new FlutterErrorDetails(
exception: new UnimplementedError('The <style> element is not implemented in this library.'),
exception: new UnimplementedError(
'The <style> element is not implemented in this library.'),
informationCollector: (StringBuffer buff) {
buff.writeln(
'Style elements are not supported by this library and the requested SVG may not '
Expand All @@ -91,22 +92,22 @@ Drawable parseSvgText(XmlElement el, DrawableDefinitionServer definitions,
double.parse(getAttribute(el, 'x', def: '0')),
double.parse(getAttribute(el, 'y', def: '0')));

final Paint fill = parseFill(el, bounds, definitions, colorBlack);
final Paint stroke = parseStroke(el, bounds, definitions);

return new DrawableText(
el.text,
offset,
parseTextAnchor(getAttribute(el, 'text-anchor', def: 'start')),
DrawableStyle.mergeAndBlend(
parentStyle,
groupOpacity: parseOpacity(el),
textStyle: new TextStyle(
fill: fill,
stroke: stroke,
textStyle: new DrawableTextStyle(
fontFamily: getAttribute(el, 'font-family'),
fontSize: double.parse(getAttribute(el, 'font-size', def: '55')),
color: parseColor(
getAttribute(
el,
'fill',
def: getAttribute(el, 'stroke', def: 'black'),
),
),
fontSize: parseFontSize(getAttribute(el, 'font-size'),
parentValue: parentStyle?.textStyle?.fontSize),
height: -1.0,
),
),
Expand Down
111 changes: 102 additions & 9 deletions lib/src/vector_drawable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class DrawableStyle {
/// The 4x4 matrix ([Matrix4]) for a transform, if any.
final Float64List transform;

final TextStyle textStyle;
final DrawableTextStyle textStyle;

/// The fill rule to use for this path.
final PathFillType pathFillType;
Expand Down Expand Up @@ -86,7 +86,7 @@ class DrawableStyle {
CircularIntervalList<double> dashArray,
DashOffset dashOffset,
Float64List transform,
TextStyle textStyle,
DrawableTextStyle textStyle,
PathFillType pathFillType,
double groupOpacity,
List<Path> clipPath}) {
Expand Down Expand Up @@ -134,33 +134,126 @@ class DrawableStyle {
}
}

class DrawableTextStyle {
const DrawableTextStyle({
this.decoration,
this.decorationColor,
this.decorationStyle,
this.fontWeight,
this.fontFamily,
this.fontSize,
this.fontStyle,
this.foreground,
this.background,
this.letterSpacing,
this.wordSpacing,
this.height,
this.locale,
this.textBaseline,
});

final TextDecoration decoration;
final Color decorationColor;
final TextDecorationStyle decorationStyle;
final FontWeight fontWeight;
final FontStyle fontStyle;
final TextBaseline textBaseline;
final String fontFamily;
final double fontSize;
final double letterSpacing;
final double wordSpacing;
final double height;
final Locale locale;
final Paint background;
final Paint foreground;

TextStyle buildTextStyle({Paint foregroundOverride}) {
return new TextStyle(
decoration: decoration,
decorationColor: decorationColor,
decorationStyle: decorationStyle,
fontWeight: fontWeight,
fontStyle: fontStyle,
textBaseline: textBaseline,
fontFamily: fontFamily,
fontSize: fontSize,
letterSpacing: letterSpacing,
wordSpacing: wordSpacing,
height: height,
locale: locale,
background: background,
color: foregroundOverride?.color ?? foreground?.color ?? const Color(0xFF000000),
// this will be supported in Flutter 0.5.6 or 0.5.7
// foreground: foregroundOverride ?? foreground,
);
}
}

enum DrawableTextAnchorPosition { start, middle, end }

// WIP. This only handles very, very minimal use cases right now.
class DrawableText implements Drawable {
final Offset offset;
final DrawableTextAnchorPosition anchor;
final DrawableStyle style;
final Paragraph _paragraph;
final Paragraph _paragraphFill;
final Paragraph _paragraphStroke;

DrawableText(String text, this.offset, this.style)
DrawableText(String text, this.offset, this.anchor, this.style)
: assert(text != null && text != ''),
_paragraph = _buildParagraph(text, style);
_paragraphFill = _buildParagraph(text, style, style?.fill),
_paragraphStroke = _buildParagraph(text, style, style?.stroke) {
print(anchor);
}

static Paragraph _buildParagraph(String text, DrawableStyle style) {
static Paragraph _buildParagraph(
String text, DrawableStyle style, Paint paint) {
if (style == null || style.textStyle == null) {
return null;
}
final ParagraphBuilder pb = new ParagraphBuilder(new ParagraphStyle())
..pushStyle(style.textStyle)
..pushStyle(style.textStyle.buildTextStyle(foregroundOverride: paint))
..addText(text);

return pb.build()..layout(new ParagraphConstraints(width: double.infinity));
}

@override
bool get hasDrawableContent => _paragraph.width > 0.0;
bool get hasDrawableContent =>
(_paragraphFill?.width ?? 0.0) + (_paragraphStroke?.width ?? 0.0) > 0.0;

@override
void draw(Canvas canvas, ColorFilter colorFilter) {
if (!hasDrawableContent) {
return;
}
canvas.drawParagraph(_paragraph, offset);
if (_paragraphFill != null) {
canvas.drawParagraph(
_paragraphFill, resolveOffset(_paragraphFill, anchor, offset));
}
if (_paragraphStroke != null) {
canvas.drawParagraph(
_paragraphStroke, resolveOffset(_paragraphStroke, anchor, offset));
}
}

static Offset resolveOffset(
Paragraph paragraph, DrawableTextAnchorPosition anchor, Offset offset) {
assert(paragraph != null);
assert(anchor != null);
assert(offset != null);
switch (anchor) {
case DrawableTextAnchorPosition.middle:
return new Offset(
offset.dx - paragraph.minIntrinsicWidth / 2, offset.dy);
break;
case DrawableTextAnchorPosition.end:
return new Offset(offset.dx - paragraph.minIntrinsicWidth, offset.dy);
break;
default:
return offset;
break;
}
}
}

Expand Down
Loading

0 comments on commit ae1b1c6

Please sign in to comment.