rive_common package

I started adding Text features to rive_core and realized that the dependency structure is going to be very difficult to manage here. Here's why:

## rive_core
 - has most of the runtime logic for things like IK, mesh, shapes, etc

## rive_flutter
 - depends on rive_core (not directly but we transpile rive_core to rive_flutter)
 - also includes the FFI/WASM text runtime

The problem is that rive_core needs the FFI/WASM text runtime. So we have a cyclic dependency. We've dealt with something similar (not quite as extreme) by abstracting things like nested artboards, but it gets very complex for a verbose API like the text one.

## rive_common
What this PR does is reworks a lot of shared logic like Math (Vec2D, Mat2D, etc), low-level text runtime (FFI/WASM), etc into a "rive_common" package. We've had shared packages before but none that have been shared by rive_flutter and rive_editor. I think it's finally time to bite the bullet here.

This will make it much easier to work through some of the obtuse abstraction patterns we've had to do to disambiguate if you're using a Vec2D from the runtime or the editor, for example.

Yes, this means we'll only have one set of math classes, one set of binary writer/readers, etc. I only did the bare minimum necessary to move text into rive_common in this first pass but we can do more as we go forward.

## TODO:
- [x] move Text WASM & FFI to rive_common
- [x] move Math used by text (Mat2D, Vec2D, TransformComponents, PathInterface, etc) to rive_common
- [x] move utilities used by text (binary reader/writer) to rive_common
- [x] fix core_generator and core_generator_runtime
- [x] fix github actions to use new paths
- [x] publish rive_common to pub.dev and unlist it

Diffs=
12c6ee130 rive_common package (#4434)
5a24e63d0 Initialize isClosed on TessRenderPath (#4431)
This commit is contained in:
luigi-rosso
2022-11-19 20:19:05 +00:00
parent e618def5cd
commit af6e7d4c07
122 changed files with 81 additions and 11799 deletions

View File

@ -24,15 +24,5 @@ jobs:
flutter channel stable
flutter doctor
- name: Build WASM
run: |
cd wasm
./build_wasm.sh release
- name: Build Shared Lib
run: |
cd shared_lib
./build_shared.sh
- name: Run tests
run: flutter test

View File

@ -1 +1 @@
3be5ff0d873280d2bcec300fb764f016ac96a08d
12c6ee13010f1f73354358ae169e4f81e646b8be

9
android/.gitignore vendored
View File

@ -1,9 +0,0 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
.cxx

View File

@ -1,79 +0,0 @@
cmake_minimum_required(VERSION 3.4.1) # for example
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -DWITH_RIVE_TEXT -DHAVE_OT -DHB_NO_FALLBACK_SHAPE -DHB_NO_WIN1256 -std=c++17"
)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSB_CONFIG_UNITY")
add_library(
rive_text
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
../ios/rive_text/rive_text.cpp
../ios/rive-cpp/src/math/raw_path.cpp
../ios/rive-cpp/src/math/mat2d.cpp
../ios/rive-cpp/src/rive_counter.cpp
../ios/rive-cpp/src/renderer.cpp
../ios/rive-cpp/src/text/font_hb.cpp
../ios/rive-cpp/src/text/line_breaker.cpp
../ios/harfbuzz/src/hb-aat-layout.cc
../ios/harfbuzz/src/hb-aat-map.cc
../ios/harfbuzz/src/hb-blob.cc
../ios/harfbuzz/src/hb-buffer-serialize.cc
../ios/harfbuzz/src/hb-buffer-verify.cc
../ios/harfbuzz/src/hb-buffer.cc
../ios/harfbuzz/src/hb-common.cc
../ios/harfbuzz/src/hb-draw.cc
../ios/harfbuzz/src/hb-face.cc
../ios/harfbuzz/src/hb-font.cc
../ios/harfbuzz/src/hb-map.cc
../ios/harfbuzz/src/hb-number.cc
../ios/harfbuzz/src/hb-ot-cff1-table.cc
../ios/harfbuzz/src/hb-ot-cff2-table.cc
../ios/harfbuzz/src/hb-ot-color.cc
../ios/harfbuzz/src/hb-ot-face.cc
../ios/harfbuzz/src/hb-ot-font.cc
../ios/harfbuzz/src/hb-ot-layout.cc
../ios/harfbuzz/src/hb-ot-map.cc
../ios/harfbuzz/src/hb-ot-math.cc
../ios/harfbuzz/src/hb-ot-meta.cc
../ios/harfbuzz/src/hb-ot-metrics.cc
../ios/harfbuzz/src/hb-ot-name.cc
../ios/harfbuzz/src/hb-ot-shape-complex-arabic.cc
../ios/harfbuzz/src/hb-ot-shape-complex-default.cc
../ios/harfbuzz/src/hb-ot-shape-complex-hangul.cc
../ios/harfbuzz/src/hb-ot-shape-complex-hebrew.cc
../ios/harfbuzz/src/hb-ot-shape-complex-indic-table.cc
../ios/harfbuzz/src/hb-ot-shape-complex-indic.cc
../ios/harfbuzz/src/hb-ot-shape-complex-khmer.cc
../ios/harfbuzz/src/hb-ot-shape-complex-myanmar.cc
../ios/harfbuzz/src/hb-ot-shape-complex-syllabic.cc
../ios/harfbuzz/src/hb-ot-shape-complex-thai.cc
../ios/harfbuzz/src/hb-ot-shape-complex-use.cc
../ios/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc
../ios/harfbuzz/src/hb-ot-shape-fallback.cc
../ios/harfbuzz/src/hb-ot-shape-normalize.cc
../ios/harfbuzz/src/hb-ot-shape.cc
../ios/harfbuzz/src/hb-ot-tag.cc
../ios/harfbuzz/src/hb-ot-var.cc
../ios/harfbuzz/src/hb-set.cc
../ios/harfbuzz/src/hb-shape-plan.cc
../ios/harfbuzz/src/hb-shape.cc
../ios/harfbuzz/src/hb-shaper.cc
../ios/harfbuzz/src/hb-static.cc
../ios/harfbuzz/src/hb-subset-cff-common.cc
../ios/harfbuzz/src/hb-subset-cff1.cc
../ios/harfbuzz/src/hb-subset-cff2.cc
../ios/harfbuzz/src/hb-subset-input.cc
../ios/harfbuzz/src/hb-subset-plan.cc
../ios/harfbuzz/src/hb-subset-repacker.cc
../ios/harfbuzz/src/hb-subset.cc
../ios/harfbuzz/src/hb-ucd.cc
../ios/harfbuzz/src/hb-unicode.cc
../ios/SheenBidi/Source/SheenBidi.c)
target_include_directories(
rive_text PRIVATE ../ios/harfbuzz/src ../ios/rive-cpp/skia/renderer/include
../ios/rive-cpp/include ../ios/SheenBidi/Headers)

View File

@ -1,56 +0,0 @@
group 'app.rive.rive'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.6.10'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
rootProject.allprojects {
repositories {
google()
mavenCentral()
}
}
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
android {
compileSdkVersion 31
ndkVersion "25.1.8937393"
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
minSdkVersion 16
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}

View File

@ -1 +0,0 @@
rootProject.name = 'rive'

View File

@ -1,3 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app.rive.rive">
</manifest>

View File

@ -1,35 +0,0 @@
package app.rive.rive
import androidx.annotation.NonNull
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
/** RivePlugin */
class RivePlugin: FlutterPlugin, MethodCallHandler {
/// The MethodChannel that will the communication between Flutter and native Android
///
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
/// when the Flutter Engine is detached from the Activity
private lateinit var channel : MethodChannel
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "rive")
channel.setMethodCallHandler(this)
}
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
if (call.method == "getPlatformVersion") {
result.success("Android ${android.os.Build.VERSION.RELEASE}")
} else {
result.notImplemented()
}
}
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
channel.setMethodCallHandler(null)
}
}

View File

@ -1,21 +1,21 @@
PODS:
- Flutter (1.0.0)
- rive (0.0.1):
- rive_common (0.0.1):
- Flutter
DEPENDENCIES:
- Flutter (from `Flutter`)
- rive (from `.symlinks/plugins/rive/ios`)
- rive_common (from `.symlinks/plugins/rive_common/ios`)
EXTERNAL SOURCES:
Flutter:
:path: Flutter
rive:
:path: ".symlinks/plugins/rive/ios"
rive_common:
:path: ".symlinks/plugins/rive_common/ios"
SPEC CHECKSUMS:
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
rive: 75e8ef88dfbec24b5dac39121b8df26efafe5097
rive_common: 375e4e551a9b372e270b572b714484c4d55451a3
PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3

View File

@ -5,7 +5,7 @@
import FlutterMacOS
import Foundation
import rive
import rive_common
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
RivePlugin.register(with: registry.registrar(forPlugin: "RivePlugin"))

View File

@ -1,21 +1,21 @@
PODS:
- FlutterMacOS (1.0.0)
- rive (0.0.1):
- rive_common (0.0.1):
- FlutterMacOS
DEPENDENCIES:
- FlutterMacOS (from `Flutter/ephemeral`)
- rive (from `Flutter/ephemeral/.symlinks/plugins/rive/macos`)
- rive_common (from `Flutter/ephemeral/.symlinks/plugins/rive_common/macos`)
EXTERNAL SOURCES:
FlutterMacOS:
:path: Flutter/ephemeral
rive:
:path: Flutter/ephemeral/.symlinks/plugins/rive/macos
rive_common:
:path: Flutter/ephemeral/.symlinks/plugins/rive_common/macos
SPEC CHECKSUMS:
FlutterMacOS: ae6af50a8ea7d6103d888583d46bd8328a7e9811
rive: 8bf1bb49b46a4c3045424aa7c1243fe8942bb576
rive_common: 0ac58617cab300ee9bcf495e710d593578ff328b
PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c

View File

@ -6,7 +6,7 @@
#include "generated_plugin_registrant.h"
#include <rive/rive_plugin.h>
#include <rive_common/rive_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
RivePluginRegisterWithRegistrar(

View File

@ -3,7 +3,7 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
rive
rive_common
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST

38
ios/.gitignore vendored
View File

@ -1,38 +0,0 @@
.idea/
.vagrant/
.sconsign.dblite
.svn/
.DS_Store
*.swp
profile
DerivedData/
build/
GeneratedPluginRegistrant.h
GeneratedPluginRegistrant.m
.generated/
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
!default.pbxuser
!default.mode1v3
!default.mode2v3
!default.perspectivev3
xcuserdata
*.moved-aside
*.pyc
*sync/
Icon?
.tags*
/Flutter/Generated.xcconfig
/Flutter/ephemeral/
/Flutter/flutter_export_environment.sh

View File

View File

@ -1,4 +0,0 @@
#import <Flutter/Flutter.h>
@interface RivePlugin : NSObject <FlutterPlugin>
@end

View File

@ -1,15 +0,0 @@
#import "RivePlugin.h"
#if __has_include(<rive/rive-Swift.h>)
#import <rive/rive-Swift.h>
#else
// Support project import fallback if the generated compatibility header
// is not copied when this plugin is created as a library.
// https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816
#import "rive-Swift.h"
#endif
@implementation RivePlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
[SwiftRivePlugin registerWithRegistrar:registrar];
}
@end

View File

@ -1,14 +0,0 @@
import Flutter
import UIKit
public class SwiftRivePlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: "rive", binaryMessenger: registrar.messenger())
let instance = SwiftRivePlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
result("iOS " + UIDevice.current.systemVersion)
}
}

View File

@ -1,96 +0,0 @@
Pod::Spec.new do |s|
s.name = "rive"
s.version = "0.0.1"
s.summary = "Rive font abstraction."
s.description = <<-DESC
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.
DESC
s.homepage = "https://rive.app"
s.license = { :file => "../LICENSE" }
s.author = { "Rive" => "hello@rive.app" }
s.source = { :path => "." }
s.source_files = [
"Classes/**/*",
"rive_text/**/*.{cpp,hpp,c,h}",
"rive-cpp/src/math/raw_path.cpp",
"rive-cpp/src/math/mat2d.cpp",
"rive-cpp/src/rive_counter.cpp",
"rive-cpp/src/renderer.cpp",
"rive-cpp/src/text/font_hb.cpp",
"rive-cpp/src/text/line_breaker.cpp",
"harfbuzz/src/hb-aat-layout.cc",
"harfbuzz/src/hb-aat-map.cc",
"harfbuzz/src/hb-blob.cc",
"harfbuzz/src/hb-buffer-serialize.cc",
"harfbuzz/src/hb-buffer-verify.cc",
"harfbuzz/src/hb-buffer.cc",
"harfbuzz/src/hb-common.cc",
"harfbuzz/src/hb-draw.cc",
"harfbuzz/src/hb-face.cc",
"harfbuzz/src/hb-font.cc",
"harfbuzz/src/hb-map.cc",
"harfbuzz/src/hb-number.cc",
"harfbuzz/src/hb-ot-cff1-table.cc",
"harfbuzz/src/hb-ot-cff2-table.cc",
"harfbuzz/src/hb-ot-color.cc",
"harfbuzz/src/hb-ot-face.cc",
"harfbuzz/src/hb-ot-font.cc",
"harfbuzz/src/hb-ot-layout.cc",
"harfbuzz/src/hb-ot-map.cc",
"harfbuzz/src/hb-ot-math.cc",
"harfbuzz/src/hb-ot-meta.cc",
"harfbuzz/src/hb-ot-metrics.cc",
"harfbuzz/src/hb-ot-name.cc",
"harfbuzz/src/hb-ot-shape-complex-arabic.cc",
"harfbuzz/src/hb-ot-shape-complex-default.cc",
"harfbuzz/src/hb-ot-shape-complex-hangul.cc",
"harfbuzz/src/hb-ot-shape-complex-hebrew.cc",
"harfbuzz/src/hb-ot-shape-complex-indic-table.cc",
"harfbuzz/src/hb-ot-shape-complex-indic.cc",
"harfbuzz/src/hb-ot-shape-complex-khmer.cc",
"harfbuzz/src/hb-ot-shape-complex-myanmar.cc",
"harfbuzz/src/hb-ot-shape-complex-syllabic.cc",
"harfbuzz/src/hb-ot-shape-complex-thai.cc",
"harfbuzz/src/hb-ot-shape-complex-use.cc",
"harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc",
"harfbuzz/src/hb-ot-shape-fallback.cc",
"harfbuzz/src/hb-ot-shape-normalize.cc",
"harfbuzz/src/hb-ot-shape.cc",
"harfbuzz/src/hb-ot-tag.cc",
"harfbuzz/src/hb-ot-var.cc",
"harfbuzz/src/hb-set.cc",
"harfbuzz/src/hb-shape-plan.cc",
"harfbuzz/src/hb-shape.cc",
"harfbuzz/src/hb-shaper.cc",
"harfbuzz/src/hb-static.cc",
"harfbuzz/src/hb-subset-cff-common.cc",
"harfbuzz/src/hb-subset-cff1.cc",
"harfbuzz/src/hb-subset-cff2.cc",
"harfbuzz/src/hb-subset-input.cc",
"harfbuzz/src/hb-subset-plan.cc",
"harfbuzz/src/hb-subset-repacker.cc",
"harfbuzz/src/hb-subset.cc",
"harfbuzz/src/hb-ucd.cc",
"harfbuzz/src/hb-unicode.cc",
"SheenBidi/Headers/*.h",
"SheenBidi/Source/SheenBidi.c",
]
s.dependency "Flutter"
s.platform = :ios, "9.0"
# Flutter.framework does not contain a i386 slice.
s.pod_target_xcconfig = {
"DEFINES_MODULE" => "YES",
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" => "i386",
"OTHER_CFLAGS" => "-DSB_CONFIG_UNITY -DWITH_RIVE_TEXT -DHAVE_OT -DHB_NO_FALLBACK_SHAPE -DHB_NO_WIN1256 -Wno-documentation -Wno-comma -Wno-unreachable-code -Wno-shorten-64-to-32",
"OTHER_CPLUSPLUSFLAGS" => "-DWITH_RIVE_TEXT -DHAVE_OT -DHB_NO_FALLBACK_SHAPE -DHB_NO_WIN1256 -Wno-conditional-uninitialized -Wno-documentation -Wno-comma -Wno-unreachable-code -Wno-shorten-64-to-32 -std=c++17",
"USER_HEADER_SEARCH_PATHS" => '"$(PODS_TARGET_SRCROOT)/SheenBidi/Headers" "$(PODS_TARGET_SRCROOT)/harfbuzz/src" "$(PODS_TARGET_SRCROOT)/rive-cpp/include" "$(PODS_TARGET_SRCROOT)/rive-cpp/skia/renderer/include"',
"OTHER_CPLUSPLUSFLAGS[config=Release]" => "-DNDEBUG -DWITH_RIVE_TEXT -DHAVE_OT -DHB_NO_FALLBACK_SHAPE -DHB_NO_WIN1256 -Wno-conditional-uninitialized -Wno-documentation -Wno-comma -Wno-unreachable-code -Wno-shorten-64-to-32 -std=c++17",
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
"CLANG_CXX_LIBRARY" => "libc++",
}
s.swift_version = "5.0"
end

View File

@ -1,139 +0,0 @@
#include <stdint.h>
#include <stdio.h>
#include "rive/text/font_hb.hpp"
#if defined(_MSC_VER)
#define EXPORT extern "C" __declspec(dllexport)
#else
#define EXPORT extern "C" __attribute__((visibility("default"))) __attribute__((used))
#endif
EXPORT
rive::Font* makeFont(const uint8_t* bytes, uint64_t length)
{
auto result = HBFont::Decode(rive::Span<const uint8_t>(bytes, length));
if (result)
{
auto ptr = result.release();
return ptr;
}
return nullptr;
}
EXPORT void deleteFont(rive::Font* font) { delete font; }
struct GlyphPath
{
rive::RawPath* rawPath;
rive::Vec2D* points;
rive::PathVerb* verbs;
uint16_t verbCount;
};
EXPORT
GlyphPath makeGlyphPath(rive::Font* font, rive::GlyphID id)
{
rive::RawPath* path = new rive::RawPath(font->getPath(id));
return {
.rawPath = path,
.points = path->points().data(),
.verbs = path->verbs().data(),
.verbCount = (uint16_t)path->verbs().size(),
};
}
EXPORT void deleteGlyphPath(rive::RawPath* rawPath) { delete rawPath; }
EXPORT
rive::SimpleArray<rive::Paragraph>*
shapeText(const uint32_t* text, uint64_t length, rive::TextRun* runs, uint64_t runsLength)
{
if (runsLength == 0 || length == 0)
{
return nullptr;
}
return new rive::SimpleArray<rive::Paragraph>(
runs[0].font->shapeText(rive::Span(text, length), rive::Span(runs, runsLength)));
}
EXPORT void deleteShapeResult(rive::SimpleArray<rive::Paragraph>* shapeResult)
{
delete shapeResult;
}
EXPORT rive::SimpleArray<rive::SimpleArray<rive::GlyphLine>>*
breakLines(rive::SimpleArray<rive::Paragraph>* paragraphs, float width, uint8_t align)
{
bool autoWidth = width == -1.0f;
float paragraphWidth = width;
rive::SimpleArray<rive::SimpleArray<rive::GlyphLine>>* lines =
new rive::SimpleArray<rive::SimpleArray<rive::GlyphLine>>(paragraphs->size());
rive::SimpleArray<rive::SimpleArray<rive::GlyphLine>>& linesRef = *lines;
size_t paragraphIndex = 0;
for (auto& para : *paragraphs)
{
linesRef[paragraphIndex] =
rive::GlyphLine::BreakLines(para.runs, autoWidth ? -1.0f : width);
if (autoWidth)
{
paragraphWidth =
std::max(paragraphWidth,
rive::GlyphLine::ComputeMaxWidth(linesRef[paragraphIndex], para.runs));
}
paragraphIndex++;
}
paragraphIndex = 0;
for (auto& para : *paragraphs)
{
rive::GlyphLine::ComputeLineSpacing(linesRef[paragraphIndex++],
para.runs,
paragraphWidth,
(rive::TextAlign)align);
}
return lines;
}
EXPORT void deleteLines(rive::SimpleArray<rive::SimpleArray<rive::GlyphLine>>* result)
{
delete result;
}
std::vector<rive::Font*> fallbackFonts;
EXPORT
void setFallbackFonts(rive::Font** fonts, uint64_t fontsLength)
{
if (fontsLength == 0)
{
fallbackFonts = std::vector<rive::Font*>();
return;
}
fallbackFonts = std::vector<rive::Font*>(fonts, fonts + fontsLength);
}
static rive::rcp<rive::Font> pickFallbackFont(rive::Span<const rive::Unichar> missing)
{
size_t length = fallbackFonts.size();
for (size_t i = 0; i < length; i++)
{
HBFont* font = static_cast<HBFont*>(fallbackFonts[i]);
if (i == length - 1 || font->hasGlyph(missing))
{
rive::rcp<rive::Font> rcFont = rive::rcp<rive::Font>(font);
// because the font was released at load time, we need to give it an
// extra ref whenever we bump it to a reference counted pointer.
rcFont->ref();
return rcFont;
}
}
return nullptr;
}
EXPORT
void init()
{
fallbackFonts.clear();
HBFont::gFallbackProc = pickFallbackFont;
}

View File

@ -1,2 +1 @@
export 'package:rive/src/rive_core/math/mat2d.dart';
export 'package:rive/src/rive_core/math/vec2d.dart';
export 'package:rive_common/math.dart';

View File

@ -2,7 +2,6 @@
// of your plugin as a separate package, instead of inlining it in the same
// package as the core of your plugin.
// ignore: avoid_web_libraries_in_flutter
import 'dart:html' as html show window;
import 'package:flutter_web_plugins/flutter_web_plugins.dart';

View File

@ -1,5 +1,5 @@
import 'package:rive/src/core/field_types/core_field_type.dart';
import 'package:rive/src/utilities/binary_buffer/binary_reader.dart';
import 'package:rive_common/utilities.dart';
class CoreBoolType extends CoreFieldType<bool> {
@override

View File

@ -1,7 +1,7 @@
import 'dart:typed_data';
import 'package:rive/src/core/field_types/core_field_type.dart';
import 'package:rive/src/utilities/binary_buffer/binary_reader.dart';
import 'package:rive_common/utilities.dart';
class CoreBytesType extends CoreFieldType<Uint8List> {
@override

View File

@ -1,5 +1,5 @@
import 'package:rive/src/core/field_types/core_field_type.dart';
import 'package:rive/src/utilities/binary_buffer/binary_reader.dart';
import 'package:rive_common/utilities.dart';
class CoreColorType extends CoreFieldType<int> {
@override

View File

@ -1,5 +1,5 @@
import 'package:rive/src/core/field_types/core_field_type.dart';
import 'package:rive/src/utilities/binary_buffer/binary_reader.dart';
import 'package:rive_common/utilities.dart';
class CoreDoubleType extends CoreFieldType<double> {
@override

View File

@ -1,4 +1,4 @@
import 'package:rive/src/utilities/binary_buffer/binary_reader.dart';
import 'package:rive_common/utilities.dart';
// ignore: one_member_abstracts
abstract class CoreFieldType<T extends Object> {

View File

@ -1,5 +1,5 @@
import 'package:rive/src/core/field_types/core_field_type.dart';
import 'package:rive/src/utilities/binary_buffer/binary_reader.dart';
import 'package:rive_common/utilities.dart';
class CoreIntType extends CoreFieldType<int> {
@override

View File

@ -1,5 +1,5 @@
import 'package:rive/src/core/field_types/core_field_type.dart';
import 'package:rive/src/utilities/binary_buffer/binary_reader.dart';
import 'package:rive_common/utilities.dart';
class CoreStringType extends CoreFieldType<String> {
@override

View File

@ -1,5 +1,5 @@
import 'package:rive/src/core/field_types/core_field_type.dart';
import 'package:rive/src/utilities/binary_buffer/binary_reader.dart';
import 'package:rive_common/utilities.dart';
class CoreUintType extends CoreFieldType<int> {
@override

View File

@ -1,9 +1,8 @@
import 'package:flutter/widgets.dart';
import 'package:rive/src/rive_core/artboard.dart';
import 'package:rive/src/rive_core/math/aabb.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_render_box.dart';
import 'package:rive/src/runtime_artboard.dart';
import 'package:rive_common/math.dart';
class Rive extends LeafRenderObjectWidget {
/// Artboard used for drawing

View File

@ -1,8 +1,8 @@
import 'package:rive/src/core/core.dart';
import 'package:rive/src/generated/animation/listener_action_base.dart';
import 'package:rive/src/rive_core/animation/state_machine_listener.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive/src/rive_core/state_machine_controller.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/animation/listener_action_base.dart';

View File

@ -1,9 +1,8 @@
import 'package:rive/src/generated/animation/listener_align_target_base.dart';
import 'package:rive/src/rive_core/constraints/constraint.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive/src/rive_core/node.dart';
import 'package:rive/src/rive_core/state_machine_controller.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/animation/listener_align_target_base.dart';

View File

@ -1,6 +1,6 @@
import 'package:rive/src/generated/animation/listener_bool_change_base.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive/src/rive_core/state_machine_controller.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/animation/listener_bool_change_base.dart';

View File

@ -1,6 +1,6 @@
import 'package:rive/src/generated/animation/listener_number_change_base.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive/src/rive_core/state_machine_controller.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/animation/listener_number_change_base.dart';

View File

@ -1,6 +1,6 @@
import 'package:rive/src/generated/animation/listener_trigger_change_base.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive/src/rive_core/state_machine_controller.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/animation/listener_trigger_change_base.dart';

View File

@ -2,8 +2,8 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:rive/src/core/core.dart';
import 'package:rive/src/generated/animation/nested_state_machine_base.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive/src/rive_core/nested_artboard.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/animation/nested_state_machine_base.dart';

View File

@ -5,9 +5,9 @@ import 'package:rive/src/generated/animation/state_machine_listener_base.dart';
import 'package:rive/src/rive_core/animation/listener_action.dart';
import 'package:rive/src/rive_core/animation/state_machine.dart';
import 'package:rive/src/rive_core/animation/state_machine_component.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive/src/rive_core/node.dart';
import 'package:rive/src/rive_core/state_machine_controller.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/animation/state_machine_listener_base.dart';

View File

@ -12,12 +12,12 @@ import 'package:rive/src/rive_core/draw_rules.dart';
import 'package:rive/src/rive_core/draw_target.dart';
import 'package:rive/src/rive_core/drawable.dart';
import 'package:rive/src/rive_core/event.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive/src/rive_core/nested_artboard.dart';
import 'package:rive/src/rive_core/rive_animation_controller.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/utilities/dependency_sorter.dart';
import 'package:rive_common/math.dart';
import 'package:rive_common/utilities.dart';
export 'package:rive/src/generated/artboard_base.dart';

View File

@ -1,5 +1,4 @@
import 'dart:async';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/foundation.dart';

View File

@ -1,7 +1,6 @@
import 'package:rive/src/generated/bones/bone_base.dart';
import 'package:rive/src/rive_core/constraints/constraint.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/bones/bone_base.dart';

View File

@ -1,5 +1,5 @@
import 'package:rive/src/generated/bones/cubic_weight_base.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/bones/cubic_weight_base.dart';

View File

@ -6,8 +6,8 @@ import 'package:rive/src/rive_core/bones/skinnable.dart';
import 'package:rive/src/rive_core/bones/tendon.dart';
import 'package:rive/src/rive_core/component.dart';
import 'package:rive/src/rive_core/component_dirt.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_core/shapes/vertex.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/bones/skin_base.dart';

View File

@ -1,6 +1,6 @@
import 'package:rive/src/generated/bones/tendon_base.dart';
import 'package:rive/src/rive_core/bones/skeletal_component.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/bones/tendon_base.dart';

View File

@ -1,8 +1,7 @@
import 'dart:typed_data';
import 'package:rive/src/generated/bones/weight_base.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/bones/weight_base.dart';

View File

@ -2,8 +2,7 @@ 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';
import 'package:rive/src/utilities/dependency_sorter.dart';
import 'package:rive/src/utilities/tops.dart';
import 'package:rive_common/utilities.dart';
export 'package:rive/src/generated/component_base.dart';

View File

@ -1,8 +1,8 @@
import 'package:rive/src/generated/constraints/constraint_base.dart';
import 'package:rive/src/rive_core/component.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_core/transform_component.dart';
import 'package:rive/src/rive_core/world_transform_component.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/constraints/constraint_base.dart';

View File

@ -1,6 +1,6 @@
import 'package:rive/src/generated/constraints/distance_constraint_base.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive/src/rive_core/transform_component.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/constraints/distance_constraint_base.dart';

View File

@ -3,10 +3,8 @@ import 'dart:math';
import 'package:rive/src/generated/constraints/ik_constraint_base.dart';
import 'package:rive/src/rive_core/bones/bone.dart';
import 'package:rive/src/rive_core/constraints/constraint.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_core/math/transform_components.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive/src/rive_core/transform_component.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/constraints/ik_constraint_base.dart';

View File

@ -2,10 +2,9 @@ import 'dart:math';
import 'package:rive/src/generated/constraints/rotation_constraint_base.dart';
import 'package:rive/src/rive_core/constraints/constraint.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_core/math/transform_components.dart';
import 'package:rive/src/rive_core/transform_component.dart';
import 'package:rive/src/rive_core/transform_space.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/constraints/rotation_constraint_base.dart';

View File

@ -1,9 +1,8 @@
import 'package:rive/src/generated/constraints/scale_constraint_base.dart';
import 'package:rive/src/rive_core/constraints/constraint.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_core/math/transform_components.dart';
import 'package:rive/src/rive_core/transform_component.dart';
import 'package:rive/src/rive_core/transform_space.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/constraints/scale_constraint_base.dart';

View File

@ -2,9 +2,9 @@ import 'dart:math';
import 'package:rive/src/generated/constraints/transform_constraint_base.dart';
import 'package:rive/src/rive_core/constraints/constraint.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_core/transform_component.dart';
import 'package:rive/src/rive_core/transform_space.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/constraints/transform_constraint_base.dart';

View File

@ -1,6 +1,6 @@
import 'package:rive/src/generated/constraints/transform_space_constraint_base.dart';
import 'package:rive/src/rive_core/math/transform_components.dart';
import 'package:rive/src/rive_core/transform_space.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/constraints/transform_space_constraint_base.dart';

View File

@ -1,9 +1,8 @@
import 'package:rive/src/generated/constraints/translation_constraint_base.dart';
import 'package:rive/src/rive_core/constraints/constraint.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive/src/rive_core/transform_component.dart';
import 'package:rive/src/rive_core/transform_space.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/constraints/translation_constraint_base.dart';

View File

@ -1,317 +0,0 @@
import 'dart:math';
import 'dart:typed_data';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
class IAABB {
int left, top, right, bottom;
IAABB(int l, int t, int r, int b)
: left = l,
top = t,
right = r,
bottom = b;
IAABB.zero()
: left = 0,
top = 0,
right = 0,
bottom = 0;
int get width => right - left;
int get height => bottom - top;
bool get empty => left >= right || top >= bottom;
IAABB inset(int dx, int dy) =>
IAABB(left + dx, top + dy, right - dx, bottom - dy);
IAABB offset(int dx, int dy) =>
IAABB(left + dx, top + dy, right + dx, bottom + dy);
}
class AABB {
Float32List _buffer;
Float32List get values {
return _buffer;
}
Vec2D get topLeft => minimum;
Vec2D get topRight {
return Vec2D.fromValues(_buffer[2], _buffer[1]);
}
Vec2D get bottomRight => maximum;
Vec2D get bottomLeft {
return Vec2D.fromValues(_buffer[0], _buffer[3]);
}
Vec2D get minimum {
return Vec2D.fromValues(_buffer[0], _buffer[1]);
}
Vec2D get maximum {
return Vec2D.fromValues(_buffer[2], _buffer[3]);
}
double get minX => _buffer[0];
double get maxX => _buffer[2];
double get minY => _buffer[1];
double get maxY => _buffer[3];
double get left => _buffer[0];
double get top => _buffer[1];
double get right => _buffer[2];
double get bottom => _buffer[3];
double get centerX => (_buffer[0] + _buffer[2]) * 0.5;
double get centerY => (_buffer[1] + _buffer[3]) * 0.5;
AABB() : _buffer = Float32List.fromList([0.0, 0.0, 0.0, 0.0]);
AABB.clone(AABB a) : _buffer = Float32List.fromList(a.values);
AABB.fromValues(double a, double b, double c, double d)
: _buffer = Float32List.fromList([a, b, c, d]);
AABB.empty()
: _buffer = Float32List.fromList([
double.maxFinite,
double.maxFinite,
-double.maxFinite,
-double.maxFinite
]);
factory AABB.expand(AABB from, double amount) {
var aabb = AABB.clone(from);
if (aabb.width < amount) {
aabb[0] -= amount / 2;
aabb[2] += amount / 2;
}
if (aabb.height < amount) {
aabb[1] -= amount / 2;
aabb[3] += amount / 2;
}
return aabb;
}
factory AABB.pad(AABB from, double amount) {
var aabb = AABB.clone(from);
aabb[0] -= amount;
aabb[2] += amount;
aabb[1] -= amount;
aabb[3] += amount;
return aabb;
}
bool get isEmpty => !AABB.isValid(this);
Vec2D includePoint(Vec2D point, Mat2D? transform) {
var transformedPoint = transform == null ? point : transform * point;
expandToPoint(transformedPoint);
return transformedPoint;
}
AABB inset(double dx, double dy) {
return AABB.fromValues(
_buffer[0] + dx, _buffer[1] + dy, _buffer[2] - dx, _buffer[3] - dy);
}
AABB offset(double dx, double dy) {
return AABB.fromValues(
_buffer[0] + dx, _buffer[1] + dy, _buffer[2] + dx, _buffer[3] + dy);
}
void expandToPoint(Vec2D point) {
var x = point.x;
var y = point.y;
if (x < _buffer[0]) {
_buffer[0] = x;
}
if (x > _buffer[2]) {
_buffer[2] = x;
}
if (y < _buffer[1]) {
_buffer[1] = y;
}
if (y > _buffer[3]) {
_buffer[3] = y;
}
}
AABB.fromMinMax(Vec2D min, Vec2D max)
: _buffer = Float32List.fromList([min.x, min.y, max.x, max.y]);
static bool areEqual(AABB a, AABB b) {
return a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3];
}
double get width => _buffer[2] - _buffer[0];
double get height => _buffer[3] - _buffer[1];
double operator [](int idx) {
return _buffer[idx];
}
void operator []=(int idx, double v) {
_buffer[idx] = v;
}
Vec2D center() {
return Vec2D.fromValues(
(this[0] + this[2]) * 0.5, (this[1] + this[3]) * 0.5);
}
static AABB copy(AABB out, AABB a) {
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
return out;
}
static Vec2D size(Vec2D out, AABB a) {
out.x = a[2] - a[0];
out.y = a[3] - a[1];
return out;
}
static Vec2D extents(Vec2D out, AABB a) {
out.x = (a[2] - a[0]) * 0.5;
out.y = (a[3] - a[1]) * 0.5;
return out;
}
static double perimeter(AABB a) {
double wx = a[2] - a[0];
double wy = a[3] - a[1];
return 2.0 * (wx + wy);
}
static AABB combine(AABB out, AABB a, AABB b) {
out[0] = min(a[0], b[0]);
out[1] = min(a[1], b[1]);
out[2] = max(a[2], b[2]);
out[3] = max(a[3], b[3]);
return out;
}
bool containsBounds(AABB b) {
return _buffer[0] <= b[0] &&
_buffer[1] <= b[1] &&
b[2] <= _buffer[2] &&
b[3] <= _buffer[3];
}
static bool isValid(AABB a) {
double dx = a[2] - a[0];
double dy = a[3] - a[1];
return dx >= 0 &&
dy >= 0 &&
a[0] <= double.maxFinite &&
a[1] <= double.maxFinite &&
a[2] <= double.maxFinite &&
a[3] <= double.maxFinite;
}
static bool testOverlap(AABB a, AABB b) {
double d1x = b[0] - a[2];
double d1y = b[1] - a[3];
double d2x = a[0] - b[2];
double d2y = a[1] - b[3];
if (d1x > 0.0 || d1y > 0.0) {
return false;
}
if (d2x > 0.0 || d2y > 0.0) {
return false;
}
return true;
}
bool contains(Vec2D point) {
return point.x >= _buffer[0] &&
point.x <= _buffer[2] &&
point.y >= _buffer[1] &&
point.y <= _buffer[3];
}
AABB translate(Vec2D vec) => AABB.fromValues(_buffer[0] + vec.x,
_buffer[1] + vec.y, _buffer[2] + vec.x, _buffer[3] + vec.y);
IAABB round() =>
IAABB(left.round(), top.round(), right.round(), bottom.round());
@override
String toString() {
return _buffer.toString();
}
AABB transform(Mat2D matrix) {
return AABB.fromPoints([
minimum,
Vec2D.fromValues(maximum.x, minimum.y),
maximum,
Vec2D.fromValues(minimum.x, maximum.y)
], transform: matrix);
}
/// Compute an AABB from a set of points with an optional [transform] to apply
/// before computing.
factory AABB.fromPoints(
Iterable<Vec2D> points, {
Mat2D? transform,
double expand = 0,
}) {
double minX = double.maxFinite;
double minY = double.maxFinite;
double maxX = -double.maxFinite;
double maxY = -double.maxFinite;
for (final point in points) {
var p = transform == null ? point : transform * point;
final x = p.x;
final y = p.y;
if (x < minX) {
minX = x;
}
if (y < minY) {
minY = y;
}
if (x > maxX) {
maxX = x;
}
if (y > maxY) {
maxY = y;
}
}
// Make sure the box is at least this wide/high
if (expand != 0) {
double width = maxX - minX;
double diff = expand - width;
if (diff > 0) {
diff /= 2;
minX -= diff;
maxX += diff;
}
double height = maxY - minY;
diff = expand - height;
if (diff > 0) {
diff /= 2;
minY -= diff;
maxY += diff;
}
}
return AABB.fromValues(minX, minY, maxX, maxY);
}
}

View File

@ -1,4 +0,0 @@
/// Use this for perfect rounded corners.
/// https://stackoverflow.com/questions/1734745/how-to-create-circle-with-b%C3%A9zier-curves
const circleConstant = 0.552284749831;
const icircleConstant = 1 - circleConstant;

View File

@ -1,325 +0,0 @@
import 'dart:math';
import 'package:rive/src/rive_core/math/aabb.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_core/math/path_types.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive/src/rive_core/shapes/path.dart';
class HitTester implements PathInterface {
final List<int> _windings;
double _firstX, _firstY;
double _prevX, _prevY;
final double _offsetX, _offsetY;
final int _iwidth;
final double _height;
final double _tolerance;
bool _expectsMove;
HitTester(IAABB area, [double tolerance = 0.25])
: _windings =
List<int>.filled(area.width * area.height, 0, growable: false),
_firstX = 0,
_firstY = 0,
_prevX = 0,
_prevY = 0,
_offsetX = area.left.toDouble(),
_offsetY = area.top.toDouble(),
_iwidth = area.width,
_height = area.height.toDouble(),
_tolerance = tolerance,
_expectsMove = true;
void _appendLine(
double x0, double y0, double x1, double y1, double slope, int winding) {
assert(winding == 1 || winding == -1);
// we round to see which pixel centers we cross
final int top = y0.round();
final int bottom = y1.round();
if (top == bottom) {
return;
}
assert(top < bottom);
assert(top >= 0);
assert(bottom <= _height);
// we add 0.5 at the end to pre-round the values
double x = x0 + slope * (top - y0 + 0.5) + 0.5;
// start on the correct row
int index = top * _iwidth;
for (int y = top; y < bottom; ++y) {
int ix = max(x, 0.0).floor();
if (ix < _iwidth) {
_windings[index + ix] += winding;
}
x += slope;
index += _iwidth; // bump to next row
}
}
void _clipLine(double x0, double y0, double x1, double y1) {
if (y0 == y1) {
return;
}
int winding = 1;
if (y0 > y1) {
winding = -1;
// Swap our two points (is there a swap utility?)
double tmp = y0;
// ignore: parameter_assignments
y0 = y1;
// ignore: parameter_assignments
y1 = tmp;
tmp = x0;
// ignore: parameter_assignments
x0 = x1;
// ignore: parameter_assignments
x1 = tmp;
}
// now we're monotonic in Y: y0 <= y1
if (y1 <= 0 || y0 >= _height) {
return;
}
final double m = (x1 - x0) / (y1 - y0);
if (y0 < 0) {
// ignore: parameter_assignments
x0 += m * (0 - y0);
// ignore: parameter_assignments
y0 = 0;
}
if (y1 > _height) {
// ignore: parameter_assignments
x1 += m * (_height - y1);
// ignore: parameter_assignments
y1 = _height;
}
assert(y0 <= y1);
assert(y0 >= 0);
assert(y1 <= _height);
_appendLine(x0, y0, x1, y1, m, winding);
}
@override
void moveTo(double x, double y) {
if (!_expectsMove) {
close();
}
_firstX = _prevX = x - _offsetX;
_firstY = _prevY = y - _offsetY;
_expectsMove = false;
}
@override
void lineTo(double x, double y) {
assert(!_expectsMove);
// ignore: parameter_assignments
x -= _offsetX;
// ignore: parameter_assignments
y -= _offsetY;
_clipLine(_prevX, _prevY, x, y);
_prevX = x;
_prevY = y;
}
bool _quickRejectY(double y0, double y1, double y2, double y3) {
final double h = _height;
return y0 <= 0 && y1 <= 0 && y2 <= 0 && y3 <= 0 ||
y0 >= h && y1 >= h && y2 >= h && y3 >= h;
}
/*
* Computes (conservatively) the number of line-segments needed
* to approximate this cubic and stay within the specified tolerance.
*/
static int _countCubicSegments(double ax, double ay, double bx, double by,
double cx, double cy, double dx, double dy, double tolerance) {
final abcX = ax - bx - bx + cx;
final abcY = ay - by - by + cy;
final bcdX = bx - cx - cx + dx;
final bcdY = by - cy - cy + dy;
final errX = max(abcX.abs(), bcdX.abs());
final errY = max(abcY.abs(), bcdY.abs());
final dist = sqrt(errX * errX + errY * errY);
const maxCurveSegments = 1 << 8; // just a big but finite value
final count = sqrt((3 * dist) / (4 * tolerance));
return max(1, min(count.ceil(), maxCurveSegments));
}
@override
void cubicTo(
double x1, double y1, double x2, double y2, double x3, double y3) {
assert(!_expectsMove);
// ignore: parameter_assignments
x1 -= _offsetX;
// ignore: parameter_assignments
x2 -= _offsetX;
// ignore: parameter_assignments
x3 -= _offsetX;
// ignore: parameter_assignments
y1 -= _offsetY;
// ignore: parameter_assignments
y2 -= _offsetY;
// ignore: parameter_assignments
y3 -= _offsetY;
if (_quickRejectY(_prevY, y1, y2, y3)) {
_prevX = x3;
_prevY = y3;
return;
}
final count =
_countCubicSegments(_prevX, _prevY, x1, y1, x2, y2, x3, y3, _tolerance);
final dt = 1.0 / count;
double t = dt;
// Compute simple coefficients for the cubic polynomial
// ... much faster to evaluate multiple times
// ... At^3 + Bt^2 + Ct + D
//
final aX = (x3 - _prevX) + 3 * (x1 - x2);
final bX = 3 * ((x2 - x1) + (_prevX - x1));
final cX = 3 * (x1 - _prevX);
final dX = _prevX;
final aY = (y3 - _prevY) + 3 * (y1 - y2);
final bY = 3 * ((y2 - y1) + (_prevY - y1));
final cY = 3 * (y1 - _prevY);
final dY = _prevY;
// we don't need the first point eval(0) or the last eval(1)
double px = _prevX;
double py = _prevY;
for (int i = 1; i < count - 1; ++i) {
// Horner's method for evaluating the simple polynomial
final nx = ((aX * t + bX) * t + cX) * t + dX;
final ny = ((aY * t + bY) * t + cY) * t + dY;
_clipLine(px, py, nx, ny);
px = nx;
py = ny;
t += dt;
}
_clipLine(px, py, x3, y3);
_prevX = x3;
_prevY = y3;
}
@override
void close() {
assert(!_expectsMove);
_clipLine(_prevX, _prevY, _firstX, _firstY);
_expectsMove = true;
}
void move(Vec2D v) {
moveTo(v.x, v.y);
}
void line(Vec2D v) {
lineTo(v.x, v.y);
}
void cubic(Vec2D b, Vec2D c, Vec2D d) {
cubicTo(b.x, b.y, c.x, c.y, d.x, d.y);
}
void addRect(AABB r, Mat2D xform, PathDirection dir) {
final p0 = xform * Vec2D.fromValues(r.left, r.top);
final p1 = xform * Vec2D.fromValues(r.right, r.top);
final p2 = xform * Vec2D.fromValues(r.right, r.bottom);
final p3 = xform * Vec2D.fromValues(r.left, r.bottom);
move(p0);
if (dir == PathDirection.clockwise) {
line(p1);
line(p2);
line(p3);
} else {
assert(dir == PathDirection.counterclockwise);
line(p3);
line(p2);
line(p1);
}
close();
}
bool test([PathFillRule rule = PathFillRule.nonZero]) {
if (!_expectsMove) {
close();
}
final int mask = (rule == PathFillRule.nonZero) ? -1 : 1;
int nonzero = 0;
for (final w in _windings) {
nonzero |= w & mask;
}
return nonzero != 0;
}
}
/// A HitTester with a settable transform. We can roll this into HitTester if we
/// like it.
class TransformingHitTester extends HitTester {
TransformingHitTester(
IAABB area, [
double tolerance = 0.25,
]) : super(area, tolerance = tolerance);
Mat2D _transform = Mat2D();
bool _needsTransform = false;
Mat2D get transform => _transform;
set transform(Mat2D value) {
_transform = value;
_needsTransform = !value.isIdentity;
}
@override
void moveTo(double x, double y) {
if (!_needsTransform) {
super.moveTo(x, y);
return;
}
var v = _transform * Vec2D.fromValues(x, y);
super.moveTo(v.x, v.y);
}
@override
void lineTo(double x, double y) {
if (!_needsTransform) {
super.lineTo(x, y);
return;
}
var v = _transform * Vec2D.fromValues(x, y);
super.lineTo(v.x, v.y);
}
@override
void cubicTo(double ox, double oy, double ix, double iy, double x, double y) {
if (!_needsTransform) {
super.cubicTo(ox, oy, ix, iy, x, y);
return;
}
var o = _transform * Vec2D.fromValues(ox, oy);
var i = _transform * Vec2D.fromValues(ix, iy);
var p = _transform * Vec2D.fromValues(x, y);
super.cubicTo(o.x, o.y, i.x, i.y, p.x, p.y);
}
}

View File

@ -1,279 +0,0 @@
import 'dart:math';
import 'dart:typed_data';
import 'package:rive/src/rive_core/math/transform_components.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
/// Can't make this constant so we override and disable changing values so we'll
/// throw if something tries to change the identity.
class _Identity extends Mat2D {
@override
void operator []=(int index, double value) => throw UnsupportedError(
'Cannot change components of the identity matrix.');
}
class Mat2D {
static final Mat2D identity = _Identity();
final Float32List _buffer;
Float32List get values {
return _buffer;
}
Float64List get mat4 {
return Float64List.fromList([
_buffer[0],
_buffer[1],
0.0,
0.0,
_buffer[2],
_buffer[3],
0.0,
0.0,
0.0,
0.0,
1.0,
0.0,
_buffer[4],
_buffer[5],
0.0,
1.0
]);
}
double operator [](int index) {
return _buffer[index];
}
void operator []=(int index, double value) {
_buffer[index] = value;
}
Mat2D() : _buffer = Float32List.fromList([1.0, 0.0, 0.0, 1.0, 0.0, 0.0]);
Mat2D.fromTranslation(Vec2D translation)
: _buffer = Float32List.fromList(
[1.0, 0.0, 0.0, 1.0, translation.x, translation.y]);
Mat2D.fromTranslate(double x, double y)
: _buffer = Float32List.fromList([1.0, 0.0, 0.0, 1.0, x, y]);
Mat2D.fromScaling(Vec2D scaling)
: _buffer = Float32List.fromList([scaling.x, 0, 0, scaling.y, 0, 0]);
Mat2D.fromScale(double x, double y)
: _buffer = Float32List.fromList([x, 0, 0, y, 0, 0]);
Mat2D.fromMat4(Float64List mat4)
: _buffer = Float32List.fromList(
[mat4[0], mat4[1], mat4[4], mat4[5], mat4[12], mat4[13]]);
Mat2D.clone(Mat2D copy) : _buffer = Float32List.fromList(copy.values);
Vec2D mapXY(double x, double y) {
return Vec2D.fromValues(x * _buffer[0] + y * _buffer[2] + _buffer[4],
x * _buffer[1] + y * _buffer[3] + _buffer[5]);
}
Vec2D operator *(Vec2D v) => mapXY(v.x, v.y);
static Mat2D fromRotation(Mat2D o, double rad) {
double s = sin(rad);
double c = cos(rad);
o[0] = c;
o[1] = s;
o[2] = -s;
o[3] = c;
o[4] = 0.0;
o[5] = 0.0;
return o;
}
static void copy(Mat2D o, Mat2D f) {
o[0] = f[0];
o[1] = f[1];
o[2] = f[2];
o[3] = f[3];
o[4] = f[4];
o[5] = f[5];
}
static void copyFromList(Mat2D o, Float32List f) {
o[0] = f[0];
o[1] = f[1];
o[2] = f[2];
o[3] = f[3];
o[4] = f[4];
o[5] = f[5];
}
static void scale(Mat2D o, Mat2D a, Vec2D v) {
double a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5];
o[0] = a0 * v.x;
o[1] = a1 * v.x;
o[2] = a2 * v.y;
o[3] = a3 * v.y;
o[4] = a4;
o[5] = a5;
}
static void scaleByValues(Mat2D o, double x, double y) {
o[0] *= x;
o[1] *= x;
o[2] *= y;
o[3] *= y;
}
// ignore: prefer_constructors_over_static_methods
static Mat2D multiplySkipIdentity(Mat2D a, Mat2D b) {
if (a == Mat2D.identity) {
return b;
} else if (b == Mat2D.identity) {
return a;
} else {
return multiply(Mat2D(), a, b);
}
}
static Mat2D multiply(Mat2D o, Mat2D a, Mat2D b) {
double a0 = a[0],
a1 = a[1],
a2 = a[2],
a3 = a[3],
a4 = a[4],
a5 = a[5],
b0 = b[0],
b1 = b[1],
b2 = b[2],
b3 = b[3],
b4 = b[4],
b5 = b[5];
o[0] = a0 * b0 + a2 * b1;
o[1] = a1 * b0 + a3 * b1;
o[2] = a0 * b2 + a2 * b3;
o[3] = a1 * b2 + a3 * b3;
o[4] = a0 * b4 + a2 * b5 + a4;
o[5] = a1 * b4 + a3 * b5 + a5;
return o;
}
static void cCopy(Mat2D o, Mat2D a) {
o[0] = a[0];
o[1] = a[1];
o[2] = a[2];
o[3] = a[3];
o[4] = a[4];
o[5] = a[5];
}
static Mat2D translate(Mat2D o, Mat2D a, Vec2D b) {
o[0] = a[0];
o[1] = a[1];
o[2] = a[2];
o[3] = a[3];
o[4] = a[4] + b.x;
o[5] = a[5] + b.y;
return o;
}
static bool invert(Mat2D o, Mat2D a) {
double aa = a[0], ab = a[1], ac = a[2], ad = a[3], atx = a[4], aty = a[5];
double det = aa * ad - ab * ac;
if (det == 0.0) {
return false;
}
det = 1.0 / det;
o[0] = ad * det;
o[1] = -ab * det;
o[2] = -ac * det;
o[3] = aa * det;
o[4] = (ac * aty - ad * atx) * det;
o[5] = (ab * atx - aa * aty) * det;
return true;
}
static void getScale(Mat2D m, Vec2D s) {
double x = m[0];
double y = m[1];
s.x = x.sign * sqrt(x * x + y * y);
x = m[2];
y = m[3];
s.y = y.sign * sqrt(x * x + y * y);
}
static Vec2D getTranslation(Mat2D m, Vec2D t) {
t.x = m[4];
t.y = m[5];
return t;
}
static void setIdentity(Mat2D mat) {
mat[0] = 1.0;
mat[1] = 0.0;
mat[2] = 0.0;
mat[3] = 1.0;
mat[4] = 0.0;
mat[5] = 0.0;
}
bool get isIdentity =>
_buffer[0] == 1.0 &&
_buffer[1] == 0.0 &&
_buffer[2] == 0.0 &&
_buffer[3] == 1.0 &&
_buffer[4] == 0.0 &&
_buffer[5] == 0.0;
static void decompose(Mat2D m, TransformComponents result) {
double m0 = m[0], m1 = m[1], m2 = m[2], m3 = m[3];
double rotation = atan2(m1, m0);
double denom = m0 * m0 + m1 * m1;
double scaleX = sqrt(denom);
double scaleY = (scaleX == 0) ? 0 : ((m0 * m3 - m2 * m1) / scaleX);
double skewX = atan2(m0 * m2 + m1 * m3, denom);
result[0] = m[4];
result[1] = m[5];
result[2] = scaleX;
result[3] = scaleY;
result[4] = rotation;
result[5] = skewX;
}
static void compose(Mat2D m, TransformComponents result) {
double r = result[4];
if (r != 0.0) {
Mat2D.fromRotation(m, r);
} else {
Mat2D.setIdentity(m);
}
m[4] = result[0];
m[5] = result[1];
Mat2D.scale(m, m, result.scale);
double sk = result[5];
if (sk != 0.0) {
m[2] = m[0] * sk + m[2];
m[3] = m[1] * sk + m[3];
}
}
static bool areEqual(Mat2D a, Mat2D b) {
return a[0] == b[0] &&
a[1] == b[1] &&
a[2] == b[2] &&
a[3] == b[3] &&
a[4] == b[4] &&
a[5] == b[5];
}
@override
String toString() {
return _buffer.toString();
}
}

View File

@ -1,22 +0,0 @@
/*
* Copyright 2022 Rive
*/
enum PathFillRule {
nonZero,
evenOdd,
}
enum PathDirection {
clockwise,
counterclockwise,
}
enum PathVerb {
move,
line,
quad,
conicUnused, // so we match skia's order
cubic,
close,
}

View File

@ -1,74 +0,0 @@
import 'package:rive/src/rive_core/math/vec2d.dart';
/// Result of projecting a point onto a segment.
class ProjectionResult {
/// The distance factor from 0-1 along the segment starting at the
/// [Segment2D.start].
final double t;
/// The actual 2d point in the same space as [Segment2D.start] and
/// [Segment2D.end].
final Vec2D point;
ProjectionResult(this.t, this.point);
}
/// A line segment with a discrete [start] and [end].
class Segment2D {
/// The starting point of this line segment.
final Vec2D start;
/// The ending point of this line segment.
final Vec2D end;
/// Difference from start to end. Nullable so we can compute it only when we
/// need it.
Vec2D? _diff;
Vec2D get diff {
_computeDiff();
return _diff!;
}
void _computeDiff() {
// We cache these internally so we can call projectPoint multiple times in
// succession performantly.
if (_diff == null) {
_diff = start - end;
lengthSquared = _diff!.squaredLength();
}
}
/// The squared length of this segment.
double lengthSquared = 0;
Segment2D(this.start, this.end);
/// Find where the given [point] lies on this segment.
ProjectionResult projectPoint(Vec2D point, {bool clamp = true}) {
_computeDiff();
if (lengthSquared == 0) {
return ProjectionResult(0, start);
}
double t = ((point.x - start.x) * (end.x - start.x) +
(point.y - start.y) * (end.y - start.y)) /
lengthSquared;
if (clamp) {
// Clamp at edges.
if (t < 0.0) {
return ProjectionResult(0, start);
}
if (t > 1.0) {
return ProjectionResult(1, end);
}
}
return ProjectionResult(
t,
Vec2D.fromValues(
start.x + t * (end.x - start.x),
start.y + t * (end.y - start.y),
),
);
}
}

View File

@ -1,97 +0,0 @@
import 'dart:math';
import 'dart:typed_data';
import 'package:rive/src/rive_core/math/vec2d.dart';
class TransformComponents {
final Float32List _buffer;
Float32List get values {
return _buffer;
}
double operator [](int index) {
return _buffer[index];
}
void operator []=(int index, double value) {
_buffer[index] = value;
}
TransformComponents()
: _buffer = Float32List.fromList([1.0, 0.0, 0.0, 1.0, 0.0, 0.0]);
TransformComponents.clone(TransformComponents copy)
: _buffer = Float32List.fromList(copy.values);
double get x {
return _buffer[0];
}
set x(double value) {
_buffer[0] = value;
}
double get y {
return _buffer[1];
}
set y(double value) {
_buffer[1] = value;
}
double get scaleX {
return _buffer[2];
}
set scaleX(double value) {
_buffer[2] = value;
}
double get scaleY {
return _buffer[3];
}
set scaleY(double value) {
_buffer[3] = value;
}
double get rotation {
return _buffer[4];
}
set rotation(double value) {
_buffer[4] = value;
}
double get skew {
return _buffer[5];
}
set skew(double value) {
_buffer[5] = value;
}
Vec2D get translation {
return Vec2D.fromValues(_buffer[0], _buffer[1]);
}
Vec2D get scale {
return Vec2D.fromValues(_buffer[2], _buffer[3]);
}
static void copy(TransformComponents source, TransformComponents other) {
source._buffer[0] = other._buffer[0];
source._buffer[1] = other._buffer[1];
source._buffer[2] = other._buffer[2];
source._buffer[3] = other._buffer[3];
source._buffer[4] = other._buffer[4];
source._buffer[5] = other._buffer[5];
}
@override
String toString() {
return 'TransformComponents(x: $x y: $y sx: $scaleX '
'sy: $scaleY r: ${rotation / pi * 180} s: $skew)';
}
}

View File

@ -1,191 +0,0 @@
import 'dart:math' as math;
import 'dart:typed_data';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/utilities/utilities.dart';
class Vec2D {
double x, y;
Vec2D()
: x = 0,
y = 0;
Vec2D.clone(Vec2D copy)
: x = copy.x,
y = copy.y;
Vec2D.fromValues(double ox, double oy)
: x = ox,
y = oy;
double at(int index) {
if (index == 0) {
return x;
}
if (index == 1) {
return y;
}
throw RangeError('index out of range');
}
void setAt(int index, double value) {
if (index == 0) {
x = value;
} else if (index == 1) {
y = value;
} else {
throw RangeError('index out of range');
}
}
double length() => math.sqrt(x * x + y * y);
double squaredLength() => x * x + y * y;
double atan2() => math.atan2(y, x);
Vec2D operator +(Vec2D v) {
return Vec2D.fromValues(x + v.x, y + v.y);
}
Vec2D operator -(Vec2D v) {
return Vec2D.fromValues(x - v.x, y - v.y);
}
// ignore: avoid_returning_this
Vec2D apply(Mat2D m) {
final newX = x * m[0] + y * m[2] + m[4];
final newY = x * m[1] + y * m[3] + m[5];
x = newX;
y = newY;
return this;
}
static void copy(Vec2D o, Vec2D a) {
o.x = a.x;
o.y = a.y;
}
static void copyFromList(Vec2D o, Float32List a) {
o.x = a[0];
o.y = a[1];
}
static Vec2D transformMat2D(Vec2D o, Vec2D a, Mat2D m) {
final x = a.x;
final y = a.y;
o.x = m[0] * x + m[2] * y + m[4];
o.y = m[1] * x + m[3] * y + m[5];
return o;
}
static Vec2D transformMat2(Vec2D o, Vec2D a, Mat2D m) {
final x = a.x;
final y = a.y;
o.x = m[0] * x + m[2] * y;
o.y = m[1] * x + m[3] * y;
return o;
}
static Vec2D scale(Vec2D o, Vec2D a, double scale) {
o.x = a.x * scale;
o.y = a.y * scale;
return o;
}
static Vec2D lerp(Vec2D o, Vec2D a, Vec2D b, double f) {
double ax = a.x;
double ay = a.y;
o.x = ax + f * (b.x - ax);
o.y = ay + f * (b.y - ay);
return o;
}
static double distance(Vec2D a, Vec2D b) {
double x = b.x - a.x;
double y = b.y - a.y;
return math.sqrt(x * x + y * y);
}
static double squaredDistance(Vec2D a, Vec2D b) {
double x = b.x - a.x;
double y = b.y - a.y;
return x * x + y * y;
}
static Vec2D negate(Vec2D result, Vec2D a) {
result.x = -1 * a.x;
result.y = -1 * a.y;
return result;
}
static void normalize(Vec2D result, Vec2D a) {
double x = a.x;
double y = a.y;
double len = x * x + y * y;
if (len > 0.0) {
len = 1.0 / math.sqrt(len);
result.x = a.x * len;
result.y = a.y * len;
}
}
static double dot(Vec2D a, Vec2D b) {
return a.x * b.x + a.y * b.y;
}
static Vec2D scaleAndAdd(Vec2D result, Vec2D a, Vec2D b, double scale) {
result.x = a.x + b.x * scale;
result.y = a.y + b.y * scale;
return result;
}
static double onSegment(Vec2D segmentPoint1, Vec2D segmentPoint2, Vec2D pt) {
double l2 = squaredDistance(segmentPoint1, segmentPoint2);
if (l2 == 0) {
return 0;
}
return ((pt.x - segmentPoint1.x) * (segmentPoint2.x - segmentPoint1.x) +
(pt.y - segmentPoint1.y) * (segmentPoint2.y - segmentPoint1.y)) /
l2;
}
static double segmentSquaredDistance(
Vec2D segmentPoint1, Vec2D segmentPoint2, Vec2D pt) {
double t = onSegment(segmentPoint1, segmentPoint2, pt);
if (t <= 0) {
return Vec2D.squaredDistance(segmentPoint1, pt);
}
if (t >= 1) {
return Vec2D.squaredDistance(segmentPoint2, pt);
}
Vec2D ptOnSeg = Vec2D.fromValues(
segmentPoint1.x + t * (segmentPoint2.x - segmentPoint1.x),
segmentPoint1.y + t * (segmentPoint2.y - segmentPoint1.y),
);
return Vec2D.squaredDistance(ptOnSeg, pt);
}
static bool approximatelyEqual(Vec2D a, Vec2D b, {double threshold = 0.001}) {
var a0 = a.x, a1 = a.y;
var b0 = b.x, b1 = b.y;
return (a0 - b0).abs() <=
threshold * math.max(1.0, math.max(a0.abs(), b0.abs())) &&
(a1 - b1).abs() <=
threshold * math.max(1.0, math.max(a1.abs(), b1.abs()));
}
@override
String toString() {
return '$x, $y';
}
@override
bool operator ==(Object o) => o is Vec2D && x == o.x && y == o.y;
@override
int get hashCode => szudzik(x.hashCode, y.hashCode);
}

View File

@ -8,10 +8,8 @@ import 'package:rive/src/rive_core/animation/nested_state_machine.dart';
import 'package:rive/src/rive_core/backboard.dart';
import 'package:rive/src/rive_core/component.dart';
import 'package:rive/src/rive_core/component_dirt.dart';
import 'package:rive/src/rive_core/math/aabb.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive/src/rive_core/nested_animation.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/nested_artboard_base.dart';
@ -63,7 +61,6 @@ class NestedArtboard extends NestedArtboardBase {
@override
void artboardIdChanged(int from, int to) {}
@override
void childAdded(Component child) {
super.childAdded(child);

View File

@ -1,5 +1,5 @@
import 'package:rive/src/generated/node_base.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/node_base.dart';

View File

@ -2,7 +2,7 @@ import 'dart:collection';
import 'package:rive/src/rive_core/runtime/exceptions/rive_format_error_exception.dart';
import 'package:rive/src/rive_core/runtime/exceptions/rive_unsupported_version_exception.dart';
import 'package:rive/src/utilities/binary_buffer/binary_reader.dart';
import 'package:rive_common/utilities.dart';
/// Stores the minor and major version of Rive. Versions with the same major
/// value are backwards and forwards compatible.

View File

@ -3,7 +3,7 @@ import 'dart:math';
import 'package:rive/src/core/core.dart';
import 'package:rive/src/generated/shapes/cubic_asymmetric_vertex_base.dart';
import 'package:rive/src/rive_core/component_dirt.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/shapes/cubic_asymmetric_vertex_base.dart';

View File

@ -3,7 +3,7 @@ import 'dart:math';
import 'package:rive/src/core/core.dart';
import 'package:rive/src/generated/shapes/cubic_detached_vertex_base.dart';
import 'package:rive/src/rive_core/component_dirt.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/shapes/cubic_detached_vertex_base.dart';

View File

@ -3,7 +3,7 @@ import 'dart:math';
import 'package:rive/src/core/core.dart';
import 'package:rive/src/generated/shapes/cubic_mirrored_vertex_base.dart';
import 'package:rive/src/rive_core/component_dirt.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/shapes/cubic_mirrored_vertex_base.dart';

View File

@ -2,8 +2,7 @@ import 'dart:typed_data';
import 'package:rive/src/generated/shapes/cubic_vertex_base.dart';
import 'package:rive/src/rive_core/bones/weight.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/shapes/cubic_vertex_base.dart';

View File

@ -1,7 +1,7 @@
import 'package:rive/src/generated/shapes/ellipse_base.dart';
import 'package:rive/src/rive_core/math/circle_constant.dart';
import 'package:rive/src/rive_core/shapes/cubic_detached_vertex.dart';
import 'package:rive/src/rive_core/shapes/path_vertex.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/shapes/ellipse_base.dart';

View File

@ -6,10 +6,9 @@ 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/math/aabb.dart';
import 'package:rive/src/rive_core/math/mat2d.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';
export 'package:rive/src/generated/shapes/image_base.dart';
@ -86,7 +85,6 @@ class Image extends ImageBase
}
}
@override
int get assetIdPropertyKey => ImageBase.assetIdPropertyKey;

View File

@ -6,13 +6,12 @@ import 'package:rive/src/rive_core/bones/skinnable.dart';
import 'package:rive/src/rive_core/component.dart';
import 'package:rive/src/rive_core/component_dirt.dart';
import 'package:rive/src/rive_core/drawable.dart';
import 'package:rive/src/rive_core/math/aabb.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_core/shapes/contour_mesh_vertex.dart';
import 'package:rive/src/rive_core/shapes/image.dart';
import 'package:rive/src/rive_core/shapes/mesh_vertex.dart';
import 'package:rive/src/rive_core/transform_component.dart';
import 'package:rive/src/utilities/binary_buffer/binary_reader.dart';
import 'package:rive_common/math.dart';
import 'package:rive_common/utilities.dart';
export 'package:rive/src/generated/shapes/mesh_base.dart';

View File

@ -4,10 +4,10 @@ import 'package:meta/meta.dart';
import 'package:rive/src/generated/shapes/paint/linear_gradient_base.dart';
import 'package:rive/src/rive_core/component.dart';
import 'package:rive/src/rive_core/component_dirt.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive/src/rive_core/shapes/paint/gradient_stop.dart';
import 'package:rive/src/rive_core/shapes/paint/shape_paint_mutator.dart';
import 'package:rive/src/rive_core/shapes/shape.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/shapes/paint/linear_gradient_base.dart';

View File

@ -1,5 +1,5 @@
import 'package:rive/src/generated/shapes/parametric_path_base.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/shapes/parametric_path_base.dart';

View File

@ -5,13 +5,11 @@ import 'package:rive/src/generated/shapes/path_base.dart';
import 'package:rive/src/rive_core/component.dart';
import 'package:rive/src/rive_core/component_dirt.dart';
import 'package:rive/src/rive_core/component_flags.dart';
import 'package:rive/src/rive_core/math/aabb.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive/src/rive_core/shapes/cubic_vertex.dart';
import 'package:rive/src/rive_core/shapes/path_vertex.dart';
import 'package:rive/src/rive_core/shapes/shape.dart';
import 'package:rive/src/rive_core/shapes/straight_vertex.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/shapes/path_base.dart';
@ -306,13 +304,6 @@ abstract class Path extends PathBase {
enum _PathCommand { moveTo, lineTo, cubicTo, close }
abstract class PathInterface {
void moveTo(double x, double y);
void lineTo(double x, double y);
void cubicTo(double ox, double oy, double ix, double iy, double x, double y);
void close();
}
class RenderPath implements PathInterface {
final ui.Path _uiPath = ui.Path();
ui.Path get uiPath => _uiPath;

View File

@ -3,8 +3,8 @@ import 'dart:ui' as ui;
import 'package:rive/src/rive_core/artboard.dart';
import 'package:rive/src/rive_core/component.dart';
import 'package:rive/src/rive_core/component_dirt.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_core/shapes/shape.dart';
import 'package:rive_common/math.dart';
/// The PathComposer builds the desired world and local paths for the shapes and
/// their fills/strokes. It guarantees that one of local or world path is always

View File

@ -2,8 +2,8 @@ import 'package:rive/src/generated/shapes/points_path_base.dart';
import 'package:rive/src/rive_core/bones/skinnable.dart';
import 'package:rive/src/rive_core/component.dart';
import 'package:rive/src/rive_core/component_dirt.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_core/shapes/path_vertex.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/shapes/points_path_base.dart';

View File

@ -3,15 +3,13 @@ import 'dart:ui' as ui;
import 'package:collection/collection.dart';
import 'package:rive/src/generated/shapes/shape_base.dart';
import 'package:rive/src/rive_core/component_dirt.dart';
import 'package:rive/src/rive_core/math/aabb.dart';
import 'package:rive/src/rive_core/math/hit_test.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_core/shapes/paint/linear_gradient.dart' as core;
import 'package:rive/src/rive_core/shapes/paint/shape_paint_mutator.dart';
import 'package:rive/src/rive_core/shapes/paint/stroke.dart';
import 'package:rive/src/rive_core/shapes/path.dart';
import 'package:rive/src/rive_core/shapes/path_composer.dart';
import 'package:rive/src/rive_core/shapes/shape_paint_container.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/shapes/shape_base.dart';

View File

@ -1,11 +1,9 @@
import 'package:meta/meta.dart';
import 'package:rive/src/rive_core/component.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_core/math/vec2d.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';
import 'package:rive_common/math.dart';
/// An abstraction to give a common interface to any component that can contain
/// fills and strokes.

View File

@ -2,8 +2,7 @@ import 'package:rive/src/core/core.dart';
import 'package:rive/src/generated/shapes/straight_vertex_base.dart';
import 'package:rive/src/rive_core/bones/weight.dart';
import 'package:rive/src/rive_core/component.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/shapes/straight_vertex_base.dart';
class StraightVertex extends StraightVertexBase {

View File

@ -2,8 +2,7 @@ import 'package:rive/src/core/core.dart';
import 'package:rive/src/generated/shapes/vertex_base.dart';
import 'package:rive/src/rive_core/bones/weight.dart';
import 'package:rive/src/rive_core/component.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/shapes/vertex_base.dart';

View File

@ -18,13 +18,11 @@ import 'package:rive/src/rive_core/animation/state_machine_listener.dart';
import 'package:rive/src/rive_core/animation/state_machine_trigger.dart';
import 'package:rive/src/rive_core/animation/state_transition.dart';
import 'package:rive/src/rive_core/artboard.dart';
import 'package:rive/src/rive_core/math/aabb.dart';
import 'package:rive/src/rive_core/math/hit_test.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive/src/rive_core/nested_artboard.dart';
import 'package:rive/src/rive_core/node.dart';
import 'package:rive/src/rive_core/rive_animation_controller.dart';
import 'package:rive/src/rive_core/shapes/shape.dart';
import 'package:rive_common/math.dart';
/// Callback signature for satate machine state changes
typedef OnStateChange = void Function(String, String);

View File

@ -11,10 +11,9 @@ import 'package:rive/src/rive_core/constraints/translation_constraint.dart';
import 'package:rive/src/rive_core/container_component.dart';
import 'package:rive/src/rive_core/draw_rules.dart';
import 'package:rive/src/rive_core/drawable.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive/src/rive_core/shapes/clipping_shape.dart';
import 'package:rive/src/rive_core/world_transform_component.dart';
import 'package:rive_common/math.dart';
import 'constraints/distance_constraint.dart';

View File

@ -1,6 +1,6 @@
import 'package:rive/src/generated/world_transform_component_base.dart';
import 'package:rive/src/rive_core/component_dirt.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive_common/math.dart';
export 'package:rive/src/generated/world_transform_component_base.dart';

View File

@ -32,7 +32,7 @@ import 'package:rive/src/rive_core/component.dart';
import 'package:rive/src/rive_core/runtime/exceptions/rive_format_error_exception.dart';
import 'package:rive/src/rive_core/runtime/runtime_header.dart';
import 'package:rive/src/runtime_nested_artboard.dart';
import 'package:rive/src/utilities/binary_buffer/binary_reader.dart';
import 'package:rive_common/utilities.dart';
Core<CoreContext>? _readRuntimeObject(
BinaryReader reader, HashMap<int, CoreFieldType> propertyToField) {

View File

@ -3,9 +3,7 @@ import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/scheduler.dart';
import 'package:rive/src/rive_core/math/aabb.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive_common/math.dart';
/// This allows a value of type T or T?
/// to be treated as a value of type T?.

View File

@ -1,7 +1,6 @@
import 'package:flutter/widgets.dart';
import 'package:rive/src/rive_core/math/aabb.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_render_box.dart';
import 'package:rive_common/math.dart';
/// An abstraction for controlling the composition and rendering of a Rive
/// scene.

View File

@ -1,319 +0,0 @@
import 'dart:collection';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:rive/math.dart';
import 'rive_text_ffi.dart' if (dart.library.html) 'rive_text_wasm.dart';
enum RawPathVerb { move, line, quad, cubic, close }
abstract class RawPathCommand {
final RawPathVerb verb;
RawPathCommand(this.verb);
Vec2D point(int index);
}
abstract class RawPath with IterableMixin<RawPathCommand> {
void dispose();
void issueCommands(ui.Path path) {
for (final command in this) {
switch (command.verb) {
case RawPathVerb.move:
var p = command.point(0);
path.moveTo(p.x, p.y);
break;
case RawPathVerb.line:
var p = command.point(1);
path.lineTo(p.x, p.y);
break;
case RawPathVerb.quad:
var p1 = command.point(1);
var p2 = command.point(2);
path.quadraticBezierTo(p1.x, p1.y, p2.x, p2.y);
break;
case RawPathVerb.cubic:
var p1 = command.point(1);
var p2 = command.point(2);
var p3 = command.point(3);
path.cubicTo(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y);
break;
case RawPathVerb.close:
path.close();
break;
}
}
}
}
enum TextDirection { ltr, rtl }
enum TextAlign { left, right, center }
abstract class Paragraph {
TextDirection get direction;
List<GlyphRun> get runs;
List<GlyphRun> get logicalRuns => runs;
List<GlyphRun> orderVisually(List<GlyphRun> glyphRuns) {
if (direction == TextDirection.ltr) {
return glyphRuns;
}
var visualOrder = <GlyphRun>[];
if (glyphRuns.isNotEmpty) {
var reversed = glyphRuns.reversed;
GlyphRun previous = reversed.first;
visualOrder.add(previous);
int ltrIndex = 0;
for (final run in reversed.skip(1)) {
if (run.direction == TextDirection.ltr &&
previous.direction == run.direction) {
visualOrder.insert(ltrIndex, run);
} else {
if (run.direction == TextDirection.ltr) {
ltrIndex = visualOrder.length;
}
visualOrder.add(run);
}
previous = run;
}
}
return visualOrder;
}
List<GlyphRun> get visualRuns => orderVisually(runs);
}
abstract class GlyphRun {
Font get font;
double get fontSize;
int get styleId;
int get glyphCount;
TextDirection get direction;
int glyphIdAt(int index);
int textIndexAt(int index);
double advanceAt(int index);
}
class LineRunGlyph {
final GlyphRun run;
final int index;
LineRunGlyph(this.run, this.index);
Float64List renderTransform(double x, double y) {
var scale = run.fontSize;
return Float64List.fromList([
scale,
0.0,
0.0,
0.0,
0.0,
scale,
0.0,
0.0,
0.0,
0.0,
1.0,
0.0,
x,
y,
0.0,
1.0
]);
}
@override
bool operator ==(Object other) =>
other is LineRunGlyph && other.run == run && other.index == index;
}
abstract class GlyphLine {
int get startRun;
int get startIndex;
int get endRun;
int get endIndex;
double get startX;
double get top;
double get baseline;
double get bottom;
/// Returns an iterator that traverses the glyphs in a line in visual order
/// taking into account both the paragraph's runs bidi order and the
/// individual glyphs bidi order within a run.
Iterable<LineRunGlyph> glyphs(Paragraph paragraph) sync* {
var displayRuns = <GlyphRun>[];
var glyphRuns = paragraph.runs;
int runIndex, bidiEndRun, runInc;
// if (paragraph.direction == TextDirection.rtl) {
// runIndex = endRun;
// bidiEndRun = startRun - 1;
// runInc = -1;
// } else {
runIndex = startRun;
bidiEndRun = endRun + 1;
runInc = 1;
// }
while (runIndex != bidiEndRun) {
var run = glyphRuns[runIndex];
displayRuns.add(run);
// int startGIndex = runIndex == startRun ? startIndex : 0;
// int endGIndex = runIndex == endRun ? endIndex : run.glyphCount;
// int j, end, inc;
// if (run.direction == TextDirection.rtl) {
// j = endGIndex - 1;
// end = startGIndex - 1;
// inc = -1;
// } else {
// j = startGIndex;
// end = endGIndex;
// inc = 1;
// }
// while (j != end) {
// yield LineRunGlyph(run, j);
// startGIndex = 0;
// j += inc;
// }
runIndex += runInc;
}
var startRunRef = displayRuns.first;
var endRunRef = displayRuns.last;
for (final run in paragraph.orderVisually(displayRuns)) {
int startGIndex = startRunRef == run ? startIndex : 0;
int endGIndex = endRunRef == run ? endIndex : run.glyphCount;
int j, end, inc;
if (run.direction == TextDirection.rtl) {
j = endGIndex - 1;
end = startGIndex - 1;
inc = -1;
} else {
j = startGIndex;
end = endGIndex;
inc = 1;
}
while (j != end) {
yield LineRunGlyph(run, j);
startGIndex = 0;
j += inc;
}
}
// var glyphRuns = paragraph.visualRuns;
// int runIndex, bidiEndRun, runInc;
// if (paragraph.direction == TextDirection.rtl) {
// runIndex = endRun;
// bidiEndRun = startRun - 1;
// runInc = -1;
// } else {
// runIndex = startRun;
// bidiEndRun = endRun + 1;
// runInc = 1;
// }
// while (runIndex != bidiEndRun) {
// var run = glyphRuns[runIndex];
// int startGIndex = runIndex == startRun ? startIndex : 0;
// int endGIndex = runIndex == endRun ? endIndex : run.glyphCount;
// int j, end, inc;
// if (run.direction == TextDirection.rtl) {
// j = endGIndex - 1;
// end = startGIndex - 1;
// inc = -1;
// } else {
// j = startGIndex;
// end = endGIndex;
// inc = 1;
// }
// while (j != end) {
// yield LineRunGlyph(run, j);
// startGIndex = 0;
// j += inc;
// }
// runIndex += runInc;
// }
}
}
abstract class BreakLinesResult extends ListBase<List<GlyphLine>> {
void dispose();
}
abstract class TextShapeResult {
List<Paragraph> get paragraphs;
void dispose();
BreakLinesResult breakLines(double width, TextAlign alignment);
}
/// A representation of a styled section of text in Rive.
class TextRun {
final Font font;
final double fontSize;
final int unicharCount;
final int styleId;
TextRun({
required this.font,
required this.fontSize,
required this.unicharCount,
this.styleId = 0,
});
TextRun copy({required int copyUnicharCount}) => TextRun(
font: font,
fontSize: fontSize,
unicharCount: copyUnicharCount,
styleId: styleId,
);
@override
String toString() => 'TextRun($fontSize:$unicharCount:$styleId)';
@override
bool operator ==(Object other) =>
other is TextRun &&
other.font == font &&
other.fontSize == fontSize &&
other.unicharCount == unicharCount &&
other.styleId == styleId;
@override
int get hashCode => Object.hash(font, fontSize, unicharCount, styleId);
}
abstract class Font {
static Future<void> initialize() => initFont();
static Font? decode(Uint8List bytes) {
return decodeFont(bytes);
}
static void setFallbacks(List<Font> fonts) {
setFallbackFonts(fonts);
}
RawPath getPath(int glyphId);
void dispose();
TextShapeResult shape(String text, List<TextRun> runs);
final HashMap<int, ui.Path> _glyphPaths = HashMap<int, ui.Path>();
ui.Path getUiPath(int glyphId) {
var glyphPath = _glyphPaths[glyphId];
if (glyphPath != null) {
return glyphPath;
}
var path = ui.Path();
var rawPath = getPath(glyphId);
rawPath.issueCommands(path);
rawPath.dispose();
_glyphPaths[glyphId] = path;
return path;
}
}

View File

@ -1,605 +0,0 @@
import 'dart:collection';
import 'dart:ffi';
import 'dart:io';
import 'dart:typed_data';
import 'package:ffi/ffi.dart';
import 'package:rive/math.dart';
import 'package:rive/src/platform.dart' as rive;
import 'package:rive/src/rive_text.dart';
final DynamicLibrary nativeLib = _loadLibrary();
DynamicLibrary _loadLibrary() {
if (rive.Platform.instance.isTesting) {
var paths = [
'',
'../../packages/rive_flutter/',
];
if (Platform.isMacOS) {
for (final path in paths) {
try {
return DynamicLibrary.open(
'${path}shared_lib/build/bin/debug/librive_text.dylib',
);
// ignore: avoid_catching_errors
} on ArgumentError catch (_) {}
}
} else if (Platform.isLinux) {
for (final path in paths) {
try {
return DynamicLibrary.open(
'${path}shared_lib/build/bin/debug/librive_text.so',
);
// ignore: avoid_catching_errors
} on ArgumentError catch (_) {}
}
}
}
if (Platform.isAndroid) {
return DynamicLibrary.open('librive_text.so');
} else if (Platform.isWindows) {
return DynamicLibrary.open('rive_plugin.dll');
}
return DynamicLibrary.process();
}
class PathPoint extends Struct {
@Float()
external double x;
@Float()
external double y;
@override
String toString() => '[$x, $y]';
}
class GlyphPathStruct extends Struct {
external Pointer<Void> rawPath;
external Pointer<PathPoint> points;
external Pointer<Uint8> verbs;
@Uint16()
external int verbCount;
}
class GlyphLineNative extends Struct {
@Uint32()
external int startRun;
@Uint32()
external int startIndex;
@Uint32()
external int endRun;
@Uint32()
external int endIndex;
@Float()
external double startX;
@Float()
external double top;
@Float()
external double baseline;
@Float()
external double bottom;
}
class GlyphLineFFI extends GlyphLine {
final GlyphLineNative nativeLine;
GlyphLineFFI(this.nativeLine);
@override
double get baseline => nativeLine.baseline;
@override
double get bottom => nativeLine.bottom;
@override
int get endIndex => nativeLine.endIndex;
@override
int get endRun => nativeLine.endRun;
@override
int get startIndex => nativeLine.startIndex;
@override
int get startRun => nativeLine.startRun;
@override
double get startX => nativeLine.startX;
@override
double get top => nativeLine.top;
}
class SimpleLineList extends Struct {
external Pointer<GlyphLineNative> data;
@Uint64()
external int size;
}
class SimpleLineDoubleList extends Struct {
external Pointer<SimpleLineList> data;
@Uint64()
external int size;
}
class SimpleUint16Array extends Struct {
external Pointer<Uint16> data;
@Uint64()
external int size;
}
class SimpleUint32Array extends Struct {
external Pointer<Uint32> data;
@Uint64()
external int size;
}
class SimpleFloatArray extends Struct {
external Pointer<Float> data;
@Uint64()
external int size;
}
class TextRunNative extends Struct {
external Pointer<Void> font;
@Float()
external double size;
@Uint32()
external int unicharCount;
@Uint32()
external int script;
@Uint16()
external int styleId;
@Uint8()
external int dir;
}
class SimpleGlyphRunArray extends Struct {
external Pointer<GlyphRunNative> data;
@Uint64()
external int size;
List<GlyphRunNative> toList() {
var list = <GlyphRunNative>[];
for (int i = 0; i < size; i++) {
list.add(data.elementAt(i).ref);
}
return list;
}
}
class GlyphRunNative extends Struct implements GlyphRun {
external Pointer<Void> fontPtr;
@Float()
external double size;
external SimpleUint16Array glyphs;
external SimpleUint32Array textIndices;
external SimpleFloatArray advances;
external SimpleFloatArray xpos;
external SimpleUint32Array breaks;
@override
@Uint16()
external int styleId;
@Uint8()
external int dir;
@override
double get fontSize => size;
@override
int get glyphCount => glyphs.size;
@override
int glyphIdAt(int index) => glyphs.data.elementAt(index).value;
@override
Font get font => FontFFI(fontPtr);
@override
int textIndexAt(int index) => textIndices.data.elementAt(index).value;
@override
double advanceAt(int index) => advances.data.elementAt(index).value;
@override
TextDirection get direction => TextDirection.values[dir];
}
class DynamicTextRunArray extends Struct {
external Pointer<GlyphRunNative> data;
@Uint64()
external int size;
}
class ParagraphNative extends Struct {
external SimpleGlyphRunArray runs;
@Uint8()
external int direction;
}
class SimpleParagraphArray extends Struct {
external Pointer<ParagraphNative> data;
@Uint64()
external int size;
List<Paragraph> toList() {
var list = <Paragraph>[];
for (int i = 0; i < size; i++) {
list.add(ParagraphFFI(data.elementAt(i).ref));
}
return list;
}
}
class ParagraphFFI extends Paragraph {
final ParagraphNative nativeParagraph;
@override
TextDirection get direction =>
TextDirection.values[nativeParagraph.direction];
@override
final List<GlyphRun> runs;
ParagraphFFI(this.nativeParagraph) : runs = nativeParagraph.runs.toList();
}
class ParagraphsListFFI extends ListBase<ParagraphFFI> {
final SimpleParagraphArray nativeList;
@override
int get length => nativeList.size;
ParagraphsListFFI._(this.nativeList);
@override
ParagraphFFI operator [](int index) =>
ParagraphFFI(nativeList.data.elementAt(index).ref);
@override
void operator []=(int index, ParagraphFFI value) {
throw UnsupportedError('Cannot set Paragraph on ParagraphList');
}
@override
set length(int newLength) {
throw UnsupportedError('Cannot set length on ParagraphList');
}
}
class LineList extends ListBase<GlyphLine> {
final SimpleLineList nativeList;
LineList(this.nativeList);
@override
int get length => nativeList.size;
@override
GlyphLine operator [](int index) =>
GlyphLineFFI(nativeList.data.elementAt(index).ref);
@override
void operator []=(int index, GlyphLine value) {
throw UnsupportedError('Cannot set glyphline on LineList');
}
@override
set length(int newLength) {
throw UnsupportedError('Cannot set length on LineList');
}
}
class LineDoubleList extends BreakLinesResult {
final Pointer<SimpleLineDoubleList> nativeDoubleListPtr;
final SimpleLineDoubleList nativeDoubleList;
@override
int get length => nativeDoubleList.size;
LineDoubleList(this.nativeDoubleListPtr)
: nativeDoubleList = nativeDoubleListPtr.ref;
@override
List<GlyphLine> operator [](int index) =>
LineList(nativeDoubleList.data.elementAt(index).ref);
@override
void operator []=(int index, List<GlyphLine> value) {
throw UnsupportedError('Cannot set list on LineDoubleList');
}
@override
set length(int newLength) {
throw UnsupportedError('Cannot set length on LineDoubleList');
}
@override
void dispose() => deleteLines(nativeDoubleListPtr);
}
class TextShapeResultFFI extends TextShapeResult {
final Pointer<SimpleParagraphArray> nativeResult;
TextShapeResultFFI(this.nativeResult)
: paragraphs = nativeResult.ref.toList();
@override
void dispose() {
deleteShapeResult(nativeResult);
}
@override
BreakLinesResult breakLines(double width, TextAlign alignment) {
return LineDoubleList(
breakLinesNative(nativeResult, width, alignment.index));
}
@override
final List<Paragraph> paragraphs;
}
final Pointer<SimpleParagraphArray> Function(Pointer<Uint32> text,
int textLength, Pointer<TextRunNative> runs, int runsLength) shapeText =
nativeLib
.lookup<
NativeFunction<
Pointer<SimpleParagraphArray> Function(Pointer<Uint32>, Uint64,
Pointer<TextRunNative>, Uint64)>>('shapeText')
.asFunction();
final void Function(Pointer<SimpleParagraphArray> font) deleteShapeResult =
nativeLib
.lookup<NativeFunction<Void Function(Pointer<SimpleParagraphArray>)>>(
'deleteShapeResult')
.asFunction();
final Pointer<SimpleLineDoubleList> Function(
Pointer<SimpleParagraphArray>, double width, int align)
breakLinesNative = nativeLib
.lookup<
NativeFunction<
Pointer<SimpleLineDoubleList> Function(
Pointer<SimpleParagraphArray>, Float, Uint8)>>('breakLines')
.asFunction();
final void Function(Pointer<SimpleLineDoubleList>) deleteLines = nativeLib
.lookup<NativeFunction<Void Function(Pointer<SimpleLineDoubleList>)>>(
'deleteLines')
.asFunction();
final Pointer<Void> Function(Pointer<Uint8> bytes, int count) makeFont =
nativeLib
.lookup<NativeFunction<Pointer<Void> Function(Pointer<Uint8>, Uint64)>>(
'makeFont')
.asFunction();
final void Function(Pointer<Void> font) deleteFont = nativeLib
.lookup<NativeFunction<Void Function(Pointer<Void>)>>('deleteFont')
.asFunction();
final GlyphPathStruct Function(
Pointer<Void> font,
int
glyphId) makeGlyphPath = nativeLib
.lookup<NativeFunction<GlyphPathStruct Function(Pointer<Void>, Uint16)>>(
'makeGlyphPath')
.asFunction();
final void Function(Pointer<Void> font) deleteGlyphPath = nativeLib
.lookup<NativeFunction<Void Function(Pointer<Void>)>>('deleteGlyphPath')
.asFunction();
final void Function() init =
nativeLib.lookup<NativeFunction<Void Function()>>('init').asFunction();
final Pointer<SimpleParagraphArray> Function(
Pointer<Pointer<Void>> fonts, int fontsLength) setFallbackFontsNative =
nativeLib
.lookup<
NativeFunction<
Pointer<SimpleParagraphArray> Function(
Pointer<Pointer<Void>>, Uint64)>>('setFallbackFonts')
.asFunction();
class RawPathCommandWasm extends RawPathCommand {
final Pointer<PathPoint> _points;
RawPathCommandWasm._(
RawPathVerb verb,
this._points,
) : super(verb);
@override
Vec2D point(int index) {
var ref = _points.elementAt(index).ref;
return Vec2D.fromValues(ref.x, ref.y);
}
}
RawPathVerb _verbFromNative(int nativeVerb) {
switch (nativeVerb) {
case 0:
return RawPathVerb.move;
case 1:
return RawPathVerb.line;
case 2:
return RawPathVerb.quad;
case 4:
return RawPathVerb.cubic;
case 5:
return RawPathVerb.close;
default:
throw Exception('Unexpected nativeVerb: $nativeVerb');
}
}
int _ptsAdvanceAfterVerb(RawPathVerb verb) {
switch (verb) {
case RawPathVerb.move:
return 1;
case RawPathVerb.line:
return 1;
case RawPathVerb.quad:
return 2;
case RawPathVerb.cubic:
return 3;
case RawPathVerb.close:
return 0;
default:
throw Exception('Unexpected nativeVerb: $verb');
}
}
int _ptsBacksetForVerb(RawPathVerb verb) {
switch (verb) {
case RawPathVerb.move:
return 0;
case RawPathVerb.line:
return -1;
case RawPathVerb.quad:
return -1;
case RawPathVerb.cubic:
return -1;
case RawPathVerb.close:
return -1;
default:
throw Exception('Unexpected nativeVerb: $verb');
}
}
class RawPathIterator extends Iterator<RawPathCommand> {
final GlyphPathStruct _native;
int _verbIndex = -1;
int _ptIndex = -1;
RawPathVerb _verb = RawPathVerb.move;
RawPathIterator._(this._native);
@override
RawPathCommand get current => RawPathCommandWasm._(
_verb,
_native.points.elementAt(_ptIndex + _ptsBacksetForVerb(_verb)),
);
@override
bool moveNext() {
if (++_verbIndex < _native.verbCount) {
_ptIndex += _ptsAdvanceAfterVerb(_verb);
_verb = _verbFromNative(_native.verbs.elementAt(_verbIndex).value);
return true;
}
return false;
}
}
class RawPathFFI extends RawPath {
final GlyphPathStruct _native;
RawPathFFI._(this._native);
@override
Iterator<RawPathCommand> get iterator => RawPathIterator._(_native);
@override
void dispose() => deleteGlyphPath(_native.rawPath);
}
/// A Font created and owned by Dart code. User is expected to call
/// dispose to release the font when they are done with it.
class StrongFontFFI extends FontFFI {
StrongFontFFI(Pointer<Void> ptr) : super(ptr);
@override
void dispose() => deleteFont(fontPtr);
}
/// A Font reference that should not be explicitly disposed by the user.
/// Returned while shaping.
class FontFFI extends Font {
Pointer<Void> fontPtr;
FontFFI(this.fontPtr);
@override
RawPath getPath(int glyphId) {
var glyphPath = makeGlyphPath(fontPtr, glyphId);
return RawPathFFI._(glyphPath);
}
@override
void dispose() {}
@override
TextShapeResult shape(String text, List<TextRun> runs) {
var textUni = text.codeUnits;
// Allocate and copy to runs memory.
var runsMemory =
calloc.allocate<TextRunNative>(runs.length * sizeOf<TextRunNative>());
int runIndex = 0;
for (final run in runs) {
runsMemory[runIndex++]
..font = (run.font as FontFFI).fontPtr
..size = run.fontSize
..script = 0
..unicharCount = run.unicharCount
..styleId = run.styleId
..dir = 0;
}
// Allocate and copy to text buffer.
var textBuffer = calloc.allocate<Uint32>(textUni.length * sizeOf<Uint32>());
for (int i = 0; i < textUni.length; i++) {
textBuffer[i] = textUni[i];
}
var shapeResult =
shapeText(textBuffer, textUni.length, runsMemory, runs.length);
// Free memory for structs passed into native that we no longer need.
calloc.free(textBuffer);
calloc.free(runsMemory);
return TextShapeResultFFI(shapeResult);
}
}
Font? decodeFont(Uint8List bytes) {
// Copy them to the native heap.
var pointer = calloc.allocate<Uint8>(bytes.length);
for (int i = 0; i < bytes.length; i++) {
pointer[i] = bytes[i];
}
// Pass the pointer in to a native method.
var result = makeFont(pointer, bytes.length);
calloc.free(pointer);
return FontFFI(result);
}
Future<void> initFont() async {
init();
}
void setFallbackFonts(List<Font> fonts) {
// Allocate and copy to fonts list memory.
var fontListMemory =
calloc.allocate<Pointer<Void>>(fonts.length * sizeOf<Pointer<Void>>());
int fontIndex = 0;
for (final font in fonts) {
fontListMemory[fontIndex++] = (font as FontFFI).fontPtr;
}
setFallbackFontsNative(fontListMemory, fonts.length);
// Free memory for structs passed into native that we no longer need.
calloc.free(fontListMemory);
}

View File

@ -1,551 +0,0 @@
// ignore: avoid_web_libraries_in_flutter
import 'dart:async';
import 'dart:collection';
import 'dart:html' as html;
import 'dart:js' as js;
import 'dart:typed_data';
import 'package:rive/math.dart';
import 'package:rive/src/rive_text.dart';
import 'package:rive/src/rive_text_wasm_version.dart';
import 'package:rive/src/utilities/binary_buffer/binary_reader.dart';
import 'package:rive/src/utilities/binary_buffer/binary_writer.dart';
late js.JsFunction _makeFont;
late js.JsFunction _deleteFont;
late js.JsFunction _makeGlyphPath;
late js.JsFunction _deleteGlyphPath;
late js.JsFunction _shapeText;
late js.JsFunction _setFallbackFonts;
late js.JsFunction _deleteShapeResult;
late js.JsFunction _breakLines;
late js.JsFunction _deleteLines;
class RawPathWasm extends RawPath {
final Uint8List verbs;
final Float32List points;
RawPathWasm({
required this.verbs,
required this.points,
});
@override
void dispose() {}
@override
Iterator<RawPathCommand> get iterator => RawPathIterator._(verbs, points);
}
class RawPathCommandWasm extends RawPathCommand {
final Float32List _points;
final int _pointsOffset;
RawPathCommandWasm._(
RawPathVerb verb,
this._points,
this._pointsOffset,
) : super(verb);
@override
Vec2D point(int index) {
var base = _pointsOffset + index * 2;
return Vec2D.fromValues(_points[base], _points[base + 1]);
}
}
RawPathVerb _verbFromNative(int nativeVerb) {
switch (nativeVerb) {
case 0:
return RawPathVerb.move;
case 1:
return RawPathVerb.line;
case 2:
return RawPathVerb.quad;
case 4:
return RawPathVerb.cubic;
case 5:
return RawPathVerb.close;
default:
throw Exception('Unexpected nativeVerb: $nativeVerb');
}
}
int _ptsAdvanceAfterVerb(RawPathVerb verb) {
switch (verb) {
case RawPathVerb.move:
return 1;
case RawPathVerb.line:
return 1;
case RawPathVerb.quad:
return 2;
case RawPathVerb.cubic:
return 3;
case RawPathVerb.close:
return 0;
default:
throw Exception('Unexpected nativeVerb: $verb');
}
}
int _ptsBacksetForVerb(RawPathVerb verb) {
switch (verb) {
case RawPathVerb.move:
return 0;
case RawPathVerb.line:
return -1;
case RawPathVerb.quad:
return -1;
case RawPathVerb.cubic:
return -1;
case RawPathVerb.close:
return -1;
default:
throw Exception('Unexpected nativeVerb: $verb');
}
}
class RawPathIterator extends Iterator<RawPathCommand> {
final Uint8List verbs;
final Float32List points;
int _verbIndex = -1;
int _ptIndex = -1;
RawPathVerb _verb = RawPathVerb.move;
RawPathIterator._(this.verbs, this.points);
@override
RawPathCommand get current => RawPathCommandWasm._(
_verb,
points,
(_ptIndex + _ptsBacksetForVerb(_verb)) * 2,
);
@override
bool moveNext() {
if (++_verbIndex < verbs.length) {
_ptIndex += _ptsAdvanceAfterVerb(_verb);
_verb = _verbFromNative(verbs[_verbIndex]);
return true;
}
return false;
}
}
class GlyphLineWasm extends GlyphLine {
@override
final int startRun;
@override
final int startIndex;
@override
final int endRun;
@override
final int endIndex;
@override
final double startX;
@override
final double top;
@override
final double baseline;
@override
final double bottom;
GlyphLineWasm(ByteData data)
: startRun = data.getUint32(0, Endian.little),
startIndex = data.getUint32(4, Endian.little),
endRun = data.getUint32(8, Endian.little),
endIndex = data.getUint32(12, Endian.little),
startX = data.getFloat32(16, Endian.little),
top = data.getFloat32(20, Endian.little),
baseline = data.getFloat32(24, Endian.little),
bottom = data.getFloat32(28, Endian.little);
@override
String toString() {
return "GlyphLineWasm $startRun $startIndex $endRun $endIndex $startX $top $baseline $bottom";
}
}
class BreakLinesResultFFI extends BreakLinesResult {
final List<List<GlyphLine>> list;
BreakLinesResultFFI(this.list);
@override
int get length => list.length;
@override
set length(int value) => list.length = value;
@override
List<GlyphLine> operator [](int index) => list[index];
@override
void operator []=(int index, List<GlyphLine> value) => list[index] = value;
@override
void dispose() {}
}
class TextShapeResultWasm extends TextShapeResult {
final int shapeResultPtr;
@override
final List<ParagraphWasm> paragraphs;
TextShapeResultWasm(this.shapeResultPtr, this.paragraphs);
@override
void dispose() => _deleteShapeResult.apply(<dynamic>[shapeResultPtr]);
@override
BreakLinesResult breakLines(double width, TextAlign alignment) {
var result = _breakLines.apply(
<dynamic>[
shapeResultPtr,
width,
alignment.index,
],
) as js.JsObject;
var rawResult = result['rawResult'] as int;
var results = result['results'] as Uint8List;
const lineSize = 32;
var paragraphsList = ByteData.view(results.buffer, results.offsetInBytes)
.readDynamicArray(0);
var paragraphsLines = <List<GlyphLine>>[];
var pointerEnd = paragraphsList.size * 8;
for (var pointer = 0; pointer < pointerEnd; pointer += 8) {
var sublist = paragraphsList.data.readDynamicArray(pointer);
var lines = <GlyphLine>[];
var end = sublist.data.offsetInBytes + sublist.size * lineSize;
for (var lineOffset = sublist.data.offsetInBytes;
lineOffset < end;
lineOffset += lineSize) {
lines.add(
GlyphLineWasm(
ByteData.view(
sublist.data.buffer,
lineOffset,
),
),
);
}
paragraphsLines.add(lines);
}
_deleteLines.apply(
<dynamic>[
rawResult,
],
);
return BreakLinesResultFFI(paragraphsLines);
}
}
extension ByteDataWasm on ByteData {
WasmDynamicArray readDynamicArray(int offset) {
return WasmDynamicArray(
ByteData.view(buffer, getUint32(offset, Endian.little)),
getUint32(
offset + 4,
Endian.little,
),
);
}
Uint16List readUint16List(int offset, {bool clone = true}) {
var array = readDynamicArray(offset);
var list =
array.data.buffer.asUint16List(array.data.offsetInBytes, array.size);
if (clone) {
return Uint16List.fromList(list);
}
return list;
}
Uint32List readUint32List(int offset, {bool clone = true}) {
var array = readDynamicArray(offset);
var list =
array.data.buffer.asUint32List(array.data.offsetInBytes, array.size);
if (clone) {
return Uint32List.fromList(list);
}
return list;
}
Float32List readFloat32List(int offset, {bool clone = true}) {
var array = readDynamicArray(offset);
var list =
array.data.buffer.asFloat32List(array.data.offsetInBytes, array.size);
if (clone) {
return Float32List.fromList(list);
}
return list;
}
}
class WasmDynamicArray {
final ByteData data;
final int size;
WasmDynamicArray(this.data, this.size);
}
class LinesWasm extends ListBase<GlyphLineWasm> {
final WasmDynamicArray wasmDynamicArray;
LinesWasm(this.wasmDynamicArray);
@override
int get length => wasmDynamicArray.size;
@override
GlyphLineWasm operator [](int index) {
const lineSize = 4 + //startRun
4 + // startIndex
4 + // endRun
4 + // endIndex
4 + // startX
4 + // top
4 + // baseline
4; // bottom
var data = wasmDynamicArray.data;
return GlyphLineWasm(
ByteData.view(
data.buffer,
data.offsetInBytes + index * lineSize,
),
);
}
@override
void operator []=(int index, GlyphLineWasm value) {
throw UnsupportedError('Cannot set Line on LinesWasm array');
}
@override
set length(int newLength) {
throw UnsupportedError('Cannot set Line count on LinesWasm array');
}
}
class ParagraphWasm extends Paragraph {
final ByteData data;
@override
final TextDirection direction;
@override
final List<GlyphRunWasm> runs = [];
ParagraphWasm(this.data)
: direction = TextDirection.values[data.getUint8(8)] {
const runSize =
52; // see rive_text_bindings.cpp assertSomeAssumptions for explanation
var runsPointer = data.getUint32(0, Endian.little);
var runsCount = data.getUint32(4, Endian.little);
for (int i = 0, runPointer = runsPointer;
i < runsCount;
i++, runPointer += runSize) {
runs.add(GlyphRunWasm(ByteData.view(data.buffer, runPointer)));
}
}
}
class GlyphRunWasm extends GlyphRun {
final ByteData byteData;
final Uint16List glyphs;
final Uint32List textIndices;
final Float32List xPositions;
@override
final TextDirection direction;
@override
final int styleId;
@override
final Font font;
@override
final double fontSize;
GlyphRunWasm(this.byteData)
: font = FontWasm(byteData.getUint32(0, Endian.little)),
fontSize = byteData.getFloat32(4, Endian.little),
glyphs = byteData.readUint16List(8),
textIndices = byteData.readUint32List(16),
xPositions = byteData.readFloat32List(24),
styleId = byteData.getUint16(48, Endian.little),
direction = TextDirection.values[byteData.getUint8(50)];
@override
int get glyphCount => glyphs.length;
@override
int glyphIdAt(int index) => glyphs[index];
@override
int textIndexAt(int index) => textIndices[index];
@override
double advanceAt(int index) => xPositions[index];
}
/// A Font reference that should not be explicitly disposed by the user.
/// Returned while shaping.
class FontWasm extends Font {
final int fontPtr;
FontWasm(this.fontPtr);
@override
String toString() {
return 'FontWasm $fontPtr';
}
@override
void dispose() {}
@override
RawPath getPath(int glyphId) {
var object =
_makeGlyphPath.apply(<dynamic>[fontPtr, glyphId]) as js.JsObject;
var rawPathPtr = object['rawPath'] as int;
// The buffer for these share the WASM heap buffer, which is efficient but
// could also be lost in-between calls to WASM.
var verbs = object['verbs'] as Uint8List;
var points = object['points'] as Float32List;
// We copy the verb and points structures so we don't have to worry about
// the references being lost if the WASM heap is re-allocated.
var rawPath = RawPathWasm(
verbs: Uint8List.fromList(verbs),
points: Float32List.fromList(points),
);
// Immediately delete the native glyph's raw path.
_deleteGlyphPath.apply(<dynamic>[rawPathPtr]);
return rawPath;
}
static const int sizeOfNativeTextRun = 20;
@override
TextShapeResult shape(String text, List<TextRun> runs) {
var writer = BinaryWriter(
alignment: runs.length * sizeOfNativeTextRun,
);
for (final run in runs) {
writer.writeUint32((run.font as FontWasm).fontPtr);
writer.writeFloat32(run.fontSize);
writer.writeUint32(run.unicharCount);
writer.writeUint32(0); // script (unknown at this point)
writer.writeUint16(run.styleId);
writer.writeUint8(0); // dir (unknown at this point)
writer.writeUint8(0); // padding to word align struct
}
var result = _shapeText.apply(
<dynamic>[
Uint32List.fromList(text.codeUnits),
writer.uint8Buffer,
],
) as js.JsObject;
var rawResult = result['rawResult'] as int;
var results = result['results'] as Uint8List;
var reader = BinaryReader.fromList(results);
var paragraphsPointer = reader.readUint32();
var paragraphsSize = reader.readUint32();
var paragraphList = <ParagraphWasm>[];
const paragraphSize = 12; // runs = 8, direction = 1, padding = 3
for (int i = 0;
i < paragraphsSize;
i++, paragraphsPointer += paragraphSize) {
paragraphList
.add(ParagraphWasm(ByteData.view(results.buffer, paragraphsPointer)));
}
return TextShapeResultWasm(rawResult, paragraphList);
}
}
/// A Font created and owned by Dart code. User is expected to call
/// dispose to release the font when they are done with it.
class StrongFontWasm extends FontWasm {
StrongFontWasm(int fontPtr) : super(fontPtr);
@override
void dispose() => _deleteFont.apply(<dynamic>[fontPtr]);
}
Font? decodeFont(Uint8List bytes) {
int ptr = _makeFont.apply(<dynamic>[bytes]) as int;
if (ptr == 0) {
return null;
}
return StrongFontWasm(ptr);
}
Future<void> initFont() async {
var script = html.ScriptElement()
..src = const bool.fromEnvironment(
'LOCAL_RIVE_FLUTTER_WASM',
defaultValue: false,
)
? 'http://localhost:8282/release/rive_text.js'
: 'https://unpkg.com/@rive-app/flutter-wasm@$wasmVersion/build/bin/release/rive_text.js'
..type = 'application/javascript'
..defer = true;
html.document.body!.append(script);
await script.onLoad.first;
var initWasm = js.context['RiveText'] as js.JsFunction;
var promise = initWasm.apply(<dynamic>[]) as js.JsObject;
var thenFunction = promise['then'] as js.JsFunction;
var completer = Completer<void>();
thenFunction.apply(
<dynamic>[
(js.JsObject module) {
var init = module['init'] as js.JsFunction;
init.apply(<dynamic>[]);
_makeFont = module['makeFont'] as js.JsFunction;
_deleteFont = module['deleteFont'] as js.JsFunction;
_makeGlyphPath = module['makeGlyphPath'] as js.JsFunction;
_deleteGlyphPath = module['deleteGlyphPath'] as js.JsFunction;
_shapeText = module['shapeText'] as js.JsFunction;
_setFallbackFonts = module['setFallbackFonts'] as js.JsFunction;
_deleteShapeResult = module['deleteShapeResult'] as js.JsFunction;
_breakLines = module['breakLines'] as js.JsFunction;
_deleteLines = module['deleteLines'] as js.JsFunction;
completer.complete();
}
],
thisArg: promise,
);
return completer.future;
}
void setFallbackFonts(List<Font> fonts) {
_setFallbackFonts.apply(
<dynamic>[
Uint32List.fromList(
fonts
.cast<FontWasm>()
.map((font) => font.fontPtr)
.toList(growable: false),
),
],
);
}

View File

@ -1 +0,0 @@
const wasmVersion = '6.0.0';

View File

@ -5,10 +5,8 @@ import 'package:rive/src/rive_core/animation/linear_animation_instance.dart';
import 'package:rive/src/rive_core/animation/nested_linear_animation.dart';
import 'package:rive/src/rive_core/animation/nested_state_machine.dart';
import 'package:rive/src/rive_core/artboard.dart';
import 'package:rive/src/rive_core/math/aabb.dart';
import 'package:rive/src/rive_core/math/mat2d.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive/src/rive_core/nested_artboard.dart';
import 'package:rive_common/math.dart';
class RuntimeNestedArtboard extends NestedArtboard {
Artboard? sourceArtboard;

View File

@ -1,114 +0,0 @@
import 'dart:convert';
import 'dart:typed_data';
class BinaryReader {
final _utf8Decoder = const Utf8Decoder();
final ByteData buffer;
final Endian endian;
/// TODO: remove setter for readIndex when we remove _readVarInt from
/// core_double_type.dart
int readIndex = 0;
int get position => readIndex;
BinaryReader(this.buffer, {this.endian = Endian.little});
BinaryReader.fromList(Uint8List list, {this.endian = Endian.little})
: buffer =
ByteData.view(list.buffer, list.offsetInBytes, list.lengthInBytes);
bool get isEOF => readIndex >= buffer.lengthInBytes;
double readFloat32() {
double value = buffer.getFloat32(readIndex, endian);
readIndex += 4;
return value;
}
double readFloat64() {
double value = buffer.getFloat64(readIndex, endian);
readIndex += 8;
return value;
}
int readInt8() {
int value = buffer.getInt8(readIndex);
readIndex += 1;
return value;
}
int readUint8() {
int value = buffer.getUint8(readIndex);
readIndex += 1;
return value;
}
int readInt16() {
int value = buffer.getInt16(readIndex, endian);
readIndex += 2;
return value;
}
int readUint16() {
int value = buffer.getUint16(readIndex, endian);
readIndex += 2;
return value;
}
int readInt32() {
int value = buffer.getInt32(readIndex, endian);
readIndex += 4;
return value;
}
int readUint32() {
int value = buffer.getUint32(readIndex, endian);
readIndex += 4;
return value;
}
int readInt64() {
int value = buffer.getInt64(readIndex, endian);
readIndex += 8;
return value;
}
int readUint64() {
int value = buffer.getUint64(readIndex, endian);
readIndex += 8;
return value;
}
/// Read a variable length unsigned integer from the buffer encoded as an
/// LEB128 unsigned integer.
int readVarUint() {
int result = 0;
int shift = 0;
while (true) {
int byte = buffer.getUint8(readIndex++) & 0xff;
result |= (byte & 0x7f) << shift;
if ((byte & 0x80) == 0) break;
shift += 7;
}
return result;
}
/// Read a string encoded into the stream. Strings are encoded with a varuint
/// integer length written first followed by length number of utf8 encoded
/// bytes.
String readString({bool explicitLength = true}) {
int length = explicitLength ? readVarUint() : buffer.lengthInBytes;
String value = _utf8Decoder.convert(Uint8List.view(
buffer.buffer, buffer.offsetInBytes + readIndex, length));
readIndex += length;
return value;
}
Uint8List read(int length, [bool allocNew = true]) {
var view =
Uint8List.view(buffer.buffer, buffer.offsetInBytes + readIndex, length);
readIndex += length;
return allocNew ? Uint8List.fromList(view) : view;
}
}

View File

@ -1,144 +0,0 @@
import 'dart:convert';
import 'dart:math';
import 'dart:typed_data';
class BinaryWriter {
final _variableEncodeList = Uint8List(8);
final _utf8Encoder = const Utf8Encoder();
/// Stride we allocate buffer in chunks of.
final int _alignment;
int get alignment => _alignment;
final Endian endian;
late Uint8List _buffer;
ByteData get buffer =>
ByteData.view(_buffer.buffer, _buffer.offsetInBytes, size);
Uint8List get uint8Buffer =>
Uint8List.view(_buffer.buffer, _buffer.offsetInBytes, size);
late ByteData _byteData;
int _writeIndex = 0;
int get size => _writeIndex;
BinaryWriter({int alignment = 1024, this.endian = Endian.little})
: _alignment = max(1, alignment) {
_buffer = Uint8List(_alignment);
_byteData = ByteData.view(_buffer.buffer);
}
/// Return the smallest multiple of [_alignment] that fits data of [length]
int nextAlignment(int length) {
return (length / alignment).ceil() * alignment;
}
void _ensureAvailable(int byteLength) {
if (_writeIndex + byteLength > _buffer.length) {
do {
_buffer = Uint8List(_buffer.length + nextAlignment(byteLength))
..setRange(0, _buffer.length, _buffer);
} while (_writeIndex + byteLength > _buffer.length);
_byteData = ByteData.view(_buffer.buffer);
}
}
void writeFloat32(double value) {
_ensureAvailable(4);
_byteData.setFloat32(_writeIndex, value, endian);
_writeIndex += 4;
}
void writeFloat64(double value) {
_ensureAvailable(8);
_byteData.setFloat64(_writeIndex, value, endian);
_writeIndex += 8;
}
void writeInt8(int value) {
_ensureAvailable(1);
_byteData.setInt8(_writeIndex, value);
_writeIndex += 1;
}
void writeUint8(int value) {
_ensureAvailable(1);
_byteData.setUint8(_writeIndex, value);
_writeIndex += 1;
}
void writeInt16(int value) {
_ensureAvailable(2);
_byteData.setInt16(_writeIndex, value, endian);
_writeIndex += 2;
}
void writeUint16(int value) {
_ensureAvailable(2);
_byteData.setUint16(_writeIndex, value, endian);
_writeIndex += 2;
}
void writeInt32(int value) {
_ensureAvailable(4);
_byteData.setInt32(_writeIndex, value, endian);
_writeIndex += 4;
}
void writeUint32(int value) {
_ensureAvailable(4);
_byteData.setUint32(_writeIndex, value, endian);
_writeIndex += 4;
}
void writeInt64(int value) {
_ensureAvailable(8);
_byteData.setInt64(_writeIndex, value, endian);
_writeIndex += 8;
}
void writeUint64(int value) {
_ensureAvailable(8);
_byteData.setUint64(_writeIndex, value, endian);
_writeIndex += 8;
}
/// Write bytes into the buffer. Optional [length] to write a specific number
/// of [bytes], otherwise the length from [bytes] is used.
void write(Uint8List bytes, [int? length]) {
length ??= bytes.length;
_ensureAvailable(length);
_buffer.setRange(_writeIndex, _writeIndex + length, bytes);
_writeIndex += length;
}
/// Write an integer as a list of bytes that contain an LEB128 unsigned
/// integer. The size of the integer is decided automatically.
void writeVarUint(int value) {
int size = (value.toRadixString(2).length / 7.0).ceil();
int index = 0;
int i = 0;
while (i < size) {
int part = value & 0x7f;
//ignore: parameter_assignments
value >>= 7;
_variableEncodeList[index++] = part;
i += 1;
}
for (var i = 0; i < index - 1; i++) {
_variableEncodeList[i] |= 0x80;
}
write(_variableEncodeList, index);
}
/// Encode a string into the buffer. Strings are encoded with a varuint
/// integer length written first followed by length number of utf8 encoded
/// bytes.
void writeString(String value, {bool explicitLength = true}) {
var list = _utf8Encoder.convert(value);
if (explicitLength) {
writeVarUint(list.length);
}
write(list);
}
}

View File

@ -1,113 +0,0 @@
import 'dart:collection';
import 'package:graphs/graphs.dart';
/// Interface for a node in the dependency graph.
abstract class DependencyGraphNode<T> {
Set<T> get dependents;
}
/// A simple dependency sorter which will solve well formed dependency
/// structures. It'll detect dependency cycles but it will not help find what
/// caused the cycle or provide any attempt at a best guess for order in cyclic
/// scenarios. Use this as a best case first run and fall back to a more complex
/// solver if this one finds a cycle.
class DependencySorter<T extends DependencyGraphNode<T>> {
final _perm = HashSet<T>();
final _temp = HashSet<T>();
var _order = <T>[];
List<T> get order => _order.reversed.toList();
List<T> sort(T root) {
_order = <T>[];
if (!visit(root)) {
return [];
}
return _order.reversed.toList();
}
void reset() {
_order = <T>[];
}
bool visit(T n) {
if (_perm.contains(n)) {
return true;
}
if (_temp.contains(n)) {
// cycle detected!
return false;
}
_temp.add(n);
final dependents = n.dependents;
for (final T d in dependents) {
if (!visit(d)) {
return false;
}
}
_perm.add(n);
// Note that we're adding in reverse order intentionally so we don't have to
// keep inserting at the start and re-alloc-ing the whole list...It does
// mean we need to reverse the list afterwards.
_order.add(n);
return true;
}
}
/// Sorts dependencies for Actors even when cycles are present
///
/// Any nodes that form part of a cycle can be found in `cycleNodes` after
/// `sort`. NOTE: Nodes isolated by cycles will not be found in `_order` or
/// `cycleNodes` e.g. `A -> B <-> C -> D` isolates D when running a sort based
/// on A
class TarjansDependencySorter<T extends DependencyGraphNode<T>>
extends DependencySorter<T> {
final _cycleNodes = HashSet<T>();
HashSet<T> get cycleNodes => _cycleNodes;
@override
List<T> sort(T root) {
_order = <T>[];
if (!visit(root)) {
// if we detect cycles, go find them all
findCycles(root);
// revisit the tree, skipping nodes on any cycle.
visit(root);
}
return _order.reversed.toList();
}
HashSet<T> findCycles(T n) {
_perm.clear();
_temp.clear();
_cycleNodes.clear();
_order.clear();
var cycles = stronglyConnectedComponents<T>([n], (node) => node.dependents);
cycles.forEach((cycle) {
// cycles of len 1 are not cycles.
if (cycle.length > 1) {
cycle.forEach(_cycleNodes.add);
}
});
return _cycleNodes;
}
@override
bool visit(T n) {
if (cycleNodes.contains(n)) {
// skip any nodes on a known cycle.
return true;
}
return super.visit(n);
}
}

View File

@ -1,28 +0,0 @@
abstract class Parentable<T> {
T? get parent;
}
/// Get the top most components (any child that has an ancestor in the set
/// should be pruned).
Set<T> tops<T extends Parentable<T>>(Iterable<T> parentables) {
var tips = <T>{};
outerLoop:
for (final item in parentables) {
for (T? parent = item.parent; parent != null; parent = parent.parent) {
if (parentables.contains(parent)) {
continue outerLoop;
}
}
tips.add(item);
}
return tips;
}
bool isChildOf<T extends Parentable<T>>(T child, Iterable<T> parents) {
for (T? parent = child; parent != null; parent = parent.parent) {
if (parents.contains(parent)) {
return true;
}
}
return false;
}

View File

@ -1,7 +0,0 @@
/// Szudzik's function for hashing two ints together
int szudzik(int a, int b) {
// a and b must be >= 0
int x = a.abs();
int y = b.abs();
return x >= y ? x * x + x + y : x + y * y;
}

View File

@ -1,6 +1,6 @@
import 'package:flutter/widgets.dart';
import 'package:rive/rive.dart';
import 'package:rive/src/rive_core/math/vec2d.dart';
import 'package:rive_common/math.dart';
/// Specifies whether a source is from an asset bundle or http
enum _Source {

View File

@ -1,19 +0,0 @@
import Cocoa
import FlutterMacOS
public class RivePlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: "rive", binaryMessenger: registrar.messenger)
let instance = RivePlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "getPlatformVersion":
result("macOS " + ProcessInfo.processInfo.operatingSystemVersionString)
default:
result(FlutterMethodNotImplemented)
}
}
}

View File

@ -1,10 +0,0 @@
//
// Generated file. Do not edit.
//
import FlutterMacOS
import Foundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
}

Some files were not shown because too many files have changed in this diff Show More