Update flutter runtime

- ran ```dev/generate_core_runtime.sh build```
- cleaned up a lot of accumulated changes from the last few months that needed to be stripped/modified for the rutnime
- removed no longer supported lining options from analysis files
- fixed up defs for some editor only features so they don't transpile
- added some more details to changelog
- bumped pubspec version

Diffs=
aa8c750bd Update flutter runtime (#4835)
This commit is contained in:
luigi-rosso
2023-02-15 23:47:35 +00:00
parent 3941b7e932
commit 27be816a46
41 changed files with 1614 additions and 181 deletions

View File

@ -1 +1 @@
c7d125c7d4efe1233c16c2a95fb7b637b746b010
aa8c750bd077f4260c0daf0de988aeae65a07614

View File

@ -1,6 +1,9 @@
## Upcoming
## 0.10.2
- Performance improvement: No longer drawing components with an opacity of 0.
- Updated example, see "Skinning Demo".
- Support for negative speeds on linear animations when played back in state machines.
- Support for overriding speed on animation states.
## 0.10.1

View File

@ -1,7 +1,4 @@
analyzer:
strong-mode:
implicit-casts: false
implicit-dynamic: false
errors:
unused_import: error
exclude:
@ -10,116 +7,116 @@ analyzer:
linter:
rules:
- always_put_required_named_parameters_first
- always_require_non_null_named_parameters
- annotate_overrides
# - avoid_annotating_with_dynamic
- avoid_bool_literals_in_conditional_expressions
- avoid_catches_without_on_clauses
- avoid_catching_errors
- avoid_classes_with_only_static_members
- avoid_double_and_int_checks
- avoid_empty_else
- avoid_field_initializers_in_const_classes
- avoid_implementing_value_types
- avoid_init_to_null
- avoid_js_rounded_ints
- avoid_null_checks_in_equality_operators
- avoid_relative_lib_imports
- avoid_return_types_on_setters
- avoid_returning_null
- avoid_returning_null_for_future
- avoid_returning_null_for_void
- avoid_returning_this
- avoid_setters_without_getters
- avoid_shadowing_type_parameters
- avoid_single_cascade_in_expression_statements
- avoid_slow_async_io
- avoid_types_as_parameter_names
- avoid_unused_constructor_parameters
- avoid_void_async
- await_only_futures
- camel_case_types
- cancel_subscriptions
- close_sinks
- constant_identifier_names
- control_flow_in_finally
- curly_braces_in_flow_control_structures
- directives_ordering
- empty_catches
- empty_constructor_bodies
- empty_statements
- file_names
- hash_and_equals
- implementation_imports
# - invariant_booleans # too many false positives: https://github.com/dart-lang/linter/issues/811
- iterable_contains_unrelated_type
- join_return_with_assignment
- library_names
- library_prefixes
- lines_longer_than_80_chars
- list_remove_unrelated_type
# - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/sdk/issues/34181
- no_adjacent_strings_in_list
- no_duplicate_case_values
- non_constant_identifier_names
- null_closures
- one_member_abstracts
- only_throw_errors
- overridden_fields
- package_api_docs
- package_names
- package_prefixed_library_names
- parameter_assignments
- prefer_adjacent_string_concatenation
- prefer_asserts_in_initializer_lists
- prefer_collection_literals
- prefer_conditional_assignment
- prefer_const_constructors
- prefer_const_constructors_in_immutables
- prefer_const_declarations
- prefer_const_literals_to_create_immutables
- prefer_constructors_over_static_methods
- prefer_contains
- prefer_equal_for_default_values
- prefer_final_fields
- prefer_final_in_for_each
- prefer_foreach
- prefer_function_declarations_over_variables
- prefer_initializing_formals
- prefer_is_empty
- prefer_is_not_empty
- prefer_iterable_whereType
# - prefer_mixin
- prefer_null_aware_operators
- prefer_typing_uninitialized_variables
- prefer_void_to_null
- recursive_getters
- slash_for_doc_comments
- sort_pub_dependencies
- sort_unnamed_constructors_first
- test_types_in_equals
- throw_in_finally
- type_annotate_public_apis
- type_init_formals
- unawaited_futures
- unnecessary_await_in_return
- unnecessary_brace_in_string_interps
- unnecessary_const
- unnecessary_getters_setters
- unnecessary_lambdas
- unnecessary_new
- unnecessary_null_aware_assignments
- unnecessary_null_in_if_null_operators
- unnecessary_overrides
- unnecessary_parenthesis
- unnecessary_statements
- unnecessary_this
- unrelated_type_equality_checks
- use_full_hex_values_for_flutter_colors
- use_rethrow_when_possible
- use_setters_to_change_properties
- use_string_buffers
- use_to_and_as_if_applicable
- valid_regexps
- void_checks
- always_put_required_named_parameters_first
- always_require_non_null_named_parameters
- annotate_overrides
# - avoid_annotating_with_dynamic
- avoid_bool_literals_in_conditional_expressions
- avoid_catches_without_on_clauses
- avoid_catching_errors
- avoid_classes_with_only_static_members
- avoid_double_and_int_checks
- avoid_empty_else
- avoid_field_initializers_in_const_classes
- avoid_implementing_value_types
- avoid_init_to_null
- avoid_js_rounded_ints
- avoid_null_checks_in_equality_operators
- avoid_relative_lib_imports
- avoid_return_types_on_setters
- avoid_returning_null
- avoid_returning_null_for_future
- avoid_returning_null_for_void
- avoid_returning_this
- avoid_setters_without_getters
- avoid_shadowing_type_parameters
- avoid_single_cascade_in_expression_statements
- avoid_slow_async_io
- avoid_types_as_parameter_names
- avoid_unused_constructor_parameters
- avoid_void_async
- await_only_futures
- camel_case_types
- cancel_subscriptions
- close_sinks
- constant_identifier_names
- control_flow_in_finally
- curly_braces_in_flow_control_structures
- directives_ordering
- empty_catches
- empty_constructor_bodies
- empty_statements
- file_names
- hash_and_equals
- implementation_imports
# - invariant_booleans # too many false positives: https://github.com/dart-lang/linter/issues/811
- iterable_contains_unrelated_type
- join_return_with_assignment
- library_names
- library_prefixes
- lines_longer_than_80_chars
- list_remove_unrelated_type
# - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/sdk/issues/34181
- no_adjacent_strings_in_list
- no_duplicate_case_values
- non_constant_identifier_names
- null_closures
- one_member_abstracts
- only_throw_errors
- overridden_fields
- package_api_docs
- package_names
- package_prefixed_library_names
- parameter_assignments
- prefer_adjacent_string_concatenation
- prefer_asserts_in_initializer_lists
- prefer_collection_literals
- prefer_conditional_assignment
- prefer_const_constructors
- prefer_const_constructors_in_immutables
- prefer_const_declarations
- prefer_const_literals_to_create_immutables
- prefer_constructors_over_static_methods
- prefer_contains
- prefer_equal_for_default_values
- prefer_final_fields
- prefer_final_in_for_each
- prefer_foreach
- prefer_function_declarations_over_variables
- prefer_initializing_formals
- prefer_is_empty
- prefer_is_not_empty
- prefer_iterable_whereType
# - prefer_mixin
- prefer_null_aware_operators
- prefer_typing_uninitialized_variables
- prefer_void_to_null
- recursive_getters
- slash_for_doc_comments
- sort_pub_dependencies
- sort_unnamed_constructors_first
- test_types_in_equals
- throw_in_finally
- type_annotate_public_apis
- type_init_formals
- unawaited_futures
- unnecessary_await_in_return
- unnecessary_brace_in_string_interps
- unnecessary_const
- unnecessary_getters_setters
- unnecessary_lambdas
- unnecessary_new
- unnecessary_null_aware_assignments
- unnecessary_null_in_if_null_operators
- unnecessary_overrides
- unnecessary_parenthesis
- unnecessary_statements
- unnecessary_this
- unrelated_type_equality_checks
- use_full_hex_values_for_flutter_colors
- use_rethrow_when_possible
- use_setters_to_change_properties
- use_string_buffers
- use_to_and_as_if_applicable
- valid_regexps
- void_checks

View File

@ -14,8 +14,8 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/rive_common/macos
SPEC CHECKSUMS:
FlutterMacOS: ae6af50a8ea7d6103d888583d46bd8328a7e9811
rive_common: 0ac58617cab300ee9bcf495e710d593578ff328b
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
rive_common: 643f5c20ccd60c53136ab5c970eccf0d17e010fe
PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7

View File

@ -0,0 +1,41 @@
/// Core automatically generated
/// lib/src/generated/animation/keyframe_string_base.dart.
/// Do not modify manually.
import 'package:rive/src/rive_core/animation/keyframe.dart';
abstract class KeyFrameStringBase extends KeyFrame {
static const int typeKey = 142;
@override
int get coreType => KeyFrameStringBase.typeKey;
@override
Set<int> get coreTypes => {KeyFrameStringBase.typeKey, KeyFrameBase.typeKey};
/// --------------------------------------------------------------------------
/// Value field with key 280.
static const String valueInitialValue = '';
String _value = valueInitialValue;
static const int valuePropertyKey = 280;
String get value => _value;
/// Change the [_value] field value.
/// [valueChanged] will be invoked only if the field's value has changed.
set value(String value) {
if (_value == value) {
return;
}
String from = _value;
_value = value;
if (hasValidated) {
valueChanged(from, value);
}
}
void valueChanged(String from, String to);
@override
void copy(covariant KeyFrameStringBase source) {
super.copy(source);
_value = source._value;
}
}

View File

@ -0,0 +1,14 @@
/// Core automatically generated lib/src/generated/assets/font_asset_base.dart.
/// Do not modify manually.
import 'package:rive/src/generated/assets/asset_base.dart';
import 'package:rive/src/rive_core/assets/file_asset.dart';
abstract class FontAssetBase extends FileAsset {
static const int typeKey = 141;
@override
int get coreType => FontAssetBase.typeKey;
@override
Set<int> get coreTypes =>
{FontAssetBase.typeKey, FileAssetBase.typeKey, AssetBase.typeKey};
}

View File

@ -10,6 +10,7 @@ import 'package:rive/src/generated/animation/blend_animation_base.dart';
import 'package:rive/src/generated/animation/cubic_ease_interpolator_base.dart';
import 'package:rive/src/generated/animation/cubic_interpolator_base.dart';
import 'package:rive/src/generated/animation/keyframe_base.dart';
import 'package:rive/src/generated/animation/keyframe_string_base.dart';
import 'package:rive/src/generated/animation/listener_input_change_base.dart';
import 'package:rive/src/generated/animation/nested_input_base.dart';
import 'package:rive/src/generated/animation/nested_linear_animation_base.dart';
@ -51,6 +52,7 @@ import 'package:rive/src/rive_core/animation/keyframe_bool.dart';
import 'package:rive/src/rive_core/animation/keyframe_color.dart';
import 'package:rive/src/rive_core/animation/keyframe_double.dart';
import 'package:rive/src/rive_core/animation/keyframe_id.dart';
import 'package:rive/src/rive_core/animation/keyframe_string.dart';
import 'package:rive/src/rive_core/animation/linear_animation.dart';
import 'package:rive/src/rive_core/animation/listener_align_target.dart';
import 'package:rive/src/rive_core/animation/listener_bool_change.dart';
@ -75,6 +77,7 @@ import 'package:rive/src/rive_core/animation/transition_trigger_condition.dart';
import 'package:rive/src/rive_core/artboard.dart';
import 'package:rive/src/rive_core/assets/file_asset_contents.dart';
import 'package:rive/src/rive_core/assets/folder.dart';
import 'package:rive/src/rive_core/assets/font_asset.dart';
import 'package:rive/src/rive_core/assets/image_asset.dart';
import 'package:rive/src/rive_core/backboard.dart';
import 'package:rive/src/rive_core/bones/bone.dart';
@ -94,7 +97,6 @@ import 'package:rive/src/rive_core/custom_property_number.dart';
import 'package:rive/src/rive_core/custom_property_string.dart';
import 'package:rive/src/rive_core/draw_rules.dart';
import 'package:rive/src/rive_core/draw_target.dart';
import 'package:rive/src/rive_core/event.dart';
import 'package:rive/src/rive_core/nested_artboard.dart';
import 'package:rive/src/rive_core/node.dart';
import 'package:rive/src/rive_core/shapes/clipping_shape.dart';
@ -120,6 +122,10 @@ import 'package:rive/src/rive_core/shapes/shape.dart';
import 'package:rive/src/rive_core/shapes/star.dart';
import 'package:rive/src/rive_core/shapes/straight_vertex.dart';
import 'package:rive/src/rive_core/shapes/triangle.dart';
import 'package:rive/src/rive_core/text/text.dart';
import 'package:rive/src/rive_core/text/text_style.dart';
import 'package:rive/src/rive_core/text/text_style_axis.dart';
import 'package:rive/src/rive_core/text/text_value_run.dart';
// ignore: avoid_classes_with_only_static_members
class RiveCoreContext {
@ -183,6 +189,8 @@ class RiveCoreContext {
return AnyState();
case StateMachineLayerBase.typeKey:
return StateMachineLayer();
case KeyFrameStringBase.typeKey:
return KeyFrameString();
case ListenerNumberChangeBase.typeKey:
return ListenerNumberChange();
case CubicEaseInterpolatorBase.typeKey:
@ -273,8 +281,6 @@ class RiveCoreContext {
return Image();
case CubicDetachedVertexBase.typeKey:
return CubicDetachedVertex();
case EventBase.typeKey:
return Event();
case DrawRulesBase.typeKey:
return DrawRules();
case CustomPropertyBooleanBase.typeKey:
@ -291,12 +297,22 @@ class RiveCoreContext {
return Skin();
case TendonBase.typeKey:
return Tendon();
case TextStyleBase.typeKey:
return TextStyle();
case TextStyleAxisBase.typeKey:
return TextStyleAxis();
case TextBase.typeKey:
return Text();
case TextValueRunBase.typeKey:
return TextValueRun();
case CustomPropertyStringBase.typeKey:
return CustomPropertyString();
case FolderBase.typeKey:
return Folder();
case ImageAssetBase.typeKey:
return ImageAsset();
case FontAssetBase.typeKey:
return FontAsset();
case FileAssetContentsBase.typeKey:
return FileAssetContents();
default:
@ -671,6 +687,11 @@ class RiveCoreContext {
object.value = value;
}
break;
case KeyFrameStringBase.valuePropertyKey:
if (object is KeyFrameStringBase && value is String) {
object.value = value;
}
break;
case ListenerNumberChangeBase.valuePropertyKey:
if (object is ListenerNumberChangeBase && value is double) {
object.value = value;
@ -1026,11 +1047,6 @@ class RiveCoreContext {
object.outDistance = value;
}
break;
case EventBase.typePropertyKey:
if (object is EventBase && value is String) {
object.type = value;
}
break;
case DrawRulesBase.drawTargetIdPropertyKey:
if (object is DrawRulesBase && value is int) {
object.drawTargetId = value;
@ -1161,6 +1177,61 @@ class RiveCoreContext {
object.ty = value;
}
break;
case TextStyleBase.fontSizePropertyKey:
if (object is TextStyleBase && value is double) {
object.fontSize = value;
}
break;
case TextStyleBase.fontAssetIdPropertyKey:
if (object is TextStyleBase && value is int) {
object.fontAssetId = value;
}
break;
case TextStyleAxisBase.tagPropertyKey:
if (object is TextStyleAxisBase && value is int) {
object.tag = value;
}
break;
case TextStyleAxisBase.axisValuePropertyKey:
if (object is TextStyleAxisBase && value is double) {
object.axisValue = value;
}
break;
case TextBase.alignValuePropertyKey:
if (object is TextBase && value is int) {
object.alignValue = value;
}
break;
case TextBase.sizingValuePropertyKey:
if (object is TextBase && value is int) {
object.sizingValue = value;
}
break;
case TextBase.overflowValuePropertyKey:
if (object is TextBase && value is int) {
object.overflowValue = value;
}
break;
case TextBase.widthPropertyKey:
if (object is TextBase && value is double) {
object.width = value;
}
break;
case TextBase.heightPropertyKey:
if (object is TextBase && value is double) {
object.height = value;
}
break;
case TextValueRunBase.styleIdPropertyKey:
if (object is TextValueRunBase && value is int) {
object.styleId = value;
}
break;
case TextValueRunBase.textPropertyKey:
if (object is TextValueRunBase && value is String) {
object.text = value;
}
break;
case CustomPropertyStringBase.propertyValuePropertyKey:
if (object is CustomPropertyStringBase && value is String) {
object.propertyValue = value;
@ -1205,7 +1276,8 @@ class RiveCoreContext {
case ComponentBase.namePropertyKey:
case AnimationBase.namePropertyKey:
case StateMachineComponentBase.namePropertyKey:
case EventBase.typePropertyKey:
case KeyFrameStringBase.valuePropertyKey:
case TextValueRunBase.textPropertyKey:
case CustomPropertyStringBase.propertyValuePropertyKey:
case AssetBase.namePropertyKey:
return stringType;
@ -1268,6 +1340,12 @@ class RiveCoreContext {
case DrawRulesBase.drawTargetIdPropertyKey:
case ArtboardBase.defaultStateMachineIdPropertyKey:
case TendonBase.boneIdPropertyKey:
case TextStyleBase.fontAssetIdPropertyKey:
case TextStyleAxisBase.tagPropertyKey:
case TextBase.alignValuePropertyKey:
case TextBase.sizingValuePropertyKey:
case TextBase.overflowValuePropertyKey:
case TextValueRunBase.styleIdPropertyKey:
case FileAssetBase.assetIdPropertyKey:
return uintType;
case CustomPropertyNumberBase.propertyValuePropertyKey:
@ -1354,6 +1432,10 @@ class RiveCoreContext {
case TendonBase.yyPropertyKey:
case TendonBase.txPropertyKey:
case TendonBase.tyPropertyKey:
case TextStyleBase.fontSizePropertyKey:
case TextStyleAxisBase.axisValuePropertyKey:
case TextBase.widthPropertyKey:
case TextBase.heightPropertyKey:
case DrawableAssetBase.heightPropertyKey:
case DrawableAssetBase.widthPropertyKey:
return doubleType;
@ -1398,8 +1480,10 @@ class RiveCoreContext {
return (object as AnimationBase).name;
case StateMachineComponentBase.namePropertyKey:
return (object as StateMachineComponentBase).name;
case EventBase.typePropertyKey:
return (object as EventBase).type;
case KeyFrameStringBase.valuePropertyKey:
return (object as KeyFrameStringBase).value;
case TextValueRunBase.textPropertyKey:
return (object as TextValueRunBase).text;
case CustomPropertyStringBase.propertyValuePropertyKey:
return (object as CustomPropertyStringBase).propertyValue;
case AssetBase.namePropertyKey:
@ -1528,6 +1612,18 @@ class RiveCoreContext {
return (object as ArtboardBase).defaultStateMachineId;
case TendonBase.boneIdPropertyKey:
return (object as TendonBase).boneId;
case TextStyleBase.fontAssetIdPropertyKey:
return (object as TextStyleBase).fontAssetId;
case TextStyleAxisBase.tagPropertyKey:
return (object as TextStyleAxisBase).tag;
case TextBase.alignValuePropertyKey:
return (object as TextBase).alignValue;
case TextBase.sizingValuePropertyKey:
return (object as TextBase).sizingValue;
case TextBase.overflowValuePropertyKey:
return (object as TextBase).overflowValue;
case TextValueRunBase.styleIdPropertyKey:
return (object as TextValueRunBase).styleId;
case FileAssetBase.assetIdPropertyKey:
return (object as FileAssetBase).assetId;
}
@ -1704,6 +1800,14 @@ class RiveCoreContext {
return (object as TendonBase).tx;
case TendonBase.tyPropertyKey:
return (object as TendonBase).ty;
case TextStyleBase.fontSizePropertyKey:
return (object as TextStyleBase).fontSize;
case TextStyleAxisBase.axisValuePropertyKey:
return (object as TextStyleAxisBase).axisValue;
case TextBase.widthPropertyKey:
return (object as TextBase).width;
case TextBase.heightPropertyKey:
return (object as TextBase).height;
case DrawableAssetBase.heightPropertyKey:
return (object as DrawableAssetBase).height;
case DrawableAssetBase.widthPropertyKey:
@ -1797,9 +1901,14 @@ class RiveCoreContext {
object.name = value;
}
break;
case EventBase.typePropertyKey:
if (object is EventBase) {
object.type = value;
case KeyFrameStringBase.valuePropertyKey:
if (object is KeyFrameStringBase) {
object.value = value;
}
break;
case TextValueRunBase.textPropertyKey:
if (object is TextValueRunBase) {
object.text = value;
}
break;
case CustomPropertyStringBase.propertyValuePropertyKey:
@ -2112,6 +2221,36 @@ class RiveCoreContext {
object.boneId = value;
}
break;
case TextStyleBase.fontAssetIdPropertyKey:
if (object is TextStyleBase) {
object.fontAssetId = value;
}
break;
case TextStyleAxisBase.tagPropertyKey:
if (object is TextStyleAxisBase) {
object.tag = value;
}
break;
case TextBase.alignValuePropertyKey:
if (object is TextBase) {
object.alignValue = value;
}
break;
case TextBase.sizingValuePropertyKey:
if (object is TextBase) {
object.sizingValue = value;
}
break;
case TextBase.overflowValuePropertyKey:
if (object is TextBase) {
object.overflowValue = value;
}
break;
case TextValueRunBase.styleIdPropertyKey:
if (object is TextValueRunBase) {
object.styleId = value;
}
break;
case FileAssetBase.assetIdPropertyKey:
if (object is FileAssetBase) {
object.assetId = value;
@ -2542,6 +2681,26 @@ class RiveCoreContext {
object.ty = value;
}
break;
case TextStyleBase.fontSizePropertyKey:
if (object is TextStyleBase) {
object.fontSize = value;
}
break;
case TextStyleAxisBase.axisValuePropertyKey:
if (object is TextStyleAxisBase) {
object.axisValue = value;
}
break;
case TextBase.widthPropertyKey:
if (object is TextBase) {
object.width = value;
}
break;
case TextBase.heightPropertyKey:
if (object is TextBase) {
object.height = value;
}
break;
case DrawableAssetBase.heightPropertyKey:
if (object is DrawableAssetBase) {
object.height = value;

View File

@ -1,7 +1,6 @@
/// Core automatically generated lib/src/generated/shapes/mesh_base.dart.
/// Do not modify manually.
import 'package:rive/src/core/core.dart';
import 'package:rive/src/generated/component_base.dart';
import 'package:rive/src/generated/container_component_base.dart';
import 'package:rive/src/rive_core/container_component.dart';

View File

@ -0,0 +1,153 @@
/// Core automatically generated lib/src/generated/text/text_base.dart.
/// Do not modify manually.
import 'package:rive/src/generated/component_base.dart';
import 'package:rive/src/generated/container_component_base.dart';
import 'package:rive/src/generated/node_base.dart';
import 'package:rive/src/generated/transform_component_base.dart';
import 'package:rive/src/generated/world_transform_component_base.dart';
import 'package:rive/src/rive_core/drawable.dart';
abstract class TextBase extends Drawable {
static const int typeKey = 134;
@override
int get coreType => TextBase.typeKey;
@override
Set<int> get coreTypes => {
TextBase.typeKey,
DrawableBase.typeKey,
NodeBase.typeKey,
TransformComponentBase.typeKey,
WorldTransformComponentBase.typeKey,
ContainerComponentBase.typeKey,
ComponentBase.typeKey
};
/// --------------------------------------------------------------------------
/// AlignValue field with key 281.
static const int alignValueInitialValue = 0;
int _alignValue = alignValueInitialValue;
static const int alignValuePropertyKey = 281;
int get alignValue => _alignValue;
/// Change the [_alignValue] field value.
/// [alignValueChanged] will be invoked only if the field's value has changed.
set alignValue(int value) {
if (_alignValue == value) {
return;
}
int from = _alignValue;
_alignValue = value;
if (hasValidated) {
alignValueChanged(from, value);
}
}
void alignValueChanged(int from, int to);
/// --------------------------------------------------------------------------
/// SizingValue field with key 284.
static const int sizingValueInitialValue = 0;
int _sizingValue = sizingValueInitialValue;
static const int sizingValuePropertyKey = 284;
int get sizingValue => _sizingValue;
/// Change the [_sizingValue] field value.
/// [sizingValueChanged] will be invoked only if the field's value has
/// changed.
set sizingValue(int value) {
if (_sizingValue == value) {
return;
}
int from = _sizingValue;
_sizingValue = value;
if (hasValidated) {
sizingValueChanged(from, value);
}
}
void sizingValueChanged(int from, int to);
/// --------------------------------------------------------------------------
/// OverflowValue field with key 287.
static const int overflowValueInitialValue = 0;
int _overflowValue = overflowValueInitialValue;
static const int overflowValuePropertyKey = 287;
/// One of visible, hidden, clipped, ellipsis.
int get overflowValue => _overflowValue;
/// Change the [_overflowValue] field value.
/// [overflowValueChanged] will be invoked only if the field's value has
/// changed.
set overflowValue(int value) {
if (_overflowValue == value) {
return;
}
int from = _overflowValue;
_overflowValue = value;
if (hasValidated) {
overflowValueChanged(from, value);
}
}
void overflowValueChanged(int from, int to);
/// --------------------------------------------------------------------------
/// Width field with key 285.
static const double widthInitialValue = 0;
double _width = widthInitialValue;
static const int widthPropertyKey = 285;
/// Width of the text object.
double get width => _width;
/// Change the [_width] field value.
/// [widthChanged] will be invoked only if the field's value has changed.
set width(double value) {
if (_width == value) {
return;
}
double from = _width;
_width = value;
if (hasValidated) {
widthChanged(from, value);
}
}
void widthChanged(double from, double to);
/// --------------------------------------------------------------------------
/// Height field with key 286.
static const double heightInitialValue = 0;
double _height = heightInitialValue;
static const int heightPropertyKey = 286;
/// Height of the text object.
double get height => _height;
/// Change the [_height] field value.
/// [heightChanged] will be invoked only if the field's value has changed.
set height(double value) {
if (_height == value) {
return;
}
double from = _height;
_height = value;
if (hasValidated) {
heightChanged(from, value);
}
}
void heightChanged(double from, double to);
@override
void copy(covariant TextBase source) {
super.copy(source);
_alignValue = source._alignValue;
_sizingValue = source._sizingValue;
_overflowValue = source._overflowValue;
_width = source._width;
_height = source._height;
}
}

View File

@ -0,0 +1,64 @@
/// Core automatically generated
/// lib/src/generated/text/text_style_axis_base.dart.
/// Do not modify manually.
import 'package:rive/src/rive_core/component.dart';
abstract class TextStyleAxisBase extends Component {
static const int typeKey = 144;
@override
int get coreType => TextStyleAxisBase.typeKey;
@override
Set<int> get coreTypes => {TextStyleAxisBase.typeKey, ComponentBase.typeKey};
/// --------------------------------------------------------------------------
/// Tag field with key 289.
static const int tagInitialValue = 0;
int _tag = tagInitialValue;
static const int tagPropertyKey = 289;
int get tag => _tag;
/// Change the [_tag] field value.
/// [tagChanged] will be invoked only if the field's value has changed.
set tag(int value) {
if (_tag == value) {
return;
}
int from = _tag;
_tag = value;
if (hasValidated) {
tagChanged(from, value);
}
}
void tagChanged(int from, int to);
/// --------------------------------------------------------------------------
/// AxisValue field with key 288.
static const double axisValueInitialValue = 0;
double _axisValue = axisValueInitialValue;
static const int axisValuePropertyKey = 288;
double get axisValue => _axisValue;
/// Change the [_axisValue] field value.
/// [axisValueChanged] will be invoked only if the field's value has changed.
set axisValue(double value) {
if (_axisValue == value) {
return;
}
double from = _axisValue;
_axisValue = value;
if (hasValidated) {
axisValueChanged(from, value);
}
}
void axisValueChanged(double from, double to);
@override
void copy(covariant TextStyleAxisBase source) {
super.copy(source);
_tag = source._tag;
_axisValue = source._axisValue;
}
}

View File

@ -0,0 +1,70 @@
/// Core automatically generated lib/src/generated/text/text_style_base.dart.
/// Do not modify manually.
import 'package:rive/src/generated/component_base.dart';
import 'package:rive/src/generated/container_component_base.dart';
import 'package:rive/src/rive_core/container_component.dart';
abstract class TextStyleBase extends ContainerComponent {
static const int typeKey = 137;
@override
int get coreType => TextStyleBase.typeKey;
@override
Set<int> get coreTypes => {
TextStyleBase.typeKey,
ContainerComponentBase.typeKey,
ComponentBase.typeKey
};
/// --------------------------------------------------------------------------
/// FontSize field with key 274.
static const double fontSizeInitialValue = 12;
double _fontSize = fontSizeInitialValue;
static const int fontSizePropertyKey = 274;
double get fontSize => _fontSize;
/// Change the [_fontSize] field value.
/// [fontSizeChanged] will be invoked only if the field's value has changed.
set fontSize(double value) {
if (_fontSize == value) {
return;
}
double from = _fontSize;
_fontSize = value;
if (hasValidated) {
fontSizeChanged(from, value);
}
}
void fontSizeChanged(double from, double to);
/// --------------------------------------------------------------------------
/// FontAssetId field with key 279.
static const int fontAssetIdInitialValue = -1;
int _fontAssetId = fontAssetIdInitialValue;
static const int fontAssetIdPropertyKey = 279;
int get fontAssetId => _fontAssetId;
/// Change the [_fontAssetId] field value.
/// [fontAssetIdChanged] will be invoked only if the field's value has
/// changed.
set fontAssetId(int value) {
if (_fontAssetId == value) {
return;
}
int from = _fontAssetId;
_fontAssetId = value;
if (hasValidated) {
fontAssetIdChanged(from, value);
}
}
void fontAssetIdChanged(int from, int to);
@override
void copy(covariant TextStyleBase source) {
super.copy(source);
_fontSize = source._fontSize;
_fontAssetId = source._fontAssetId;
}
}

View File

@ -0,0 +1,68 @@
/// Core automatically generated
/// lib/src/generated/text/text_value_run_base.dart.
/// Do not modify manually.
import 'package:rive/src/rive_core/component.dart';
abstract class TextValueRunBase extends Component {
static const int typeKey = 135;
@override
int get coreType => TextValueRunBase.typeKey;
@override
Set<int> get coreTypes => {TextValueRunBase.typeKey, ComponentBase.typeKey};
/// --------------------------------------------------------------------------
/// StyleId field with key 272.
static const int styleIdInitialValue = -1;
int _styleId = styleIdInitialValue;
static const int styleIdPropertyKey = 272;
/// The id of the style to be applied to this run.
int get styleId => _styleId;
/// Change the [_styleId] field value.
/// [styleIdChanged] will be invoked only if the field's value has changed.
set styleId(int value) {
if (_styleId == value) {
return;
}
int from = _styleId;
_styleId = value;
if (hasValidated) {
styleIdChanged(from, value);
}
}
void styleIdChanged(int from, int to);
/// --------------------------------------------------------------------------
/// Text field with key 268.
static const String textInitialValue = '';
String _text = textInitialValue;
static const int textPropertyKey = 268;
/// The text string value.
String get text => _text;
/// Change the [_text] field value.
/// [textChanged] will be invoked only if the field's value has changed.
set text(String value) {
if (_text == value) {
return;
}
String from = _text;
_text = value;
if (hasValidated) {
textChanged(from, value);
}
}
void textChanged(String from, String to);
@override
void copy(covariant TextValueRunBase source) {
super.copy(source);
_styleId = source._styleId;
_text = source._text;
}
}

View File

@ -18,7 +18,6 @@ abstract class BlendAnimation extends BlendAnimationBase {
@override
void onAdded() {}
@override
void onAddedDirty() {}

View File

@ -20,7 +20,6 @@ class KeyedObject extends KeyedObjectBase<RuntimeArtboard> {
@override
void onAdded() {}
bool isValidKeyedProperty(KeyedProperty property) {
var value = _keyedProperties[property.propertyKey];

View File

@ -62,7 +62,6 @@ class KeyedProperty extends KeyedPropertyBase<RuntimeArtboard>
@override
void onAddedDirty() {}
/// Called by rive_core to add a KeyFrame to this KeyedProperty. This should
/// be @internal when it's supported.
bool internalAddKeyFrame(KeyFrame frame) {

View File

@ -1,5 +1,7 @@
import 'package:rive/src/core/core.dart';
import 'package:rive/src/generated/animation/keyframe_base.dart';
import 'package:rive/src/rive_core/animation/cubic_interpolator.dart';
import 'package:rive/src/rive_core/animation/cubic_value_interpolator.dart';
import 'package:rive/src/rive_core/animation/interpolator.dart';
import 'package:rive/src/rive_core/animation/keyed_property.dart';
import 'package:rive/src/rive_core/animation/keyframe_interpolation.dart';
@ -42,8 +44,27 @@ abstract class KeyFrame extends KeyFrameBase<RuntimeArtboard>
if (interpolatorId != Core.missingId) {
interpolator = context.resolve(interpolatorId);
}
}
// Ensure interpolation types are valid, correct them if not.
switch (interpolation) {
case KeyFrameInterpolation.cubicValue:
if (interpolator is! CubicValueInterpolator) {
interpolation = canInterpolate
? KeyFrameInterpolation.linear
: KeyFrameInterpolation.hold;
}
break;
case KeyFrameInterpolation.cubic:
if (interpolator is! CubicInterpolator) {
interpolation = canInterpolate
? KeyFrameInterpolation.linear
: KeyFrameInterpolation.hold;
}
break;
default:
break;
}
}
@override
void frameChanged(int from, int to) {}

View File

@ -0,0 +1,22 @@
import 'package:rive/src/core/core.dart';
import 'package:rive/src/generated/animation/keyframe_string_base.dart';
export 'package:rive/src/generated/animation/keyframe_id_base.dart';
class KeyFrameString extends KeyFrameStringBase {
@override
bool get canInterpolate => false;
@override
void apply(Core<CoreContext> object, int propertyKey, double mix) {
RiveCoreContext.setString(object, propertyKey, value);
}
@override
void applyInterpolation(Core<CoreContext> object, int propertyKey,
double currentTime, KeyFrameString nextFrame, double mix) {
RiveCoreContext.setString(object, propertyKey, value);
}
@override
void valueChanged(String from, String to) {}
}

View File

@ -26,7 +26,6 @@ abstract class LayerState extends LayerStateBase {
_transitions.remove(transition);
}
StateInstance makeInstance();
@override

View File

@ -6,7 +6,6 @@ class LinearAnimationInstance {
final LinearAnimation animation;
double _time = 0;
double _lastTime = 0;
double _totalTime = 0;
double _lastTotalTime = 0;
int _direction = 1;
@ -21,9 +20,7 @@ class LinearAnimationInstance {
LinearAnimationInstance(this.animation)
: _time =
(animation.enableWorkArea ? animation.workStart : 0).toDouble() /
animation.fps {
_lastTime = _time;
}
animation.fps;
/// Note that when time is set, the direction will be changed to 1
set time(double value) {
@ -33,7 +30,7 @@ class LinearAnimationInstance {
// Make sure to keep last and total in relative lockstep so state machines
// can track change even when setting time.
var diff = _totalTime - _lastTotalTime;
_lastTime = _time = _totalTime = value;
_time = _totalTime = value;
_lastTotalTime = _totalTime - diff;
_direction = 1;
}
@ -41,9 +38,6 @@ class LinearAnimationInstance {
/// Returns the current time position of the animation in seconds
double get time => _time;
/// Returns the time the position was at when the previous advance was called.
double get lastTime => _lastTime;
/// Direction should only be +1 or -1
set direction(int value) => _direction = value == -1 ? -1 : 1;
@ -70,7 +64,6 @@ class LinearAnimationInstance {
var deltaSeconds = elapsedSeconds * animation.speed * _direction;
_lastTotalTime = _totalTime;
_totalTime += deltaSeconds;
_lastTime = _time;
_time += deltaSeconds;
double frames = _time * animation.fps;
@ -84,40 +77,47 @@ class LinearAnimationInstance {
_didLoop = false;
_spilledTime = 0;
int direction = animation.speed < 0 ? -_direction : _direction;
switch (animation.loop) {
case Loop.oneShot:
if (frames > end) {
if (direction == 1 && frames > end) {
keepGoing = false;
_spilledTime = (frames - end) / fps;
frames = end.toDouble();
_time = frames / fps;
_didLoop = true;
} else if (direction == -1 && frames < start) {
keepGoing = false;
_spilledTime = (start - frames) / fps;
frames = start.toDouble();
_time = frames / fps;
_didLoop = true;
}
break;
case Loop.loop:
if (frames >= end) {
if (direction == 1 && frames >= end) {
_spilledTime = (frames - end) / fps;
frames = _time * fps;
frames = start + (frames - start) % range;
_time = frames / fps;
_didLoop = true;
} else if (direction == -1 && frames <= start) {
_spilledTime = (start - frames) / fps;
frames = _time * fps;
frames = end - (start - frames) % range;
_time = frames / fps;
_didLoop = true;
}
break;
case Loop.pingPong:
// ignore: literal_only_boolean_expressions
while (true) {
if (_direction == 1 && frames >= end) {
if (direction == 1 && frames >= end) {
_spilledTime = (frames - end) / animation.fps;
_direction = -1;
frames = end + (end - frames);
_time = frames / animation.fps;
_didLoop = true;
} else if (_direction == -1 && frames < start) {
} else if (direction == -1 && frames < start) {
_spilledTime = (start - frames) / animation.fps;
_direction = 1;
frames = start + (start - frames);
_time = frames / animation.fps;
_didLoop = true;
} else {
// we're within the range, we can stop fixing. We do this in a
// loop to fix conditions when time has advanced so far that we've
@ -126,7 +126,10 @@ class LinearAnimationInstance {
// advanced on regular intervals.
break;
}
_lastTime = _time;
_time = frames / animation.fps;
_direction *= -1;
direction *= -1;
_didLoop = true;
}
break;
}

View File

@ -37,7 +37,6 @@ class StateTransition extends StateTransitionBase {
@override
void onAddedDirty() {}
bool get isDisabled => (flags & StateTransitionFlags.disabled) != 0;
bool get pauseOnExit => (flags & StateTransitionFlags.pauseOnExit) != 0;
bool get enableExitTime => (flags & StateTransitionFlags.enableExitTime) != 0;

View File

@ -93,9 +93,6 @@ class Artboard extends ArtboardBase with ShapePaintContainer {
Iterable<StateMachine> get stateMachines =>
_animations.whereType<StateMachine>();
/// Does this artboard have animations?
bool get hasAnimations => _animations.isNotEmpty;
int _dirtDepth = 0;
/// Iterate each component and call callback for it.
@ -327,7 +324,7 @@ class Artboard extends ArtboardBase with ShapePaintContainer {
for (var drawable = _firstDrawable;
drawable != null;
drawable = drawable.prev) {
if (drawable.isHidden) {
if (drawable.isHidden || drawable.renderOpacity == 0) {
continue;
}
drawable.draw(canvas);

View File

@ -0,0 +1,46 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:rive/src/generated/assets/font_asset_base.dart';
import 'package:rive_common/rive_text.dart';
export 'package:rive/src/generated/assets/font_asset_base.dart';
class FontAsset extends FontAssetBase {
final Set<VoidCallback> _decodedCallbacks = {};
/// Call [callback] when the font is ready. Set [notifyAlreadyDecoded] to
/// specify if you want to be called if the font is already decoded.
bool whenDecoded(VoidCallback callback, {bool notifyAlreadyDecoded = true}) {
if (font != null) {
if (notifyAlreadyDecoded) {
callback();
}
return true;
}
_decodedCallbacks.add(callback);
return false;
}
Font? font;
@override
Future<void> decode(Uint8List bytes) async {
font = Font.decode(bytes);
var callbacks = _decodedCallbacks.toList(growable: false);
_decodedCallbacks.clear();
for (final callback in callbacks) {
callback();
}
}
@override
void onRemoved() {
super.onRemoved();
font?.dispose();
font = null;
}
@override
String get fileExtension => 'ttf';
}

View File

@ -1,4 +1,3 @@
import 'package:rive/src/core/core.dart';
import 'package:rive/src/generated/component_base.dart';
import 'package:rive/src/rive_core/artboard.dart';
import 'package:rive/src/rive_core/container_component.dart';

View File

@ -46,5 +46,4 @@ class ComponentFlags {
/// End of TransformComponentConstraint
///
/// ----------
}

View File

@ -4,6 +4,8 @@ import 'package:rive/src/rive_core/component.dart';
import 'package:rive/src/rive_core/draw_rules.dart';
import 'package:rive/src/rive_core/drawable.dart';
export 'package:rive/src/core/core.dart';
typedef bool DescentCallback(Component component);
abstract class ContainerComponent extends ContainerComponentBase {

View File

@ -6,6 +6,7 @@ import 'package:rive/src/rive_core/assets/file_asset.dart';
import 'package:rive/src/rive_core/assets/image_asset.dart';
import 'package:rive/src/rive_core/bones/skinnable.dart';
import 'package:rive/src/rive_core/component.dart';
import 'package:rive/src/rive_core/container_component.dart';
import 'package:rive/src/rive_core/shapes/mesh.dart';
import 'package:rive/src/rive_core/shapes/mesh_vertex.dart';
import 'package:rive_common/math.dart';
@ -44,7 +45,8 @@ class Image extends ImageBase
final paint = ui.Paint()
..color = ui.Color.fromRGBO(0, 0, 0, renderOpacity)
..filterQuality = ui.FilterQuality.high;
..filterQuality = ui.FilterQuality.high
..blendMode = blendMode;
final width = asset!.width;
final height = asset!.height;

View File

@ -34,7 +34,7 @@ class Fill extends FillBase {
@override
void draw(Canvas canvas, Path path) {
if (!isVisible) {
if (!isVisible || renderOpacity == 0) {
return;
}
path.fillType = fillType;

View File

@ -20,7 +20,7 @@ class LinearGradient extends LinearGradientBase with ShapePaintMutator {
/// this container.
final List<GradientStop> gradientStops = [];
bool _paintsInWorldSpace = true;
bool _paintsInWorldSpace = false;
bool get paintsInWorldSpace => _paintsInWorldSpace;
set paintsInWorldSpace(bool value) {
if (_paintsInWorldSpace == value) {
@ -65,11 +65,17 @@ class LinearGradient extends LinearGradientBase with ShapePaintMutator {
/// Mark the gradient stops as changed. This will re-sort the stops and
/// rebuild the necessary gradients in the next update cycle.
void markStopsDirty() => addDirt(ComponentDirt.stops | ComponentDirt.paint);
void markStopsDirty() {
addDirt(ComponentDirt.stops | ComponentDirt.paint);
markPaintDirty();
}
/// Mark the gradient as needing to be rebuilt. This is a more efficient
/// version of markStopsDirty as it won't re-sort the stops.
void markGradientDirty() => addDirt(ComponentDirt.paint);
void markGradientDirty() {
addDirt(ComponentDirt.paint);
markPaintDirty();
}
@override
void update(int dirt) {
@ -120,23 +126,29 @@ class LinearGradient extends LinearGradientBase with ShapePaintMutator {
@override
void startXChanged(double from, double to) {
addDirt(ComponentDirt.transform);
markPaintDirty();
}
@override
void startYChanged(double from, double to) {
addDirt(ComponentDirt.transform);
markPaintDirty();
}
@override
void endXChanged(double from, double to) {
addDirt(ComponentDirt.transform);
markPaintDirty();
}
@override
void endYChanged(double from, double to) {
addDirt(ComponentDirt.transform);
markPaintDirty();
}
void markPaintDirty() => shapePaintContainer?.addDirt(ComponentDirt.paint);
@override
void onAdded() {
super.onAdded();
@ -148,7 +160,7 @@ class LinearGradient extends LinearGradientBase with ShapePaintMutator {
syncColor();
// We don't need to rebuild anything, just let our shape know we should
// repaint.
shapePaintContainer!.addDirt(ComponentDirt.paint);
markPaintDirty();
}
@override

View File

@ -1,6 +1,5 @@
import 'dart:ui';
import 'package:meta/meta.dart';
import 'package:rive/src/generated/shapes/paint/shape_paint_base.dart';
import 'package:rive/src/rive_core/component.dart';
import 'package:rive/src/rive_core/component_dirt.dart';

View File

@ -84,7 +84,7 @@ class Stroke extends StrokeBase {
@override
void draw(Canvas canvas, Path path) {
if (!isVisible) {
if (!isVisible || renderOpacity == 0) {
return;
}

View File

@ -1,5 +1,6 @@
import 'package:meta/meta.dart';
import 'package:rive/src/rive_core/component.dart';
import 'package:rive/src/rive_core/container_component.dart';
import 'package:rive/src/rive_core/shapes/paint/fill.dart';
import 'package:rive/src/rive_core/shapes/paint/shape_paint_mutator.dart';
import 'package:rive/src/rive_core/shapes/paint/stroke.dart';

View File

@ -25,7 +25,8 @@ import 'package:rive/src/rive_core/shapes/shape.dart';
import 'package:rive_common/math.dart';
/// Callback signature for state machine state changes
typedef OnStateChange = void Function(String, String);
typedef OnStateChange = void Function(
String stateMachineName, String stateName);
/// Callback signature for layer state changes
typedef OnLayerStateChange = void Function(LayerState);

View File

@ -0,0 +1,40 @@
import 'package:rive_common/rive_text.dart';
import 'package:rive_common/utilities.dart';
class StyledText {
final String value;
final List<TextRun> runs;
factory StyledText(String text, List<TextRun> runs) {
assert(runs.isNotEmpty);
var extendedRuns = runs.take(runs.length - 1).toList();
extendedRuns
.add(runs.last.copyWith(unicharCount: runs.last.unicharCount + 1));
return StyledText.exact(text + ' ', extendedRuns);
}
factory StyledText.empty(TextRun run) => StyledText('', [run]);
StyledText withoutLastCharacter() {
assert(value.isNotEmpty);
var shortenedRuns = runs.take(runs.length - 1).toList();
if (runs.last.unicharCount > 1) {
// Only add the last run if it's not 0 length.
shortenedRuns
.add(runs.last.copyWith(unicharCount: runs.last.unicharCount - 1));
}
return StyledText.exact(
value.substring(0, value.length - 1), shortenedRuns);
}
StyledText.exact(this.value, this.runs);
@override
bool operator ==(Object other) =>
other is StyledText &&
other.value == value &&
iterableEquals(other.runs, runs);
@override
int get hashCode => Object.hash(value, Object.hashAll(runs));
}

View File

@ -0,0 +1,382 @@
import 'dart:ui';
import 'package:flutter/services.dart';
import 'package:rive/src/generated/text/text_base.dart';
import 'package:rive/src/rive_core/component_dirt.dart';
import 'package:rive/src/rive_core/text/styled_text.dart';
import 'package:rive/src/rive_core/text/text_style.dart' as rive;
import 'package:rive/src/rive_core/text/text_style_container.dart';
import 'package:rive/src/rive_core/text/text_value_run.dart';
import 'package:rive_common/rive_text.dart';
export 'package:rive/src/generated/text/text_base.dart';
enum TextSizing {
autoWidth,
autoHeight,
fixed,
}
enum TextOverflow {
visible,
hidden,
clipped,
ellipsis,
}
class Text extends TextBase with TextStyleContainer {
TextShapeResult? _shape;
// Shapes that should be cleaned before next shaping call.
final List<TextShapeResult> _cleanupShapes = [];
BreakLinesResult? _lines;
// TextShapeResult? get shape => _shape;
BreakLinesResult? get lines => _lines;
bool get isEmpty => runs.isEmpty || !runs.any((run) => run.text.isNotEmpty);
StyledText makeStyled(Font defaultFont, {bool forEditing = false}) {
final List<TextRun> textRuns = [];
final buffer = StringBuffer();
int runIndex = 0;
for (final run in runs) {
if (run.text.isEmpty) {
runIndex++;
continue;
}
buffer.write(run.text);
textRuns.add(TextRun(
font: run.style?.font ?? defaultFont,
fontSize: run.style?.fontSize ?? 16,
unicharCount: run.text.codeUnits.length,
styleId: runIndex++,
));
}
// Couldn't fit anything?
if (textRuns.isEmpty && runs.isNotEmpty) {
var run = runs.first;
textRuns.add(TextRun(
font: run.style?.font ?? defaultFont,
fontSize: run.style?.fontSize ?? 16,
unicharCount: run.text.codeUnits.length,
styleId: 0,
));
}
// We keep an empty space at the end of the buffer if it's for editing
// purposes (we need to know where the final cursor goes and we want some
// sense of shape even when completely empty).
return forEditing || buffer.isEmpty
? StyledText(buffer.toString(), textRuns)
: StyledText.exact(buffer.toString(), textRuns);
}
String get text {
final buffer = StringBuffer();
for (final run in runs) {
buffer.write(run.text);
}
return buffer.toString();
}
/// [defaultFont] will be removed when we add asset font options.
TextShapeResult? shape(Font defaultFont) {
if (_shape != null) {
return _shape;
}
var styled = makeStyled(defaultFont);
return _shape = defaultFont.shape(
styled.value,
styled.runs,
);
}
void _disposeShape() {
for (final shape in _cleanupShapes) {
shape.dispose();
}
_cleanupShapes.clear();
_shape = null;
}
rive.TextStyle? styleFromShaperId(int id) => runFromShaperId(id)?.style;
TextValueRun? runFromShaperId(int id) => id < _runs.length ? _runs[id] : null;
List<TextValueRun> _runs = [];
Iterable<TextValueRun> get runs => _runs;
void _syncRuns() {
_runs = children.whereType<TextValueRun>().toList(growable: false);
updateStyles();
}
@override
void onAdded() {
super.onAdded();
_syncRuns();
}
// We cache the text drawing into a display list so subsequent draws are
// faster.
Picture? _textPicture;
final Size _size = Size.zero;
static const double paragraphSpacing = 20;
void forEachGlyph(
bool Function(LineRunGlyph, double, double, GlyphLine) callback) {
var lines = _lines;
var shape = _shape;
if (lines == null || shape == null) {
return;
}
double y = 0;
double maxX = 0;
var paragraphIndex = 0;
for (final paragraphLines in lines) {
final paragraph = shape.paragraphs[paragraphIndex++];
for (final line in paragraphLines) {
double x = line.startX;
for (final glyphInfo in line.glyphs(paragraph)) {
var run = glyphInfo.run;
if (!callback(glyphInfo, x, y, line)) {
return;
}
x += run.advanceAt(glyphInfo.index);
}
if (x > maxX) {
maxX = x;
}
}
if (paragraphLines.isNotEmpty) {
y += paragraphLines.last.bottom;
}
y += paragraphSpacing;
}
}
@override
void draw(Canvas canvas) {
var lines = _lines;
var shape = _shape;
if (lines == null || shape == null) {
return;
}
if (_textPicture == null) {
var recorder = PictureRecorder();
var canvas = Canvas(recorder);
double y = 0;
double maxX = 0;
var paragraphIndex = 0;
int ellipsisLine = -1;
bool isEllipsisLineLast = false;
// Find the line to put the ellipsis on (line before the one that
// overflows).
if (overflow == TextOverflow.ellipsis && sizing == TextSizing.fixed) {
int lastLineIndex = -1;
for (final paragraphLines in lines) {
for (final line in paragraphLines) {
lastLineIndex++;
if (y + line.bottom <= height) {
ellipsisLine++;
}
}
if (paragraphLines.isNotEmpty) {
y += paragraphLines.last.bottom;
}
y += paragraphSpacing;
}
if (ellipsisLine == -1) {
// Nothing fits, just show the first line and ellipse it.
ellipsisLine = 0;
}
isEllipsisLineLast = lastLineIndex == ellipsisLine;
y = 0;
}
int lineIndex = 0;
outer:
for (final paragraphLines in lines) {
final paragraph = shape.paragraphs[paragraphIndex++];
for (final line in paragraphLines) {
switch (overflow) {
case TextOverflow.hidden:
if (sizing == TextSizing.fixed && y + line.bottom > height) {
break outer;
}
break;
case TextOverflow.clipped:
if (sizing == TextSizing.fixed && y + line.top > height) {
break outer;
}
break;
default:
break;
}
double x = line.startX;
for (final glyphInfo in lineIndex == ellipsisLine
? line.glyphsWithEllipsis(
width,
paragraph: paragraph,
isLastLine: isEllipsisLineLast,
cleanupShapes: _cleanupShapes,
)
: line.glyphs(paragraph)) {
var run = glyphInfo.run;
var font = run.font;
var path = font.getUiPath(run.glyphIdAt(glyphInfo.index));
// canvas.save();
// canvas.transform();
var renderPath =
path.transform(glyphInfo.renderTransform(x, y + line.baseline));
var style = styleFromShaperId(run.styleId);
if (style == null || style.shapePaints.isEmpty) {
canvas.drawPath(
renderPath,
Paint()..color = const Color(0xFFFFFFFF),
);
} else {
for (final shapePaint in style.shapePaints) {
if (!shapePaint.isVisible) {
continue;
}
canvas.drawPath(
renderPath,
shapePaint.paint,
);
}
}
// canvas.restore();
x += run.advanceAt(glyphInfo.index);
}
if (x > maxX) {
maxX = x;
}
if (lineIndex == ellipsisLine) {
break outer;
}
lineIndex++;
}
if (paragraphLines.isNotEmpty) {
y += paragraphLines.last.bottom;
}
y += paragraphSpacing;
}
_textPicture = recorder.endRecording();
}
canvas.save();
canvas.transform(worldTransform.mat4);
if (overflow == TextOverflow.clipped) {
canvas.clipRect(Offset.zero & _size);
}
canvas.drawPicture(_textPicture!);
canvas.restore();
}
void markShapeDirty() {
_disposeShape();
addDirt(ComponentDirt.path);
}
// TODO: figure out asset system
static Font? _defaultFont;
void markPaintDirty() {
_textPicture?.dispose();
_textPicture = null;
}
void computeShape() {
markPaintDirty();
_shape = null;
_lines?.dispose();
_lines = null;
if (runs.isEmpty) {
return;
}
_shape = shape(_defaultFont!);
_cleanupShapes.add(_shape!);
_lines =
_shape?.breakLines(sizing == TextSizing.autoWidth ? -1 : width, align);
}
@override
void update(int dirt) {
super.update(dirt);
if (dirt & ComponentDirt.path != 0) {
// Hardcode font for now.
if (_defaultFont == null) {
rootBundle.load('assets/fonts/Inter-Regular.ttf').then((fontAsset) {
_defaultFont = Font.decode(fontAsset.buffer.asUint8List());
// Reshape now that we have font.
markShapeDirty();
});
} else {
computeShape();
}
}
}
@override
void onRemoved() {
super.onRemoved();
_disposeShape();
_lines?.dispose();
disposeStyleContainer();
_lines = null;
}
@override
void alignValueChanged(int from, int to) => markShapeDirty();
TextAlign get align => TextAlign.values[alignValue];
set align(TextAlign value) => alignValue = value.index;
@override
void heightChanged(double from, double to) {
if (sizing == TextSizing.fixed) {
markShapeDirty();
}
}
TextSizing get sizing => TextSizing.values[sizingValue];
set sizing(TextSizing value) => sizingValue = value.index;
TextOverflow get overflow {
return TextOverflow.values[overflowValue];
}
set overflow(TextOverflow value) => overflowValue = value.index;
@override
void sizingValueChanged(int from, int to) {
markShapeDirty();
}
@override
void widthChanged(double from, double to) {
if (sizing != TextSizing.autoWidth) {
markShapeDirty();
}
}
@override
void overflowValueChanged(int from, int to) {
if (sizing != TextSizing.autoWidth) {
markShapeDirty();
}
}
}

View File

@ -0,0 +1,207 @@
import 'package:rive/src/generated/text/text_style_base.dart';
import 'package:rive/src/rive_core/artboard.dart';
import 'package:rive/src/rive_core/assets/file_asset.dart';
import 'package:rive/src/rive_core/assets/font_asset.dart';
import 'package:rive/src/rive_core/component.dart';
import 'package:rive/src/rive_core/component_dirt.dart';
import 'package:rive/src/rive_core/shapes/paint/shape_paint.dart';
import 'package:rive/src/rive_core/shapes/paint/shape_paint_mutator.dart';
import 'package:rive/src/rive_core/shapes/shape_paint_container.dart';
import 'package:rive/src/rive_core/text/text.dart';
import 'package:rive/src/rive_core/text/text_style_axis.dart';
import 'package:rive/src/rive_core/text/text_value_run.dart';
import 'package:rive_common/math.dart';
import 'package:rive_common/rive_text.dart';
export 'package:rive/src/generated/text/text_style_base.dart';
class TextVariationHelper extends Component {
final TextStyle style;
Font? _font;
@override
Artboard? get artboard => style.artboard;
Font? get font => _font;
TextVariationHelper(this.style) {
style.markRebuildDependencies();
}
@override
void update(int dirt) {
_font?.dispose();
_font = style._makeVariableFont();
}
void dispose() {
_font?.dispose();
_font = null;
}
@override
void buildDependencies() {
var text = style.text;
if (text != null) {
text.artboard?.addDependent(this);
addDependent(text);
}
}
}
class TextStyle extends TextStyleBase
with ShapePaintContainer, FileAssetReferencer<FontAsset> {
final Set<TextValueRun> _referencers = {};
Text? get text => parent as Text?;
final Set<TextStyleAxis> _variations = {};
Iterable<TextStyleAxis> get variations => _variations;
Iterable<FontAxis> get variableAxes => asset?.font?.axes ?? [];
bool get hasVariableAxes => asset?.font?.axes.isNotEmpty ?? false;
TextVariationHelper? _variationHelper;
TextVariationHelper? get variationHelper => _variationHelper;
Font? _makeVariableFont() => asset?.font?.makeVariation(
_variations.map((axis) => FontAxisCoord(axis.tag, axis.axisValue)));
Font? get font => _variationHelper?.font ?? asset?.font;
List<ShapePaint> get shapePaints =>
fills.cast<ShapePaint>().toList() + strokes.cast<ShapePaint>().toList();
/// An identifier used by the shaper to remap style ids as text runs are
/// converted to glyph runs.
int shaperId = -1;
@override
void fontSizeChanged(double from, double to) => _markShapeDirty();
void _markShapeDirty() {
for (final run in _referencers) {
run.markShapeDirty();
}
}
@override
void update(int dirt) {}
/// Let the style know that a run references it.
void ref(TextValueRun run) {
_referencers.add(run);
}
void deref(TextValueRun run) {
_referencers.remove(run);
}
@override
String toString() => '${super.toString()} -> FontSize($fontSize)';
@override
void buildDependencies() {
parent?.addDependent(this);
_variationHelper?.buildDependencies();
}
@override
set asset(FontAsset? value) {
if (asset == value) {
return;
}
_variations.toSet().forEach(context.removeObject);
super.asset = value;
if (asset?.whenDecoded(_fontDecoded, notifyAlreadyDecoded: false) ??
false) {
// Already decoded.
_markShapeDirty();
}
}
@override
void fontAssetIdChanged(int from, int to) {
asset = context.resolve(to);
}
void _fontDecoded() => _markShapeDirty();
@override
void onAddedDirty() {
super.onAddedDirty();
asset = context.resolve(fontAssetId);
}
@override
void onDirty(int mask) {
super.onDirty(mask);
if ((mask & ComponentDirt.paint) != 0) {
text?.markPaintDirty();
}
if ((mask & ComponentDirt.textShape) != 0) {
text?.markShapeDirty();
_variationHelper?.addDirt(ComponentDirt.textShape);
}
}
@override
void onFillsChanged() {
text?.markPaintDirty();
}
@override
void onPaintMutatorChanged(ShapePaintMutator mutator) {
text?.markPaintDirty();
}
@override
void onStrokesChanged() {
text?.markPaintDirty();
}
@override
Mat2D get worldTransform => text?.worldTransform ?? Mat2D.identity;
@override
Vec2D get worldTranslation => text?.worldTranslation ?? Vec2D();
@override
void childAdded(Component component) {
super.childAdded(component);
if (component is TextStyleAxis) {
if (_variations.add(component)) {
_variationHelper ??= TextVariationHelper(this);
addDirt(ComponentDirt.textShape);
}
}
}
@override
void childRemoved(Component component) {
super.childRemoved(component);
if (component is TextStyleAxis) {
if (_variations.remove(component)) {
addDirt(ComponentDirt.textShape);
if (_variations.isEmpty) {
_variationHelper?.dispose();
_variationHelper = null;
}
}
}
}
@override
void onRemoved() {
super.onRemoved();
_variationHelper?.dispose();
_variationHelper = null;
}
@override
int get assetId => fontAssetId;
@override
set assetId(int value) => fontAssetId = value;
@override
int get assetIdPropertyKey => TextStyleBase.fontAssetIdPropertyKey;
}

View File

@ -0,0 +1,23 @@
import 'package:rive/src/generated/text/text_style_axis_base.dart';
import 'package:rive/src/rive_core/component_dirt.dart';
import 'package:rive/src/rive_core/text/text_style.dart';
import 'package:rive_common/rive_text.dart';
export 'package:rive/src/generated/text/text_style_axis_base.dart';
class TextStyleAxis extends TextStyleAxisBase {
@override
bool validate() => super.validate() && parent is TextStyle;
String get tagName => FontAxis.tagToName(tag);
@override
void update(int dirt) {}
@override
void axisValueChanged(double from, double to) =>
parent?.addDirt(ComponentDirt.textShape);
@override
void tagChanged(int from, int to) => parent?.addDirt(ComponentDirt.textShape);
}

View File

@ -0,0 +1,65 @@
import 'dart:collection';
import 'package:rive/src/rive_core/component.dart';
import 'package:rive/src/rive_core/container_component.dart';
import 'package:rive/src/rive_core/text/text_style.dart';
import 'package:rive_common/utilities.dart';
/// An abstraction to give a common interface to any component that can contain
/// TextStyles. Currently used by the [Text] object but we can later support
/// file-wide styles by making them owned by an [Artboard] or [Backboard].
abstract class TextStyleContainer {
int _nextShaperId = 0;
final Set<TextStyle> styles = {};
final HashMap<int, TextStyle> _styleLookup = HashMap<int, TextStyle>();
// TextStyle? styleFromShaperId(int id) => _styleLookup[id];
void disposeStyleContainer() {
_styleLookup.clear();
styles.clear();
}
bool addStyle(TextStyle style) {
if (styles.add(style)) {
_registerStyle(style);
return true;
}
return false;
}
void _registerStyle(TextStyle style) {
if (style.shaperId == -1) {
style.shaperId = _nextShaperId++;
_styleLookup[style.shaperId] = style;
}
}
ContainerChildren get children;
void updateStyles() {
var nextStyles = children.whereType<TextStyle>();
if (!iterableEquals(nextStyles, styles)) {
styles.clear();
styles.addAll(nextStyles);
styles.forEach(_registerStyle);
}
}
bool removeStyle(TextStyle style) {
if (styles.remove(style)) {
return true;
}
return false;
}
/// These usually gets auto implemented as this mixin is meant to be added to
/// a ComponentBase. This way the implementor doesn't need to cast
/// ShapePaintContainer to ContainerComponent/Shape/Artboard/etc.
bool addDirt(int value, {bool recurse = false});
bool addDependent(Component dependent, {Component? via});
void appendChild(Component child);
// Mat2D get worldTransform;
// Vec2D get worldTranslation;
}

View File

@ -0,0 +1,50 @@
import 'package:rive/src/core/core.dart';
import 'package:rive/src/generated/text/text_value_run_base.dart';
import 'package:rive/src/rive_core/text/text.dart';
import 'package:rive/src/rive_core/text/text_style.dart';
export 'package:rive/src/generated/text/text_value_run_base.dart';
class TextValueRun extends TextValueRunBase {
Text? get textComponent => parent as Text?;
TextStyle? _style;
TextStyle? get style => _style;
set style(TextStyle? value) {
if (_style == value) {
return;
}
_style?.deref(this);
_style = value;
styleId = value?.id ?? Core.missingId;
_style?.ref(this);
}
void markShapeDirty() => textComponent?.markShapeDirty();
@override
void onAdded() {}
@override
void styleIdChanged(int from, int to) {
style = context.resolve(to);
}
@override
void onRemoved() {
super.onRemoved();
_style?.deref(this);
}
@override
void onAddedDirty() {
super.onAddedDirty();
style = context.resolve(styleId);
}
@override
void update(int dirt) {}
@override
void textChanged(String from, String to) => textComponent?.markShapeDirty();
}

View File

@ -1,4 +1,3 @@
import 'package:flutter/foundation.dart';
import 'package:rive/src/generated/transform_component_base.dart';
import 'package:rive/src/rive_core/component.dart';
import 'package:rive/src/rive_core/component_dirt.dart';

View File

@ -1,5 +1,5 @@
name: rive
version: 0.10.1
version: 0.10.2
homepage: https://rive.app
description: Rive 2 Flutter Runtime. This package provides runtime functionality for playing back and interacting with animations built with the Rive editor available at https://rive.app.
repository: https://github.com/rive-app/rive-flutter

View File

@ -14,7 +14,7 @@ void main() {
test('LinearAnimationInstance exposes direction is either +/-1', () {
final artboard = riveFile.mainArtboard;
expect(artboard.hasAnimations, isTrue);
expect(artboard.animations, isNotEmpty);
LinearAnimationInstance instance =
LinearAnimationInstance(artboard.animations.first as LinearAnimation);
@ -29,7 +29,7 @@ void main() {
test('LinearAnimationInstance has a valid start and end time', () {
final artboard = riveFile.mainArtboard;
expect(artboard.hasAnimations, isTrue);
expect(artboard.animations, isNotEmpty);
LinearAnimationInstance instance =
LinearAnimationInstance(artboard.animations.first as LinearAnimation);
@ -49,7 +49,7 @@ void main() {
test('LinearAnimationInstance can be reset', () {
final artboard = riveFile.mainArtboard;
expect(artboard.hasAnimations, isTrue);
expect(artboard.animations, isNotEmpty);
LinearAnimationInstance instance =
LinearAnimationInstance(artboard.animations.first as LinearAnimation);