mirror of
https://github.com/rive-app/rive-flutter
synced 2025-07-14 21:55:57 +00:00
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:
10
.github/workflows/tests.yaml
vendored
10
.github/workflows/tests.yaml
vendored
@ -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
|
||||
|
@ -1 +1 @@
|
||||
3be5ff0d873280d2bcec300fb764f016ac96a08d
|
||||
12c6ee13010f1f73354358ae169e4f81e646b8be
|
||||
|
9
android/.gitignore
vendored
9
android/.gitignore
vendored
@ -1,9 +0,0 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.cxx
|
@ -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)
|
@ -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"
|
||||
}
|
@ -1 +0,0 @@
|
||||
rootProject.name = 'rive'
|
@ -1,3 +0,0 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="app.rive.rive">
|
||||
</manifest>
|
@ -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)
|
||||
}
|
||||
}
|
@ -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
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import rive
|
||||
import rive_common
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
RivePlugin.register(with: registry.registrar(forPlugin: "RivePlugin"))
|
||||
|
@ -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
|
||||
|
||||
|
@ -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(
|
||||
|
@ -3,7 +3,7 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
rive
|
||||
rive_common
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
|
38
ios/.gitignore
vendored
38
ios/.gitignore
vendored
@ -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
|
@ -1,4 +0,0 @@
|
||||
#import <Flutter/Flutter.h>
|
||||
|
||||
@interface RivePlugin : NSObject <FlutterPlugin>
|
||||
@end
|
@ -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
|
@ -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)
|
||||
}
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
@ -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';
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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> {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
@ -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);
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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,
|
||||
}
|
@ -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),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -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)';
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
@ -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);
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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?.
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
@ -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),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
@ -1 +0,0 @@
|
||||
const wasmVersion = '6.0.0';
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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
Reference in New Issue
Block a user