Repository: react-native-community/art Branch: master Commit: e4a97cd03ec9 Files: 128 Total size: 252.5 KB Directory structure: gitextract_jk1tw2te/ ├── .circleci/ │ └── config.yml ├── .eslintrc.js ├── .flowconfig ├── .gitattributes ├── .gitignore ├── .npmignore ├── .prettierrc.js ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── ReactNativeART.podspec ├── android/ │ ├── .gitignore │ ├── build.gradle │ ├── gradle/ │ │ └── wrapper/ │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── gradle.properties │ ├── gradlew │ ├── gradlew.bat │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ ├── java/ │ │ └── com/ │ │ └── reactnativecommunity/ │ │ └── art/ │ │ ├── ARTGroupShadowNode.java │ │ ├── ARTGroupViewManager.java │ │ ├── ARTPackage.java │ │ ├── ARTRenderableViewManager.java │ │ ├── ARTShapeShadowNode.java │ │ ├── ARTShapeViewManager.java │ │ ├── ARTSurfaceView.java │ │ ├── ARTSurfaceViewManager.java │ │ ├── ARTSurfaceViewShadowNode.java │ │ ├── ARTTextShadowNode.java │ │ ├── ARTTextViewManager.java │ │ ├── ARTVirtualNode.java │ │ └── PropHelper.java │ └── res/ │ └── values/ │ └── strings.xml ├── babel.config.js ├── docs/ │ └── api.md ├── example/ │ ├── App.js │ ├── android/ │ │ ├── app/ │ │ │ ├── build.gradle │ │ │ ├── proguard-rules.pro │ │ │ └── src/ │ │ │ ├── debug/ │ │ │ │ └── AndroidManifest.xml │ │ │ └── main/ │ │ │ ├── AndroidManifest.xml │ │ │ ├── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ ├── MainActivity.java │ │ │ │ └── MainApplication.java │ │ │ └── res/ │ │ │ └── values/ │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ ├── build.gradle │ │ ├── gradle/ │ │ │ └── wrapper/ │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ │ ├── gradle.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ ├── keystores/ │ │ │ └── debug.keystore.properties │ │ └── settings.gradle │ ├── app.json │ ├── components/ │ │ ├── CustomShape.js │ │ ├── CustomText.js │ │ └── Heart.js │ ├── index.js │ ├── ios/ │ │ ├── example/ │ │ │ ├── AppDelegate.h │ │ │ ├── AppDelegate.m │ │ │ ├── Base.lproj/ │ │ │ │ └── LaunchScreen.xib │ │ │ ├── Images.xcassets/ │ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ │ └── Contents.json │ │ │ │ └── Contents.json │ │ │ ├── Info.plist │ │ │ └── main.m │ │ ├── example-tvOS/ │ │ │ └── Info.plist │ │ └── example.xcodeproj/ │ │ ├── project.pbxproj │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ ├── example-tvOS.xcscheme │ │ └── example.xcscheme │ └── metro.config.js ├── index.d.ts ├── ios/ │ ├── ART.xcodeproj/ │ │ └── project.pbxproj │ ├── ARTCGFloatArray.h │ ├── ARTContainer.h │ ├── ARTGroup.h │ ├── ARTGroup.m │ ├── ARTNode.h │ ├── ARTNode.m │ ├── ARTRenderable.h │ ├── ARTRenderable.m │ ├── ARTShadow.h │ ├── ARTShape.h │ ├── ARTShape.m │ ├── ARTSurfaceView.h │ ├── ARTSurfaceView.m │ ├── ARTText.h │ ├── ARTText.m │ ├── ARTTextFrame.h │ ├── Brushes/ │ │ ├── ARTBrush.h │ │ ├── ARTBrush.m │ │ ├── ARTLinearGradient.h │ │ ├── ARTLinearGradient.m │ │ ├── ARTPattern.h │ │ ├── ARTPattern.m │ │ ├── ARTRadialGradient.h │ │ ├── ARTRadialGradient.m │ │ ├── ARTSolidColor.h │ │ └── ARTSolidColor.m │ ├── RCTConvert+ART.h │ ├── RCTConvert+ART.m │ └── ViewManagers/ │ ├── ARTGroupManager.h │ ├── ARTGroupManager.m │ ├── ARTNodeManager.h │ ├── ARTNodeManager.m │ ├── ARTRenderableManager.h │ ├── ARTRenderableManager.m │ ├── ARTShapeManager.h │ ├── ARTShapeManager.m │ ├── ARTSurfaceViewManager.h │ ├── ARTSurfaceViewManager.m │ ├── ARTTextManager.h │ └── ARTTextManager.m ├── jest.config.js ├── lib/ │ ├── ARTSerializablePath.js │ ├── ClippingRectangle.js │ ├── Group.js │ ├── LinearGradient.js │ ├── Pattern.js │ ├── RadialGradient.js │ ├── Shape.js │ ├── Surface.js │ ├── Text.js │ ├── __tests__/ │ │ └── helpers.test.js │ ├── helpers.js │ ├── index.js │ ├── nativeComponents.js │ └── types.js └── package.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .circleci/config.yml ================================================ version: 2.1 orbs: rn: react-native-community/react-native@1.1.0 jobs: checkout_code: executor: rn/linux_js steps: - checkout - persist_to_workspace: root: . paths: . analyse: executor: rn/linux_js steps: - attach_workspace: at: . - rn/yarn_install - run: name: Lint JS Code (ESLint) command: yarn lint - run: name: Flow command: yarn flow-check - run: name: Unit Tests command: yarn test workflows: test: jobs: - checkout_code - analyse: requires: - checkout_code ================================================ FILE: .eslintrc.js ================================================ module.exports = { extends: ['@react-native-community'], env: { jest: true } }; ================================================ FILE: .flowconfig ================================================ [ignore] ; We fork some components by platform .*/*[.]android.js ; Ignore "BUCK" generated dirs /\.buckd/ ; Ignore unexpected extra "@providesModule" .*/node_modules/.*/node_modules/fbjs/.* ; Ignore duplicate module providers ; For RN Apps installed via npm, "Libraries" folder is inside ; "node_modules/react-native" but in the source repo it is in the root .*/Libraries/react-native/React.js ; Ignore polyfills .*/Libraries/polyfills/.* ; Ignore metro .*/node_modules/metro/.* [include] [libs] node_modules/react-native/Libraries/react-native/react-native-interface.js node_modules/react-native/flow/ [options] emoji=true esproposal.optional_chaining=enable esproposal.nullish_coalescing=enable module.system=haste module.system.haste.use_name_reducers=true # get basename module.system.haste.name_reducers='^.*/\([a-zA-Z0-9$_.-]+\.js\(\.flow\)?\)$' -> '\1' # strip .js or .js.flow suffix module.system.haste.name_reducers='^\(.*\)\.js\(\.flow\)?$' -> '\1' # strip .ios suffix module.system.haste.name_reducers='^\(.*\)\.ios$' -> '\1' module.system.haste.name_reducers='^\(.*\)\.android$' -> '\1' module.system.haste.name_reducers='^\(.*\)\.native$' -> '\1' module.system.haste.paths.blacklist=.*/__tests__/.* module.system.haste.paths.blacklist=.*/__mocks__/.* module.system.haste.paths.blacklist=/node_modules/react-native/Libraries/Animated/src/polyfills/.* module.system.haste.paths.whitelist=/node_modules/react-native/Libraries/.* munge_underscores=true module.name_mapper='\(@react-native-community/art\)' -> '/lib/index.js' module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub' module.file_ext=.js module.file_ext=.jsx module.file_ext=.json module.file_ext=.native.js suppress_type=$FlowIssue suppress_type=$FlowFixMe suppress_type=$FlowFixMeProps suppress_type=$FlowFixMeState suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError [version] ^0.92.0 ================================================ FILE: .gitattributes ================================================ *.pbxproj -text ================================================ FILE: .gitignore ================================================ # OSX # .DS_Store # Xcode # build/ *.pbxuser !default.pbxuser *.mode1v3 !default.mode1v3 *.mode2v3 !default.mode2v3 *.perspectivev3 !default.perspectivev3 xcuserdata *.xccheckout *.moved-aside DerivedData *.hmap *.ipa *.xcuserstate project.xcworkspace # Android/IntelliJ # build/ .idea .gradle local.properties *.iml # node.js # node_modules/ npm-debug.log yarn-error.log # BUCK buck-out/ \.buckd/ *.keystore # fastlane # # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the # screenshots whenever they are needed. # For more information about the recommended setup visit: # https://docs.fastlane.tools/best-practices/source-control/ */fastlane/report.xml */fastlane/Preview.html */fastlane/screenshots # Bundle artifact *.jsbundle .eslintcache ================================================ FILE: .npmignore ================================================ .circleci .github example android/build ios/build ================================================ FILE: .prettierrc.js ================================================ module.exports = { singleQuote: true, trailingComma: 'all', bracketSpacing: false, jsxBracketSameLine: true, }; ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing to React Native ART ## Development Process All work on React Native ART happens directly on GitHub. Contributors send pull requests which go through review process. > **Working on your first pull request?** You can learn how from this _free_ series: [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github). 1. Fork the repo and create your branch from `master` (a guide on [how to fork a repository](https://help.github.com/articles/fork-a-repo/)). 2. Run `yarn` or `npm install` to install all required dependencies. 3. Now you are ready to do the changes. ## Testing your changes You can test your changes by installing `example` app on a simulator or device: Installing on iOS: - Run `yarn ios` or - Open `example/ios/example.xcodeproj` - Click `run` in the top left corner of `Xcode`. Installing on Android: - Connect Android Device or open Android Emulator - Run `yarn android` ## Typechecking, linting and testing Currently we use flow for typechecking, eslint with prettier for linting and formatting the code and jest for testing. - `yarn flow`: run flow - `yarn lint`: run eslint and prettier - `yarn test`: run unit tests ## Sending Pull Request When you're sending a pull request: - Prefer small pull requests focused on one change. - Verify that flow, eslint and all tests are passing. - Preview the documentation to make sure it looks good. - Follow the pull request template when opening a pull request. ## Reporting issues You can report issues on our [bug tracker](https://github.com/react-native-community/art/issues). Please follow the issue template when opening an issue. ## License By contributing to React Native ART, you agree that your contributions will be licensed under its **MIT** license. ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2019 react-native-community Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # **DEPRECATED** - This package is deprecated. If you need a similar package please consider using [react-native-svg](https://github.com/react-native-svg/react-native-svg). # `@react-native-community/art` [![CircleCI][circle-ci-badge]][circle-ci] ![MIT License][license-badge] [![PRs Welcome][pr-welcome-badge]][make-a-pr] ![Supports Android and iOS][support-badge] [![Lean Core Badge][lean-core-badge]][lean-core-issue] > _NOTE: ART was extracted from core `react-native` as a part of "[Lean Core](https://github.com/facebook/react-native/issues/23313)" effort._ React Native module that allows you to draw vector graphics # Getting started ## Installing module ```sh yarn add @react-native-community/art ``` or ```sh npm install @react-native-community/art --save ``` ## Linking module ### Mostly automatic linking For `react-native >= 0.60` ReactNativeART should be autolinked and no additional action is required. For `react-native < 0.60` you need to link ReactNative ART: ```js react-native link @react-native-community/art ``` ### Manual linking
Manually linking the library for iOS #### `Open project.xcodeproj in Xcode` Drag `RNCSlider.xcodeproj` to your project on Xcode (usually under the Libraries group on Xcode): ![xcode-add](https://facebook.github.io/react-native/docs/assets/AddToLibraries.png) #### Link `libART.a` binary with libraries Click on your main project file (the one that represents the `.xcodeproj`) select `Build Phases` and drag the static library from the `Products` folder inside the Library you are importing to `Link Binary With Libraries` (or use the `+` sign and choose library from the list): ![xcode-link](https://facebook.github.io/react-native/docs/assets/AddToBuildPhases.png)
Manually linking the library for Android #### `android/settings.gradle` ```groovy include ':react-native-art' project(':react-native-art').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/art/android') ``` #### `android/app/build.gradle` ```groovy dependencies { ... implementation project(':react-native-art') } ``` #### `android/app/src/main/.../MainApplication.java` On top, where imports are: ```java import com.reactnativecommunity.art.ARTPackage; ``` Add the `ARTPackage` class to your list of exported packages. ```java @Override protected List getPackages() { return Arrays.asList( new MainReactPackage(), new ARTPackage() ); } ```
# Migrating from the core `react-native` module To migrate to this module you need to follow all the installation instructions above and change your imports from: ```js import {ART} from 'react-native'; const {Surface, Shape} = ART; ``` to: ```js import {Surface, Shape} from '@react-native-community/art'; ``` # Documentation You can find API reference [here](https://github.com/react-native-community/art/tree/master/docs/api.md). ## Related - [react-native-svg](https://github.com/react-native-community/react-native-svg) - Render SVGs in any React project ## License The library is released under the MIT licence. For more information see `LICENSE`. [support-badge]:https://img.shields.io/badge/platforms-android%20|%20ios-lightgrey.svg?style=flat-square [make-a-pr]:http://makeapullrequest.com [pr-welcome-badge]:https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square [license-badge]:https://img.shields.io/npm/l/@react-native-community/slider.svg?style=flat-square [circle-ci]:https://circleci.com/gh/react-native-community/art [circle-ci-badge]: https://img.shields.io/circleci/project/github/react-native-community/art/master.svg?style=flat-square [lean-core-badge]: https://img.shields.io/badge/Lean%20Core-Extracted-brightgreen.svg?style=flat-square [lean-core-issue]: https://github.com/facebook/react-native/issues/23313 ================================================ FILE: ReactNativeART.podspec ================================================ # coding: utf-8 # Copyright (c) Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. require "json" package = JSON.parse(File.read(File.join(__dir__, "package.json"))) Pod::Spec.new do |s| s.name = "ReactNativeART" s.version = package['version'] s.summary = package['description'] s.license = package['license'] s.authors = package['author'] s.homepage = package['homepage'] s.platforms = { :ios => "9.0", :tvos => "9.2" } s.source = { :git => "https://github.com/react-native-community/art.git", :tag => "v#{s.version}" } s.source_files = "ios/**/*.{h,m}" s.dependency "React" end ================================================ FILE: android/.gitignore ================================================ /build ================================================ FILE: android/build.gradle ================================================ buildscript { repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.2.1' } } def getExtOrDefault(name) { return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['ReactNativeART_' + name] } def getExtOrIntegerDefault(name) { return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties['ReactNativeART_' + name]).toInteger() } apply plugin: 'com.android.library' android { compileSdkVersion getExtOrIntegerDefault('compileSdkVersion') buildToolsVersion getExtOrDefault('buildToolsVersion') defaultConfig { minSdkVersion getExtOrIntegerDefault('minSdkVersion') targetSdkVersion getExtOrIntegerDefault('targetSdkVersion') } } repositories { google() jcenter() mavenCentral() } allprojects { repositories { mavenLocal() google() jcenter() maven { url "$rootDir/../node_modules/react-native/android" } } } dependencies { //noinspection GradleDynamicVersion api 'com.facebook.react:react-native:+' } ================================================ FILE: android/gradle/wrapper/gradle-wrapper.properties ================================================ #Fri Jun 07 12:29:57 CEST 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip ================================================ FILE: android/gradle.properties ================================================ # Project-wide Gradle settings. # IDE (e.g. Android Studio) users: # Gradle settings configured through the IDE *will override* # any settings specified in this file. # For more details on how to configure your build environment visit # http://www.gradle.org/docs/current/userguide/build_environment.html # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. # Default value: -Xmx10248m -XX:MaxPermSize=256m # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true ReactNativeART_compileSdkVersion=28 ReactNativeART_buildToolsVersion=28.0.3 ReactNativeART_targetSdkVersion=27 ReactNativeART_minSdkVersion=16 ReactNativeART_supportLibVersion=28.0.0 ================================================ FILE: android/gradlew ================================================ #!/usr/bin/env sh ############################################################################## ## ## Gradle start up script for UN*X ## ############################################################################## # Attempt to set APP_HOME # Resolve links: $0 may be a link PRG="$0" # Need this for relative symlinks. while [ -h "$PRG" ] ; do ls=`ls -ld "$PRG"` link=`expr "$ls" : '.*-> \(.*\)$'` if expr "$link" : '/.*' > /dev/null; then PRG="$link" else PRG=`dirname "$PRG"`"/$link" fi done SAVED="`pwd`" cd "`dirname \"$PRG\"`/" >/dev/null APP_HOME="`pwd -P`" cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS="" # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" warn () { echo "$*" } die () { echo echo "$*" echo exit 1 } # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false case "`uname`" in CYGWIN* ) cygwin=true ;; Darwin* ) darwin=true ;; MINGW* ) msys=true ;; NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD="$JAVA_HOME/jre/sh/java" else JAVACMD="$JAVA_HOME/bin/java" fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD="java" which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi # Increase the maximum file descriptors if we can. if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then MAX_FD="$MAX_FD_LIMIT" fi ulimit -n $MAX_FD if [ $? -ne 0 ] ; then warn "Could not set maximum file descriptor limit: $MAX_FD" fi else warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" fi fi # For Darwin, add options to specify how the application appears in the dock if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi # For Cygwin, switch paths to Windows format before running java if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` SEP="" for dir in $ROOTDIRSRAW ; do ROOTDIRS="$ROOTDIRS$SEP$dir" SEP="|" done OURCYGPATTERN="(^($ROOTDIRS))" # Add a user-defined pattern to the cygpath arguments if [ "$GRADLE_CYGPATTERN" != "" ] ; then OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" fi # Now convert the arguments - kludge to limit ourselves to /bin/sh i=0 for arg in "$@" ; do CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` else eval `echo args$i`="\"$arg\"" fi i=$((i+1)) done case $i in (0) set -- ;; (1) set -- "$args0" ;; (2) set -- "$args0" "$args1" ;; (3) set -- "$args0" "$args1" "$args2" ;; (4) set -- "$args0" "$args1" "$args2" "$args3" ;; (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi # Escape application args save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } APP_ARGS=$(save "$@") # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then cd "$(dirname "$0")" fi exec "$JAVACMD" "$@" ================================================ FILE: android/gradlew.bat ================================================ @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @rem @rem ########################################################################## @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS= @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if "%ERRORLEVEL%" == "0" goto init echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto init echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :init @rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args :win9xME_args @rem Slurp the command line arguments. set CMD_LINE_ARGS= set _SKIP=2 :win9xME_args_slurp if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% :end @rem End local scope for the variables with windows NT shell if "%ERRORLEVEL%"=="0" goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 exit /b 1 :mainEnd if "%OS%"=="Windows_NT" endlocal :omega ================================================ FILE: android/proguard-rules.pro ================================================ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the # proguardFiles setting in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} # Uncomment this to preserve the line number information for # debugging stack traces. #-keepattributes SourceFile,LineNumberTable # If you keep the line number information, uncomment this to # hide the original source file name. #-renamesourcefileattribute SourceFile ================================================ FILE: android/src/main/AndroidManifest.xml ================================================ ================================================ FILE: android/src/main/java/com/reactnativecommunity/art/ARTGroupShadowNode.java ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ package com.reactnativecommunity.art; import javax.annotation.Nullable; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.Region; import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.ReactShadowNodeImpl; /** * Shadow node for virtual ARTGroup view */ public class ARTGroupShadowNode extends ARTVirtualNode { protected @Nullable RectF mClipping; public ARTGroupShadowNode() { } @ReactProp(name = "clipping") public void setClipping(@Nullable ReadableArray clippingDims) { float[] clippingData = PropHelper.toFloatArray(clippingDims); if (clippingData != null) { mClipping = createClipping(clippingData); markUpdated(); } } @Override public boolean isVirtual() { return true; } public void draw(Canvas canvas, Paint paint, float opacity) { opacity *= mOpacity; if (opacity > MIN_OPACITY_FOR_DRAW) { saveAndSetupCanvas(canvas); if (mClipping != null) { canvas.clipRect( mClipping.left * mScale, mClipping.top * mScale, mClipping.right * mScale, mClipping.bottom * mScale, Region.Op.REPLACE); } for (int i = 0; i < getChildCount(); i++) { ARTVirtualNode child = (ARTVirtualNode) getChildAt(i); child.draw(canvas, paint, opacity); child.markUpdateSeen(); } restoreCanvas(canvas); } } /** * Creates a {@link RectF} from an array of dimensions * (e.g. [x, y, width, height]) * * @param data the array of dimensions * @return the {@link RectF} that can used to clip the canvas */ private static RectF createClipping(float[] data) { if (data.length != 4) { throw new JSApplicationIllegalArgumentException( "Clipping should be array of length 4 (e.g. [x, y, width, height])"); } RectF clippingRect = new RectF( data[0], data[1], data[0] + data[2], data[1] + data[3]); return clippingRect; } } ================================================ FILE: android/src/main/java/com/reactnativecommunity/art/ARTGroupViewManager.java ================================================ // Copyright (c) Facebook, Inc. and its affiliates. // This source code is licensed under the MIT license found in the // LICENSE file in the root directory of this source tree. package com.reactnativecommunity.art; import com.facebook.react.module.annotations.ReactModule; /** * ViewManager for shadowed ART group views. */ @ReactModule(name = ARTRenderableViewManager.CLASS_GROUP) public class ARTGroupViewManager extends ARTRenderableViewManager { /* package */ ARTGroupViewManager() { super(CLASS_GROUP); } } ================================================ FILE: android/src/main/java/com/reactnativecommunity/art/ARTPackage.java ================================================ package com.reactnativecommunity.art; import java.util.Arrays; import java.util.Collections; import java.util.List; import com.facebook.react.ReactPackage; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.uimanager.ViewManager; import com.facebook.react.bridge.JavaScriptModule; public class ARTPackage implements ReactPackage { @Override public List createNativeModules(ReactApplicationContext reactContext) { return Collections.emptyList(); } // Deprecated from RN 0.47 public List> createJSModules() { return Collections.emptyList(); } @Override @SuppressWarnings("rawtypes") public List createViewManagers(ReactApplicationContext reactContext) { return Arrays.asList( ARTRenderableViewManager.createARTGroupViewManager(), ARTRenderableViewManager.createARTShapeViewManager(), ARTRenderableViewManager.createARTTextViewManager(), new ARTSurfaceViewManager() ); } } ================================================ FILE: android/src/main/java/com/reactnativecommunity/art/ARTRenderableViewManager.java ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ package com.reactnativecommunity.art; import android.view.View; import com.facebook.react.uimanager.ReactShadowNode; import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.ViewManager; /** * ViewManager for all shadowed ART views: Group, Shape and Text. Since these never get rendered * into native views and don't need any logic (all the logic is in {@link ARTSurfaceView}), this * "stubbed" ViewManager is used for all of them. */ public class ARTRenderableViewManager extends ViewManager { public static final String CLASS_GROUP = "ARTGroup"; public static final String CLASS_SHAPE = "ARTShape"; public static final String CLASS_TEXT = "ARTText"; private final String mClassName; public static ARTRenderableViewManager createARTGroupViewManager() { return new ARTGroupViewManager(); } public static ARTRenderableViewManager createARTShapeViewManager() { return new ARTShapeViewManager(); } public static ARTRenderableViewManager createARTTextViewManager() { return new ARTTextViewManager(); } /* package */ ARTRenderableViewManager(String className) { mClassName = className; } @Override public String getName() { return mClassName; } @Override public ReactShadowNode createShadowNodeInstance() { if (CLASS_GROUP.equals(mClassName)) { return new ARTGroupShadowNode(); } else if (CLASS_SHAPE.equals(mClassName)) { return new ARTShapeShadowNode(); } else if (CLASS_TEXT.equals(mClassName)) { return new ARTTextShadowNode(); } else { throw new IllegalStateException("Unexpected type " + mClassName); } } @Override public Class getShadowNodeClass() { if (CLASS_GROUP.equals(mClassName)) { return ARTGroupShadowNode.class; } else if (CLASS_SHAPE.equals(mClassName)) { return ARTShapeShadowNode.class; } else if (CLASS_TEXT.equals(mClassName)) { return ARTTextShadowNode.class; } else { throw new IllegalStateException("Unexpected type " + mClassName); } } @Override protected View createViewInstance(ThemedReactContext reactContext) { throw new IllegalStateException("ARTShape does not map into a native view"); } @Override public void updateExtraData(View root, Object extraData) { throw new IllegalStateException("ARTShape does not map into a native view"); } } ================================================ FILE: android/src/main/java/com/reactnativecommunity/art/ARTShapeShadowNode.java ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ package com.reactnativecommunity.art; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.DashPathEffect; import android.graphics.LinearGradient; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; import android.graphics.Shader; import com.facebook.common.logging.FLog; import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.common.ReactConstants; import com.facebook.react.uimanager.annotations.ReactProp; import javax.annotation.Nullable; import static com.facebook.react.common.ArrayUtils.copyArray; /** * Shadow node for virtual ARTShape view */ public class ARTShapeShadowNode extends ARTVirtualNode { private static final int CAP_BUTT = 0; private static final int CAP_ROUND = 1; private static final int CAP_SQUARE = 2; private static final int JOIN_BEVEL = 2; private static final int JOIN_MITER = 0; private static final int JOIN_ROUND = 1; private static final int PATH_TYPE_ARC = 4; private static final int PATH_TYPE_CLOSE = 1; private static final int PATH_TYPE_CURVETO = 3; private static final int PATH_TYPE_LINETO = 2; private static final int PATH_TYPE_MOVETO = 0; // For color type JS and ObjectiveC definitions counterparts // refer to ReactNativeART.js and RCTConvert+ART.m private static final int COLOR_TYPE_SOLID_COLOR = 0; private static final int COLOR_TYPE_LINEAR_GRADIENT = 1; private static final int COLOR_TYPE_RADIAL_GRADIENT = 2; private static final int COLOR_TYPE_PATTERN = 3; protected @Nullable Path mPath; private @Nullable String mStrokeColor; private @Nullable float[] mBrushData; private @Nullable float[] mStrokeDash; private float mStrokeWidth = 1; private int mStrokeCap = CAP_ROUND; private int mStrokeJoin = JOIN_ROUND; public ARTShapeShadowNode() { } @ReactProp(name = "d") public void setShapePath(@Nullable ReadableArray shapePath) { float[] pathData = PropHelper.toFloatArray(shapePath); mPath = createPath(pathData); markUpdated(); } @ReactProp(name = "stroke") public void setStroke(@Nullable String strokeColors) { mStrokeColor = strokeColors; markUpdated(); } @ReactProp(name = "strokeDash") public void setStrokeDash(@Nullable ReadableArray strokeDash) { mStrokeDash = PropHelper.toFloatArray(strokeDash); markUpdated(); } @ReactProp(name = "fill") public void setFill(@Nullable ReadableArray fillColors) { mBrushData = PropHelper.toFloatArray(fillColors); markUpdated(); } @ReactProp(name = "strokeWidth", defaultFloat = 1f) public void setStrokeWidth(float strokeWidth) { mStrokeWidth = strokeWidth; markUpdated(); } @ReactProp(name = "strokeCap", defaultInt = CAP_ROUND) public void setStrokeCap(int strokeCap) { mStrokeCap = strokeCap; markUpdated(); } @ReactProp(name = "strokeJoin", defaultInt = JOIN_ROUND) public void setStrokeJoin(int strokeJoin) { mStrokeJoin = strokeJoin; markUpdated(); } @Override public void draw(Canvas canvas, Paint paint, float opacity) { opacity *= mOpacity; if (opacity > MIN_OPACITY_FOR_DRAW) { saveAndSetupCanvas(canvas); if (mPath == null) { throw new JSApplicationIllegalArgumentException( "Shapes should have a valid path (d) prop"); } if (setupFillPaint(paint, opacity)) { canvas.drawPath(mPath, paint); } if (setupStrokePaint(paint, opacity)) { canvas.drawPath(mPath, paint); } restoreCanvas(canvas); } markUpdateSeen(); } /** * Sets up {@link #mPaint} according to the props set on a shadow view. Returns {@code true} * if the stroke should be drawn, {@code false} if not. */ protected boolean setupStrokePaint(Paint paint, float opacity) { if (mStrokeWidth == 0 || mStrokeColor == null) { return false; } paint.reset(); paint.setFlags(Paint.ANTI_ALIAS_FLAG); paint.setStyle(Paint.Style.STROKE); switch (mStrokeCap) { case CAP_BUTT: paint.setStrokeCap(Paint.Cap.BUTT); break; case CAP_SQUARE: paint.setStrokeCap(Paint.Cap.SQUARE); break; case CAP_ROUND: paint.setStrokeCap(Paint.Cap.ROUND); break; default: throw new JSApplicationIllegalArgumentException( "strokeCap " + mStrokeCap + " unrecognized"); } switch (mStrokeJoin) { case JOIN_MITER: paint.setStrokeJoin(Paint.Join.MITER); break; case JOIN_BEVEL: paint.setStrokeJoin(Paint.Join.BEVEL); break; case JOIN_ROUND: paint.setStrokeJoin(Paint.Join.ROUND); break; default: throw new JSApplicationIllegalArgumentException( "strokeJoin " + mStrokeJoin + " unrecognized"); } paint.setStrokeWidth(mStrokeWidth * mScale); paint.setColor(Color.parseColor(mStrokeColor)); if (mStrokeDash != null && mStrokeDash.length > 0) { paint.setPathEffect(new DashPathEffect(mStrokeDash, 0)); } if (mShadowOpacity > 0) { paint.setShadowLayer(mShadowRadius, mShadowOffsetX, mShadowOffsetY, mShadowColor); } return true; } /** * Sets up {@link #mPaint} according to the props set on a shadow view. Returns {@code true} * if the fill should be drawn, {@code false} if not. */ protected boolean setupFillPaint(Paint paint, float opacity) { if (mBrushData != null && mBrushData.length > 0) { paint.reset(); paint.setFlags(Paint.ANTI_ALIAS_FLAG); paint.setStyle(Paint.Style.FILL); int colorType = (int) mBrushData[0]; switch (colorType) { case COLOR_TYPE_SOLID_COLOR: paint.setARGB( (int) (mBrushData.length > 4 ? mBrushData[4] * opacity * 255 : opacity * 255), (int) (mBrushData[1] * 255), (int) (mBrushData[2] * 255), (int) (mBrushData[3] * 255)); break; case COLOR_TYPE_LINEAR_GRADIENT: // For mBrushData format refer to LinearGradient and insertColorStopsIntoArray functions in ReactNativeART.js if (mBrushData.length < 5) { FLog.w(ReactConstants.TAG, "[ARTShapeShadowNode setupFillPaint] expects 5 elements, received " + mBrushData.length); return false; } float gradientStartX = mBrushData[1] * mScale; float gradientStartY = mBrushData[2] * mScale; float gradientEndX = mBrushData[3] * mScale; float gradientEndY = mBrushData[4] * mScale; int stops = (mBrushData.length - 5) / 5; int[] colors = null; float[] positions = null; if (stops > 0) { colors = new int[stops]; positions = new float[stops]; for (int i=0; i 0) { paint.setShadowLayer(mShadowRadius, mShadowOffsetX, mShadowOffsetY, mShadowColor); } return true; } return false; } /** * Returns the floor modulus of the float arguments. Java modulus will return a negative remainder * when the divisor is negative. Modulus should always be positive. This mimics the behavior of * Math.floorMod, introduced in Java 8. */ private float modulus(float x, float y) { float remainder = x % y; float modulus = remainder; if (remainder < 0) { modulus += y; } return modulus; } /** * Creates a {@link Path} from an array of instructions constructed by JS * (see ARTSerializablePath.js). Each instruction starts with a type (see PATH_TYPE_*) followed * by arguments for that instruction. For example, to create a line the instruction will be * 2 (PATH_LINE_TO), x, y. This will draw a line from the last draw point (or 0,0) to x,y. * * @param data the array of instructions * @return the {@link Path} that can be drawn to a canvas */ private Path createPath(float[] data) { Path path = new Path(); path.moveTo(0, 0); int i = 0; while (i < data.length) { int type = (int) data[i++]; switch (type) { case PATH_TYPE_MOVETO: path.moveTo(data[i++] * mScale, data[i++] * mScale); break; case PATH_TYPE_CLOSE: path.close(); break; case PATH_TYPE_LINETO: path.lineTo(data[i++] * mScale, data[i++] * mScale); break; case PATH_TYPE_CURVETO: path.cubicTo( data[i++] * mScale, data[i++] * mScale, data[i++] * mScale, data[i++] * mScale, data[i++] * mScale, data[i++] * mScale); break; case PATH_TYPE_ARC: { float x = data[i++] * mScale; float y = data[i++] * mScale; float r = data[i++] * mScale; float start = (float) Math.toDegrees(data[i++]); float end = (float) Math.toDegrees(data[i++]); boolean counterClockwise = !(data[i++] == 1f); float sweep = end - start; if (Math.abs(sweep) >= 360) { path.addCircle(x, y, r, counterClockwise ? Path.Direction.CCW : Path.Direction.CW); } else { sweep = modulus(sweep, 360); if (counterClockwise && sweep < 360) { // Counter-clockwise sweeps are negative sweep = -1 * (360 - sweep); } RectF oval = new RectF(x - r, y - r, x + r, y + r); path.arcTo(oval, start, sweep); } break; } default: throw new JSApplicationIllegalArgumentException( "Unrecognized drawing instruction " + type); } } return path; } } ================================================ FILE: android/src/main/java/com/reactnativecommunity/art/ARTShapeViewManager.java ================================================ // Copyright (c) Facebook, Inc. and its affiliates. // This source code is licensed under the MIT license found in the // LICENSE file in the root directory of this source tree. package com.reactnativecommunity.art; import com.facebook.react.module.annotations.ReactModule; /** * ViewManager for shadowed ART shape views. */ @ReactModule(name = ARTRenderableViewManager.CLASS_SHAPE) public class ARTShapeViewManager extends ARTRenderableViewManager { /* package */ ARTShapeViewManager() { super(CLASS_SHAPE); } } ================================================ FILE: android/src/main/java/com/reactnativecommunity/art/ARTSurfaceView.java ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ package com.reactnativecommunity.art; import android.content.Context; import android.view.TextureView; /** * Custom {@link View} implementation that draws an ARTSurface React view and its children. */ public class ARTSurfaceView extends TextureView { public ARTSurfaceView(Context context) { super(context); setOpaque(false); } } ================================================ FILE: android/src/main/java/com/reactnativecommunity/art/ARTSurfaceViewManager.java ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ package com.reactnativecommunity.art; import com.facebook.yoga.YogaMeasureMode; import com.facebook.yoga.YogaMeasureFunction; import com.facebook.yoga.YogaNode; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.uimanager.BaseViewManager; import com.facebook.react.uimanager.ThemedReactContext; /** * ViewManager for ARTSurfaceView React views. Renders as a {@link ARTSurfaceView} and handles * invalidating the native view on shadow view updates happening in the underlying tree. */ @ReactModule(name = ARTSurfaceViewManager.REACT_CLASS) public class ARTSurfaceViewManager extends BaseViewManager { public static final String REACT_CLASS = "ARTSurfaceView"; private static final YogaMeasureFunction MEASURE_FUNCTION = new YogaMeasureFunction() { @Override public long measure( YogaNode node, float width, YogaMeasureMode widthMode, float height, YogaMeasureMode heightMode) { throw new IllegalStateException("SurfaceView should have explicit width and height set"); } }; @Override public String getName() { return REACT_CLASS; } @Override public ARTSurfaceViewShadowNode createShadowNodeInstance() { ARTSurfaceViewShadowNode node = new ARTSurfaceViewShadowNode(); node.setMeasureFunction(MEASURE_FUNCTION); return node; } @Override public Class getShadowNodeClass() { return ARTSurfaceViewShadowNode.class; } @Override protected ARTSurfaceView createViewInstance(ThemedReactContext reactContext) { return new ARTSurfaceView(reactContext); } @Override public void updateExtraData(ARTSurfaceView root, Object extraData) { ARTSurfaceViewShadowNode shadowNode = (ARTSurfaceViewShadowNode) extraData; shadowNode.setupSurfaceTextureListener(root); } @Override public void setBackgroundColor(ARTSurfaceView view, int backgroundColor) { // As of Android N TextureView does not support calling setBackground on it. // It will also throw an exception when target SDK is set to N or higher. // Setting the background color for this view is handled in the shadow node. } } ================================================ FILE: android/src/main/java/com/reactnativecommunity/art/ARTSurfaceViewShadowNode.java ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ package com.reactnativecommunity.art; import javax.annotation.Nullable; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Color; import android.view.Surface; import android.graphics.PorterDuff; import android.graphics.SurfaceTexture; import android.view.TextureView; import android.os.Build; import com.facebook.common.logging.FLog; import com.facebook.react.common.ReactConstants; import com.facebook.react.uimanager.LayoutShadowNode; import com.facebook.react.uimanager.UIViewOperationQueue; import com.facebook.react.uimanager.ReactShadowNode; import com.facebook.react.uimanager.ViewProps; import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.bridge.LifecycleEventListener; /** * Shadow node for ART virtual tree root - ARTSurfaceView */ public class ARTSurfaceViewShadowNode extends LayoutShadowNode implements TextureView.SurfaceTextureListener, LifecycleEventListener { private @Nullable Surface mSurface; private @Nullable Integer mBackgroundColor; @ReactProp(name = ViewProps.BACKGROUND_COLOR, customType = "Color") public void setBackgroundColor(Integer color) { mBackgroundColor = color; markUpdated(); } @Override public boolean isVirtual() { return false; } @Override public boolean isVirtualAnchor() { return true; } @Override public void onCollectExtraUpdates(UIViewOperationQueue uiUpdater) { super.onCollectExtraUpdates(uiUpdater); drawOutput(false); uiUpdater.enqueueUpdateExtraData(getReactTag(), this); } private void drawOutput(boolean markAsUpdated) { if (mSurface == null || !mSurface.isValid()) { markChildrenUpdatesSeen(this); return; } try { Canvas canvas = mSurface.lockCanvas(null); canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); if (mBackgroundColor != null) { canvas.drawColor(mBackgroundColor); } Paint paint = new Paint(); for (int i = 0; i < getChildCount(); i++) { ARTVirtualNode child = (ARTVirtualNode) getChildAt(i); child.draw(canvas, paint, 1f); if (markAsUpdated) { child.markUpdated(); } else { child.markUpdateSeen(); } } if (mSurface == null) { return; } mSurface.unlockCanvasAndPost(canvas); } catch (IllegalArgumentException | IllegalStateException e) { FLog.e(ReactConstants.TAG, e.getClass().getSimpleName() + " in Surface.unlockCanvasAndPost"); } } public void setupSurfaceTextureListener(ARTSurfaceView surfaceView) { SurfaceTexture surface = surfaceView.getSurfaceTexture(); surfaceView.setSurfaceTextureListener(this); if (surface != null && mSurface == null) { mSurface = new Surface(surface); drawOutput(true); } } private void markChildrenUpdatesSeen(ReactShadowNode shadowNode) { for (int i = 0; i < shadowNode.getChildCount(); i++) { ReactShadowNode child = shadowNode.getChildAt(i); child.markUpdateSeen(); markChildrenUpdatesSeen(child); } } @Override public void setThemedContext(ThemedReactContext themedContext) { super.setThemedContext(themedContext); if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) { themedContext.addLifecycleEventListener(this); } } @Override public void dispose() { super.dispose(); if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) { getThemedContext().removeLifecycleEventListener(this); } } @Override public void onHostResume() { drawOutput(false); } @Override public void onHostPause() {} @Override public void onHostDestroy() {} @Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { mSurface = new Surface(surface); drawOutput(false); } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { mSurface.release(); mSurface = null; return true; } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {} @Override public void onSurfaceTextureUpdated(SurfaceTexture surface) {} } ================================================ FILE: android/src/main/java/com/reactnativecommunity/art/ARTTextShadowNode.java ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ package com.reactnativecommunity.art; import javax.annotation.Nullable; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Typeface; import android.text.TextUtils; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.uimanager.annotations.ReactProp; /** * Shadow node for virtual ARTText view */ public class ARTTextShadowNode extends ARTShapeShadowNode { private static final String PROP_LINES = "lines"; private static final String PROP_FONT = "font"; private static final String PROP_FONT_FAMILY = "fontFamily"; private static final String PROP_FONT_SIZE = "fontSize"; private static final String PROP_FONT_STYLE = "fontStyle"; private static final String PROP_FONT_WEIGHT = "fontWeight"; private static final int DEFAULT_FONT_SIZE = 12; private static final int TEXT_ALIGNMENT_CENTER = 2; private static final int TEXT_ALIGNMENT_LEFT = 0; private static final int TEXT_ALIGNMENT_RIGHT = 1; private @Nullable ReadableMap mFrame; private int mTextAlignment = TEXT_ALIGNMENT_LEFT; public ARTTextShadowNode() { } @ReactProp(name = "frame") public void setFrame(@Nullable ReadableMap frame) { mFrame = frame; } @ReactProp(name = "alignment", defaultInt = TEXT_ALIGNMENT_LEFT) public void setAlignment(int alignment) { mTextAlignment = alignment; } @Override public void draw(Canvas canvas, Paint paint, float opacity) { if (mFrame == null) { return; } opacity *= mOpacity; if (opacity <= MIN_OPACITY_FOR_DRAW) { return; } if (!mFrame.hasKey(PROP_LINES)) { return; } ReadableArray linesProp = mFrame.getArray(PROP_LINES); if (linesProp == null || linesProp.size() == 0) { return; } // only set up the canvas if we have something to draw saveAndSetupCanvas(canvas); String[] lines = new String[linesProp.size()]; for (int i = 0; i < lines.length; i++) { lines[i] = linesProp.getString(i); } String text = TextUtils.join("\n", lines); if (setupStrokePaint(paint, opacity)) { applyTextPropertiesToPaint(paint); if (mPath == null) { canvas.drawText(text, 0, -paint.ascent(), paint); } else { canvas.drawTextOnPath(text, mPath, 0, 0, paint); } } if (setupFillPaint(paint, opacity)) { applyTextPropertiesToPaint(paint); if (mPath == null) { canvas.drawText(text, 0, -paint.ascent(), paint); } else { canvas.drawTextOnPath(text, mPath, 0, 0, paint); } } if (mShadowOpacity > 0) { paint.setShadowLayer(mShadowRadius, mShadowOffsetX, mShadowOffsetY, mShadowColor); } restoreCanvas(canvas); markUpdateSeen(); } private void applyTextPropertiesToPaint(Paint paint) { int alignment = mTextAlignment; switch (alignment) { case TEXT_ALIGNMENT_LEFT: paint.setTextAlign(Paint.Align.LEFT); break; case TEXT_ALIGNMENT_RIGHT: paint.setTextAlign(Paint.Align.RIGHT); break; case TEXT_ALIGNMENT_CENTER: paint.setTextAlign(Paint.Align.CENTER); break; } if (mFrame != null) { if (mFrame.hasKey(PROP_FONT)) { ReadableMap font = mFrame.getMap(PROP_FONT); if (font != null) { float fontSize = DEFAULT_FONT_SIZE; if (font.hasKey(PROP_FONT_SIZE)) { fontSize = (float) font.getDouble(PROP_FONT_SIZE); } paint.setTextSize(fontSize * mScale); boolean isBold = font.hasKey(PROP_FONT_WEIGHT) && "bold".equals(font.getString(PROP_FONT_WEIGHT)); boolean isItalic = font.hasKey(PROP_FONT_STYLE) && "italic".equals(font.getString(PROP_FONT_STYLE)); int fontStyle; if (isBold && isItalic) { fontStyle = Typeface.BOLD_ITALIC; } else if (isBold) { fontStyle = Typeface.BOLD; } else if (isItalic) { fontStyle = Typeface.ITALIC; } else { fontStyle = Typeface.NORMAL; } // NB: if the font family is null / unsupported, the default one will be used paint.setTypeface(Typeface.create(font.getString(PROP_FONT_FAMILY), fontStyle)); } } } } } ================================================ FILE: android/src/main/java/com/reactnativecommunity/art/ARTTextViewManager.java ================================================ // Copyright (c) Facebook, Inc. and its affiliates. // This source code is licensed under the MIT license found in the // LICENSE file in the root directory of this source tree. package com.reactnativecommunity.art; import com.facebook.react.module.annotations.ReactModule; /** * ViewManager for shadowed ART text views. */ @ReactModule(name = ARTRenderableViewManager.CLASS_TEXT) public class ARTTextViewManager extends ARTRenderableViewManager { /* package */ ARTTextViewManager() { super(CLASS_TEXT); } } ================================================ FILE: android/src/main/java/com/reactnativecommunity/art/ARTVirtualNode.java ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ package com.reactnativecommunity.art; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import androidx.core.graphics.ColorUtils; import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.uimanager.DisplayMetricsHolder; import com.facebook.react.uimanager.ReactShadowNodeImpl; import com.facebook.react.uimanager.annotations.ReactProp; import javax.annotation.Nullable; /** * Base class for ARTView virtual nodes: {@link ARTGroupShadowNode}, {@link ARTShapeShadowNode} and * indirectly for {@link ARTTextShadowNode}. */ public abstract class ARTVirtualNode extends ReactShadowNodeImpl { protected static final float MIN_OPACITY_FOR_DRAW = 0.01f; private static final float[] sMatrixData = new float[9]; private static final float[] sRawMatrix = new float[9]; protected float mOpacity = 1f; private @Nullable Matrix mMatrix = new Matrix(); protected int mShadowColor = 0; protected float mShadowOpacity = 1; protected float mShadowRadius = 0; protected float mShadowOffsetX = 0; protected float mShadowOffsetY = 0; protected final float mScale; public ARTVirtualNode() { mScale = DisplayMetricsHolder.getWindowDisplayMetrics().density; } @Override public boolean isVirtual() { return true; } public abstract void draw(Canvas canvas, Paint paint, float opacity); /** * Sets up the transform matrix on the canvas before an element is drawn. * * NB: for perf reasons this does not apply opacity, as that would mean creating a new canvas * layer (which allocates an offscreen bitmap) and having it composited afterwards. Instead, the * drawing code should apply opacity recursively. * * @param canvas the canvas to set up */ protected final void saveAndSetupCanvas(Canvas canvas) { canvas.save(); if (mMatrix != null) { canvas.concat(mMatrix); } } /** * Restore the canvas after an element was drawn. This is always called in mirror with * {@link #saveAndSetupCanvas}. * * @param canvas the canvas to restore */ protected void restoreCanvas(Canvas canvas) { canvas.restore(); } @ReactProp(name = "opacity", defaultFloat = 1f) public void setOpacity(float opacity) { mOpacity = opacity; markUpdated(); } @ReactProp(name = "transform") public void setTransform(@Nullable ReadableArray transformArray) { if (transformArray != null) { int matrixSize = PropHelper.toFloatArray(transformArray, sMatrixData); if (matrixSize == 6) { setupMatrix(); } else if (matrixSize != -1) { throw new JSApplicationIllegalArgumentException("Transform matrices must be of size 6"); } } else { mMatrix = null; } markUpdated(); } @ReactProp(name = "shadow") public void setShadow(@Nullable ReadableArray shadowArray) { if (shadowArray != null) { mShadowOpacity = (float)shadowArray.getDouble(1); mShadowRadius = (float)shadowArray.getDouble(2); mShadowOffsetX = (float)shadowArray.getDouble(3); mShadowOffsetY = (float)shadowArray.getDouble(4); int color = shadowArray.getInt(0); if (mShadowOpacity < 1) { color = ColorUtils.setAlphaComponent(color, (int)(mShadowOpacity * 255)); } mShadowColor = color; } else { mShadowColor = 0; mShadowOpacity = 0; mShadowRadius = 0; mShadowOffsetX = 0; mShadowOffsetY = 0; } markUpdated(); } protected void setupMatrix() { sRawMatrix[0] = sMatrixData[0]; sRawMatrix[1] = sMatrixData[2]; sRawMatrix[2] = sMatrixData[4] * mScale; sRawMatrix[3] = sMatrixData[1]; sRawMatrix[4] = sMatrixData[3]; sRawMatrix[5] = sMatrixData[5] * mScale; sRawMatrix[6] = 0; sRawMatrix[7] = 0; sRawMatrix[8] = 1; if (mMatrix == null) { mMatrix = new Matrix(); } mMatrix.setValues(sRawMatrix); } } ================================================ FILE: android/src/main/java/com/reactnativecommunity/art/PropHelper.java ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ package com.reactnativecommunity.art; import javax.annotation.Nullable; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.uimanager.ReactStylesDiffMap; /** * Contains static helper methods for accessing props. */ /* package */ class PropHelper { /** * Converts {@link ReadableArray} to an array of {@code float}. Returns newly created array. * * @return a {@code float[]} if converted successfully, or {@code null} if {@param value} was * {@code null}. */ /*package*/ static @Nullable float[] toFloatArray(@Nullable ReadableArray value) { if (value != null) { float[] result = new float[value.size()]; toFloatArray(value, result); return result; } return null; } /** * Converts given {@link ReadableArray} to an array of {@code float}. Writes result to the array * passed in {@param into}. This method will write to the output array up to the number of items * from the input array. If the input array is longer than output the remaining part of the input * will not be converted. * * @param value input array * @param into output array * @return number of items copied from input to the output array */ /*package*/ static int toFloatArray(ReadableArray value, float[] into) { int length = value.size() > into.length ? into.length : value.size(); for (int i = 0; i < length; i++) { into[i] = (float) value.getDouble(i); } return value.size(); } } ================================================ FILE: android/src/main/res/values/strings.xml ================================================ ReactNativeART ================================================ FILE: babel.config.js ================================================ module.exports = { presets: ['module:metro-react-native-babel-preset'], }; ================================================ FILE: docs/api.md ================================================ # API ## Surface Container for all other ART components | Prop | Type | Default | | :------: | :----------: | :-----: | | height | `number` | `0` | | width | `number` | `0` | | style | `any` | --- | | children | `React.Node` | --- | ```jsx import {Surface} from '@react-native-community/art'; function Heart() { return ( {renderARTShapes()} ); } ``` ## Group Container to combine shapes or other groups into hierarchies that can be transformed as a set. | Prop | Type | Default | | :---------------: | :-----------------------------------: | :-----: | | ...opacityProps | [`OpacityProps`](###OpacityProps) | --- | | ...transformProps | [`TransformProps`](###TransformProps) | --- | | ...shadowProps | [`ShadowProps`](###ShadowProps) | --- | | children | `React.Node` | --- | ```jsx import {Surface, Group} from '@react-native-community/art'; function GrouppedHearts() { return ( {renderARTGroupContents()} ); } ``` ## Shape Used to draw arbitrary vector shapes from Path. Shape implements Transform as a mixin which means it has all transform methods available for moving, scaling and rotating a shape. | Prop | Type | Default | | :---------------: | :-----------------------------------: | :-------: | | ...opacityProps | [`OpacityProps`](###OpacityProps) | --- | | ...transformProps | [`TransformProps`](###TransformProps) | --- | | ...shadowProps | [`ShadowProps`](###ShadowProps) | --- | | fill | `string \| Brush` | --- | | stroke | `string` | --- | | strokeCap | `'butt' \| 'square' \| 'round'` | `'round'` | | strokeDash | `Array` | --- | | strokeJoin | `'miter' \| 'bevel' \| 'round'` | `'round'` | | strokeWidth | `number` | `1` | | d | `string \| Path` | --- | | width | `number` | `0` | | height | `number` | `0` | | children | `React.Node` | --- | ```jsx import {Surface, Shape, Path} from '@react-native-community/art'; function SomeShape() { return ( ); } ``` ## Text Text component creates a shape based on text content using native text rendering. | Prop | Type | Default | | :---------------: | :-----------------------------------: | :-------: | | ...opacityProps | [`OpacityProps`](###OpacityProps) | --- | | ...transformProps | [`TransformProps`](###TransformProps) | --- | | ...shadowProps | [`ShadowProps`](###ShadowProps) | --- | | fill | `string \| Brush` | --- | | stroke | `string` | --- | | strokeCap | `'butt' \| 'square' \| 'round'` | `'round'` | | strokeDash | `Array` | --- | | strokeJoin | `'miter' \| 'bevel' \| 'round'` | `'round'` | | strokeWidth | `number` | `1` | | width | `number` | `0` | | height | `number` | `0` | | alignment | `'center' \| 'left' \| 'right'` | `'left'` | | font | `string \| Font` | --- | | path | `string \| Path` | --- | | children | `string \| Array` | --- | ## Path Generate an SVG `path` that you can pass to the `Shape` element. ### `constructor` ```jsx new Path(path: string | Path) ``` ### `move` Move current context from current position by `x` and `y`. ```jsx function move(x: number, y: number): Path; ``` ### `moveTo` Move current context from current position to absolute coordinate `x` and `y`. ```jsx function moveTo(x: number, y: number): Path; ``` ### `line` Draw a line from current position to relative `x` and `y`. ```jsx function line(x: number, y: number): Path; ``` ### `lineTo` Draw a line from current poistion to absolute coordinate `x` and `y`. ```jsx function lineTo(x: number, y: number): Path; ``` ### `curve` Draw a cubic bezier curve to relative position. ```jsx function curve( x1: number, y1: number, x2: number, y2: number, deltaX: number, deltaY: number, ): Path; ``` ### `curveTo` Draw a bezier curve to absolute position. ```jsx function curveTo( x1: number, y1: number, x2: number, y2: number, deltaX: number, deltaY: number, ): Path ``` ### `arc` Draw an arc with specific arguments. ```jsx function arc( x: number, y: number, xRadius: number, yRadius: number, outer?: boolean, counterClockWise?: boolean, rotation?: number, ): Path; ``` ### `arcTo` Draw an arc to absolute coordinates. ```jsx function arcTo( x: number, y: number, xRadius: number, yRadius: number, outer?: boolean, counterClockWise?: boolean, rotation?: number, ): Path; ``` ### `counterArc` Same as `arc`, opposite clockwise. ### `counterArcTo` Same as `arcTo`, opposite clockwise. ### `close` Draws a line to the first point in the current sub-path and begins a new sub-path. ```jsx function close(): Path; ``` ### `reset` Reset the current path. ```jsx function reset(): Path; ``` ### `toJSON` Return the current path points, which can be used on Shape d attribute. ```jsx function toJSON() => Array; ``` ## LinearGradient Creates a linear gradient fill. ```jsx function LinearGradient({ stops: GradientStops, x1?: number, y1?: number, x2?: number, y2?: number, }): Brush; ``` ## RadialGradient Creates a radial gradient fill. ```jsx function RadialGradient({ stops: GradientStops, x1?: number, y1?: number, x2?: number, y2?: number, }): Brush; ``` ## Pattern Creates a pattern fill. > _This component is not exactly working as expected. [More context here.](https://github.com/facebook/react-native/issues/1462)_ ```jsx function Pattern( url: number | string, width: number, height: number, left?: number, top?: number, ): Brush; ``` ## Transform Generate a transform that can applied to ART elements. [Transform docs](https://github.com/sebmarkbage/art/blob/842d2d56c6436adc0bbb0c065a296f295b95bc0a/docs/ART/ART.Transform.md) ## ClippingRectangle Control display area of graphic. | Prop | Type | Default | | :-------------: | :------------: | :-----: | | ...opacityProps | `OpacityProps` | --- | | x | `number` | `0` | | y | `number` | `0` | | width | `number` | `0` | | height | `number` | `0` | | children | `React.Node` | --- | ```jsx import React from 'react'; import { Surface, ClippingRectangle, Shape, Path, } from '@react-native-community/art'; function Component() { return ( ); } ``` ## Common types ### OpacityProps | Prop | Type | Default | | :-----: | :-------: | :-----: | | visible | `boolean` | `true` | | opacity | `number` | --- | ### TransformObject | Prop | Type | Default | | :--: | :------: | :-----: | | y | `number` | `0` | | x | `number` | `0` | | yy | `number` | `1` | | xx | `number` | `1` | | yx | `number` | `0` | | xy | `number` | `0` | ### TransformProps | Prop | Type | Default | | :-------: | :---------------: | :-----: | | scaleX | `number` | `1` | | scaleY | `number` | `1` | | scale | `number` | --- | | x | `number` | `0` | | y | `number` | `0` | | rotation | `number` | `0` | | originX | `number` | --- | | originY | `number` | --- | | transform | `TransformObject` | --- | ### ShadowProps | Prop | Type | Default | | :-----------: | :------------------: | :------: | | shadowOpacity | `number` | `1` | | shadowColor | `string` | `black` | | shadowRadius | `number` | `0` | | shadowOffset | `ShadowOffsetObject` | --- | ### ShadowOffsetObject | Prop | Type | Default | | :--: | :------: | :-----: | | y | `number` | `0` | | x | `number` | `0` | ### Font | Prop | Type | Default | | :--------: | :------: | :-----: | | fontFamily | `string` | --- | | fontSize | `number` | `12` | | fontWeight | `string` | `'400'` | | fontStyle | `string` | --- | ================================================ FILE: example/App.js ================================================ // @flow import React from 'react'; import {StyleSheet, ScrollView, SafeAreaView} from 'react-native'; import Heart from './components/Heart'; import CustomShape from './components/CustomShape'; import CustomText from './components/CustomText'; export default function App() { return ( ); } const styles = StyleSheet.create({ container: { flexGrow: 1, backgroundColor: '#F5FCFF', }, }); ================================================ FILE: example/android/app/build.gradle ================================================ apply plugin: "com.android.application" import com.android.build.OutputFile /** * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets * and bundleReleaseJsAndAssets). * These basically call `react-native bundle` with the correct arguments during the Android build * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the * bundle directly from the development server. Below you can see all the possible configurations * and their defaults. If you decide to add a configuration block, make sure to add it before the * `apply from: "../../node_modules/react-native/react.gradle"` line. * * project.ext.react = [ * // the name of the generated asset file containing your JS bundle * bundleAssetName: "index.android.bundle", * * // the entry file for bundle generation * entryFile: "index.android.js", * * // whether to bundle JS and assets in debug mode * bundleInDebug: false, * * // whether to bundle JS and assets in release mode * bundleInRelease: true, * * // whether to bundle JS and assets in another build variant (if configured). * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants * // The configuration property can be in the following formats * // 'bundleIn${productFlavor}${buildType}' * // 'bundleIn${buildType}' * // bundleInFreeDebug: true, * // bundleInPaidRelease: true, * // bundleInBeta: true, * * // whether to disable dev mode in custom build variants (by default only disabled in release) * // for example: to disable dev mode in the staging build type (if configured) * devDisabledInStaging: true, * // The configuration property can be in the following formats * // 'devDisabledIn${productFlavor}${buildType}' * // 'devDisabledIn${buildType}' * * // the root of your project, i.e. where "package.json" lives * root: "../../", * * // where to put the JS bundle asset in debug mode * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", * * // where to put the JS bundle asset in release mode * jsBundleDirRelease: "$buildDir/intermediates/assets/release", * * // where to put drawable resources / React Native assets, e.g. the ones you use via * // require('./image.png')), in debug mode * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", * * // where to put drawable resources / React Native assets, e.g. the ones you use via * // require('./image.png')), in release mode * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", * * // by default the gradle tasks are skipped if none of the JS files or assets change; this means * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to * // date; if you have any other folders that you want to ignore for performance reasons (gradle * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ * // for example, you might want to remove it from here. * inputExcludes: ["android/**", "ios/**"], * * // override which node gets called and with what additional arguments * nodeExecutableAndArgs: ["node"], * * // supply additional arguments to the packager * extraPackagerArgs: [] * ] */ project.ext.react = [ entryFile: "index.js" ] apply from: "../../../node_modules/react-native/react.gradle" /** * Set this to true to create two separate APKs instead of one: * - An APK that only works on ARM devices * - An APK that only works on x86 devices * The advantage is the size of the APK is reduced by about 4MB. * Upload all the APKs to the Play Store and people will download * the correct one based on the CPU architecture of their device. */ def enableSeparateBuildPerCPUArchitecture = false /** * Run Proguard to shrink the Java bytecode in release builds. */ def enableProguardInReleaseBuilds = false android { compileSdkVersion rootProject.ext.compileSdkVersion compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } defaultConfig { applicationId "com.example" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode 1 versionName "1.0" } splits { abi { reset() enable enableSeparateBuildPerCPUArchitecture universalApk false // If true, also generate a universal APK include "armeabi-v7a", "x86", "arm64-v8a", "x86_64" } } buildTypes { release { minifyEnabled enableProguardInReleaseBuilds proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" } } // applicationVariants are e.g. debug, release applicationVariants.all { variant -> variant.outputs.each { output -> // For each separate APK per architecture, set a unique version code as described here: // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits def versionCodes = ["armeabi-v7a":1, "x86":2, "arm64-v8a": 3, "x86_64": 4] def abi = output.getFilter(OutputFile.ABI) if (abi != null) { // null for the universal-debug, universal-release variants output.versionCodeOverride = versionCodes.get(abi) * 1048576 + defaultConfig.versionCode } } } } dependencies { implementation fileTree(dir: "libs", include: ["*.jar"]) implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}" implementation "com.facebook.react:react-native:+" // From node_modules implementation project(':react-native-art') } // Run this once to be able to run the application with BUCK // puts all compile dependencies into folder libs for BUCK to use task copyDownloadableDepsToLibs(type: Copy) { from configurations.compile into 'libs' } ================================================ FILE: example/android/app/proguard-rules.pro ================================================ # Add project specific ProGuard rules here. # By default, the flags in this file are appended to flags specified # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt # You can edit the include path and order by changing the proguardFiles # directive in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # Add any project specific keep options here: # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} ================================================ FILE: example/android/app/src/debug/AndroidManifest.xml ================================================ ================================================ FILE: example/android/app/src/main/AndroidManifest.xml ================================================ ================================================ FILE: example/android/app/src/main/java/com/example/MainActivity.java ================================================ package com.example; import com.facebook.react.ReactActivity; public class MainActivity extends ReactActivity { /** * Returns the name of the main component registered from JavaScript. * This is used to schedule rendering of the component. */ @Override protected String getMainComponentName() { return "example"; } } ================================================ FILE: example/android/app/src/main/java/com/example/MainApplication.java ================================================ package com.example; import android.app.Application; import com.reactnativecommunity.art.ARTPackage; import com.facebook.react.ReactApplication; import com.facebook.react.ReactNativeHost; import com.facebook.react.ReactPackage; import com.facebook.react.shell.MainReactPackage; import com.facebook.soloader.SoLoader; import java.util.Arrays; import java.util.List; public class MainApplication extends Application implements ReactApplication { private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { @Override public boolean getUseDeveloperSupport() { return BuildConfig.DEBUG; } @Override protected List getPackages() { return Arrays.asList( new MainReactPackage(), new ARTPackage() ); } @Override protected String getJSMainModuleName() { return "example/index"; } }; @Override public ReactNativeHost getReactNativeHost() { return mReactNativeHost; } @Override public void onCreate() { super.onCreate(); SoLoader.init(this, /* native exopackage */ false); } } ================================================ FILE: example/android/app/src/main/res/values/strings.xml ================================================ example ================================================ FILE: example/android/app/src/main/res/values/styles.xml ================================================ ================================================ FILE: example/android/build.gradle ================================================ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { ext { buildToolsVersion = "28.0.3" minSdkVersion = 16 compileSdkVersion = 28 targetSdkVersion = 28 supportLibVersion = "28.0.0" } repositories { google() jcenter() } dependencies { classpath("com.android.tools.build:gradle:3.4.0") // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { mavenLocal() google() jcenter() maven { // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm url "$rootDir/../../node_modules/react-native/android" } } } ================================================ FILE: example/android/gradle/wrapper/gradle-wrapper.properties ================================================ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists ================================================ FILE: example/android/gradle.properties ================================================ # Project-wide Gradle settings. # IDE (e.g. Android Studio) users: # Gradle settings configured through the IDE *will override* # any settings specified in this file. # For more details on how to configure your build environment visit # http://www.gradle.org/docs/current/userguide/build_environment.html # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. # Default value: -Xmx10248m -XX:MaxPermSize=256m # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true ================================================ FILE: example/android/gradlew ================================================ #!/usr/bin/env sh # # Copyright 2015 the original author or authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################## ## ## Gradle start up script for UN*X ## ############################################################################## # Attempt to set APP_HOME # Resolve links: $0 may be a link PRG="$0" # Need this for relative symlinks. while [ -h "$PRG" ] ; do ls=`ls -ld "$PRG"` link=`expr "$ls" : '.*-> \(.*\)$'` if expr "$link" : '/.*' > /dev/null; then PRG="$link" else PRG=`dirname "$PRG"`"/$link" fi done SAVED="`pwd`" cd "`dirname \"$PRG\"`/" >/dev/null APP_HOME="`pwd -P`" cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" warn () { echo "$*" } die () { echo echo "$*" echo exit 1 } # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false case "`uname`" in CYGWIN* ) cygwin=true ;; Darwin* ) darwin=true ;; MINGW* ) msys=true ;; NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD="$JAVA_HOME/jre/sh/java" else JAVACMD="$JAVA_HOME/bin/java" fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD="java" which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi # Increase the maximum file descriptors if we can. if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then MAX_FD="$MAX_FD_LIMIT" fi ulimit -n $MAX_FD if [ $? -ne 0 ] ; then warn "Could not set maximum file descriptor limit: $MAX_FD" fi else warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" fi fi # For Darwin, add options to specify how the application appears in the dock if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi # For Cygwin, switch paths to Windows format before running java if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` SEP="" for dir in $ROOTDIRSRAW ; do ROOTDIRS="$ROOTDIRS$SEP$dir" SEP="|" done OURCYGPATTERN="(^($ROOTDIRS))" # Add a user-defined pattern to the cygpath arguments if [ "$GRADLE_CYGPATTERN" != "" ] ; then OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" fi # Now convert the arguments - kludge to limit ourselves to /bin/sh i=0 for arg in "$@" ; do CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` else eval `echo args$i`="\"$arg\"" fi i=$((i+1)) done case $i in (0) set -- ;; (1) set -- "$args0" ;; (2) set -- "$args0" "$args1" ;; (3) set -- "$args0" "$args1" "$args2" ;; (4) set -- "$args0" "$args1" "$args2" "$args3" ;; (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi # Escape application args save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } APP_ARGS=$(save "$@") # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then cd "$(dirname "$0")" fi exec "$JAVACMD" "$@" ================================================ FILE: example/android/gradlew.bat ================================================ @rem @rem Copyright 2015 the original author or authors. @rem @rem Licensed under the Apache License, Version 2.0 (the "License"); @rem you may not use this file except in compliance with the License. @rem You may obtain a copy of the License at @rem @rem http://www.apache.org/licenses/LICENSE-2.0 @rem @rem Unless required by applicable law or agreed to in writing, software @rem distributed under the License is distributed on an "AS IS" BASIS, @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @rem @rem ########################################################################## @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if "%ERRORLEVEL%" == "0" goto init echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto init echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :init @rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args :win9xME_args @rem Slurp the command line arguments. set CMD_LINE_ARGS= set _SKIP=2 :win9xME_args_slurp if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% :end @rem End local scope for the variables with windows NT shell if "%ERRORLEVEL%"=="0" goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 exit /b 1 :mainEnd if "%OS%"=="Windows_NT" endlocal :omega ================================================ FILE: example/android/keystores/debug.keystore.properties ================================================ key.store=debug.keystore key.alias=androiddebugkey key.store.password=android key.alias.password=android ================================================ FILE: example/android/settings.gradle ================================================ rootProject.name = 'example' include ':app' include ':react-native-art' project(':react-native-art').projectDir = new File(rootProject.projectDir, '../../android') ================================================ FILE: example/app.json ================================================ { "name": "example", "displayName": "example" } ================================================ FILE: example/components/CustomShape.js ================================================ // @flow import React from 'react'; import {StyleSheet, Dimensions} from 'react-native'; import { Surface, Shape, Group, Path, Transform, LinearGradient, } from '@react-native-community/art'; export default function CustomShape() { const surfaceWidth = Dimensions.get('window').width; const surfaceHeight = surfaceWidth / 2; const gradient = new LinearGradient( { '.5': 'blue', '1': 'black', }, 0, 0, 250, 250, ); const path = new Path() .line(40, 200) .line(150, 80) .line(150, -80) .line(40, -200) .line(-190, 120); return ( ); } const styles = StyleSheet.create({ surface: { backgroundColor: '#d39494', }, }); ================================================ FILE: example/components/CustomText.js ================================================ import React from 'react'; import {Dimensions, StyleSheet} from 'react-native'; import {Surface, Text, Group} from '@react-native-community/art'; const SHADOW = { shadowOpacity: 0.5, shadowColor: 'blue', shadowRadius: 10, shadowOffset: {x: 4, y: 4}, }; export default function CustomText() { const surfaceWidth = Dimensions.get('window').width; const surfaceHeight = surfaceWidth / 3; return ( React Native Community ); } const styles = StyleSheet.create({ surface: { backgroundColor: 'transparent', }, }); ================================================ FILE: example/components/Heart.js ================================================ // @flow import React from 'react'; import {StyleSheet, Dimensions} from 'react-native'; import { Surface, Shape, Group, RadialGradient, } from '@react-native-community/art'; const HEART_SHAPE = 'M 10,30 A 20,20 0,0,1 50,30 A 20,20 0,0,1 90,30 Q 90,60 50,90 Q 10,60 10,30 z'; const SHADOW = { shadowOpacity: 1, shadowColor: 'red', shadowRadius: 8, shadowOffset: {x: 0, y: 0}, }; export default function Heart() { const surfaceDimensions = Dimensions.get('window').width; const gradient = new RadialGradient( { '.1': 'red', '0.4': '#8c0505', '1': '#d39494', }, 50, 50, 20, 20, 50, 50, ); return ( ); } const styles = StyleSheet.create({ surface: { backgroundColor: 'black', }, }); ================================================ FILE: example/index.js ================================================ /** * @format */ import {AppRegistry} from 'react-native'; import App from './App'; import {name as appName} from './app.json'; AppRegistry.registerComponent(appName, () => App); ================================================ FILE: example/ios/example/AppDelegate.h ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import #import @interface AppDelegate : UIResponder @property (nonatomic, strong) UIWindow *window; @end ================================================ FILE: example/ios/example/AppDelegate.m ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "AppDelegate.h" #import #import #import @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSURL *jsCodeLocation; jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"example/index" fallbackResource:nil]; RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"example" initialProperties:nil launchOptions:launchOptions]; rootView.backgroundColor = [UIColor blackColor]; self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; UIViewController *rootViewController = [UIViewController new]; rootViewController.view = rootView; self.window.rootViewController = rootViewController; [self.window makeKeyAndVisible]; return YES; } @end ================================================ FILE: example/ios/example/Base.lproj/LaunchScreen.xib ================================================ ================================================ FILE: example/ios/example/Images.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: example/ios/example/Images.xcassets/Contents.json ================================================ { "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: example/ios/example/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleDisplayName example CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSRequiresIPhoneOS NSLocationWhenInUseUsageDescription UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIViewControllerBasedStatusBarAppearance NSLocationWhenInUseUsageDescription NSAppTransportSecurity NSAllowsArbitraryLoads NSExceptionDomains localhost NSExceptionAllowsInsecureHTTPLoads ================================================ FILE: example/ios/example/main.m ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import #import "AppDelegate.h" int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } ================================================ FILE: example/ios/example-tvOS/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIViewControllerBasedStatusBarAppearance NSLocationWhenInUseUsageDescription NSAppTransportSecurity NSExceptionDomains localhost NSExceptionAllowsInsecureHTTPLoads ================================================ FILE: example/ios/example.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; }; 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; }; 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; }; 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; }; 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; }; 11D1A2F320CAFA9E000508D9 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */; }; 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; }; 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; }; 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; }; 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; }; 2D02E4BC1E0B4A80006451C7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; 2D02E4BD1E0B4A84006451C7 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 2D02E4BF1E0B4AB3006451C7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 2D02E4C21E0B4AEC006451C7 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */; }; 2D02E4C31E0B4AEC006451C7 /* libRCTImage-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E841DF850E9000B6D8A /* libRCTImage-tvOS.a */; }; 2D02E4C41E0B4AEC006451C7 /* libRCTLinking-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E881DF850E9000B6D8A /* libRCTLinking-tvOS.a */; }; 2D02E4C51E0B4AEC006451C7 /* libRCTNetwork-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E8C1DF850E9000B6D8A /* libRCTNetwork-tvOS.a */; }; 2D02E4C61E0B4AEC006451C7 /* libRCTSettings-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E901DF850E9000B6D8A /* libRCTSettings-tvOS.a */; }; 2D02E4C71E0B4AEC006451C7 /* libRCTText-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E941DF850E9000B6D8A /* libRCTText-tvOS.a */; }; 2D02E4C81E0B4AEC006451C7 /* libRCTWebSocket-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E991DF850E9000B6D8A /* libRCTWebSocket-tvOS.a */; }; 2D16E6881FA4F8E400B85C8A /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2D16E6891FA4F8E400B85C8A /* libReact.a */; }; 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; ADBDB9381DFEBF1600ED6528 /* libRCTBlob.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */; }; E73EAAC822AA4D8E0051DFD6 /* libART.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E73EAA9822AA4D7C0051DFD6 /* libART.a */; }; ED297163215061F000B7C4FE /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED297162215061F000B7C4FE /* JavaScriptCore.framework */; }; ED2971652150620600B7C4FE /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED2971642150620600B7C4FE /* JavaScriptCore.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */; proxyType = 2; remoteGlobalIDString = 134814201AA4EA6300B7C361; remoteInfo = RCTActionSheet; }; 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */; proxyType = 2; remoteGlobalIDString = 134814201AA4EA6300B7C361; remoteInfo = RCTGeolocation; }; 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; proxyType = 2; remoteGlobalIDString = 58B5115D1A9E6B3D00147676; remoteInfo = RCTImage; }; 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; proxyType = 2; remoteGlobalIDString = 58B511DB1A9E6C8500147676; remoteInfo = RCTNetwork; }; 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */; proxyType = 2; remoteGlobalIDString = 832C81801AAF6DEF007FA2F7; remoteInfo = RCTVibration; }; 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; proxyType = 2; remoteGlobalIDString = 134814201AA4EA6300B7C361; remoteInfo = RCTSettings; }; 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; proxyType = 2; remoteGlobalIDString = 3C86DF461ADF2C930047B81A; remoteInfo = RCTWebSocket; }; 146834031AC3E56700842450 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; proxyType = 2; remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192; remoteInfo = React; }; 2D16E6711FA4F8DC00B85C8A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */; proxyType = 2; remoteGlobalIDString = ADD01A681E09402E00F6D226; remoteInfo = "RCTBlob-tvOS"; }; 2D16E6831FA4F8DC00B85C8A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; proxyType = 2; remoteGlobalIDString = 3DBE0D001F3B181A0099AA32; remoteInfo = fishhook; }; 2D16E6851FA4F8DC00B85C8A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; proxyType = 2; remoteGlobalIDString = 3DBE0D0D1F3B181C0099AA32; remoteInfo = "fishhook-tvOS"; }; 2DF0FFDE2056DD460020B375 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; proxyType = 2; remoteGlobalIDString = EBF21BDC1FC498900052F4D5; remoteInfo = jsinspector; }; 2DF0FFE02056DD460020B375 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; proxyType = 2; remoteGlobalIDString = EBF21BFA1FC4989A0052F4D5; remoteInfo = "jsinspector-tvOS"; }; 2DF0FFE22056DD460020B375 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; proxyType = 2; remoteGlobalIDString = 139D7ECE1E25DB7D00323FB7; remoteInfo = "third-party"; }; 2DF0FFE42056DD460020B375 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; proxyType = 2; remoteGlobalIDString = 3D383D3C1EBD27B6005632C8; remoteInfo = "third-party-tvOS"; }; 2DF0FFE62056DD460020B375 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; proxyType = 2; remoteGlobalIDString = 139D7E881E25C6D100323FB7; remoteInfo = "double-conversion"; }; 2DF0FFE82056DD460020B375 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; proxyType = 2; remoteGlobalIDString = 3D383D621EBD27B9005632C8; remoteInfo = "double-conversion-tvOS"; }; 3DAD3E831DF850E9000B6D8A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; proxyType = 2; remoteGlobalIDString = 2D2A283A1D9B042B00D4039D; remoteInfo = "RCTImage-tvOS"; }; 3DAD3E871DF850E9000B6D8A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; proxyType = 2; remoteGlobalIDString = 2D2A28471D9B043800D4039D; remoteInfo = "RCTLinking-tvOS"; }; 3DAD3E8B1DF850E9000B6D8A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; proxyType = 2; remoteGlobalIDString = 2D2A28541D9B044C00D4039D; remoteInfo = "RCTNetwork-tvOS"; }; 3DAD3E8F1DF850E9000B6D8A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; proxyType = 2; remoteGlobalIDString = 2D2A28611D9B046600D4039D; remoteInfo = "RCTSettings-tvOS"; }; 3DAD3E931DF850E9000B6D8A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; proxyType = 2; remoteGlobalIDString = 2D2A287B1D9B048500D4039D; remoteInfo = "RCTText-tvOS"; }; 3DAD3E981DF850E9000B6D8A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; proxyType = 2; remoteGlobalIDString = 2D2A28881D9B049200D4039D; remoteInfo = "RCTWebSocket-tvOS"; }; 3DAD3EA21DF850E9000B6D8A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; proxyType = 2; remoteGlobalIDString = 2D2A28131D9B038B00D4039D; remoteInfo = "React-tvOS"; }; 3DAD3EA41DF850E9000B6D8A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; proxyType = 2; remoteGlobalIDString = 3D3C059A1DE3340900C268FA; remoteInfo = yoga; }; 3DAD3EA61DF850E9000B6D8A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; proxyType = 2; remoteGlobalIDString = 3D3C06751DE3340C00C268FA; remoteInfo = "yoga-tvOS"; }; 3DAD3EA81DF850E9000B6D8A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; proxyType = 2; remoteGlobalIDString = 3D3CD9251DE5FBEC00167DC4; remoteInfo = cxxreact; }; 3DAD3EAA1DF850E9000B6D8A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; proxyType = 2; remoteGlobalIDString = 3D3CD9321DE5FBEE00167DC4; remoteInfo = "cxxreact-tvOS"; }; 5E9157321DD0AC6500FF2AA8 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */; proxyType = 2; remoteGlobalIDString = 134814201AA4EA6300B7C361; remoteInfo = RCTAnimation; }; 5E9157341DD0AC6500FF2AA8 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */; proxyType = 2; remoteGlobalIDString = 2D2A28201D9B03D100D4039D; remoteInfo = "RCTAnimation-tvOS"; }; 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; proxyType = 2; remoteGlobalIDString = 134814201AA4EA6300B7C361; remoteInfo = RCTLinking; }; 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; proxyType = 2; remoteGlobalIDString = 58B5119B1A9E6C1200147676; remoteInfo = RCTText; }; ADBDB9261DFEBF0700ED6528 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */; proxyType = 2; remoteGlobalIDString = 358F4ED71D1E81A9004DF814; remoteInfo = RCTBlob; }; E73EAA9722AA4D7C0051DFD6 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E73EAA9222AA4D7C0051DFD6 /* ART.xcodeproj */; proxyType = 2; remoteGlobalIDString = 0CF68AC11AF0540F00FF9E5C; remoteInfo = ART; }; E73EAA9922AA4D7C0051DFD6 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E73EAA9222AA4D7C0051DFD6 /* ART.xcodeproj */; proxyType = 2; remoteGlobalIDString = 323A12871E5F266B004975B8; remoteInfo = "ART-tvOS"; }; E73EAAC022AA4D7C0051DFD6 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; proxyType = 2; remoteGlobalIDString = EDEBC6D6214B3E7000DD5AC8; remoteInfo = jsi; }; E73EAAC222AA4D7C0051DFD6 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; proxyType = 2; remoteGlobalIDString = EDEBC73B214B45A300DD5AC8; remoteInfo = jsiexecutor; }; E73EAAC422AA4D7C0051DFD6 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; proxyType = 2; remoteGlobalIDString = ED296FB6214C9A0900B7C4FE; remoteInfo = "jsi-tvOS"; }; E73EAAC622AA4D7C0051DFD6 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; proxyType = 2; remoteGlobalIDString = ED296FEE214C9CF800B7C4FE; remoteInfo = "jsiexecutor-tvOS"; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = ""; }; 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = "../../node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj"; sourceTree = ""; }; 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = "../../node_modules/react-native/Libraries/Geolocation/RCTGeolocation.xcodeproj"; sourceTree = ""; }; 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = "../../node_modules/react-native/Libraries/Image/RCTImage.xcodeproj"; sourceTree = ""; }; 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = "../../node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj"; sourceTree = ""; }; 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "../../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = ""; }; 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = ""; }; 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = ""; }; 13B07F961A680F5B00A75B9A /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = example/AppDelegate.h; sourceTree = ""; }; 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = example/AppDelegate.m; sourceTree = ""; }; 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = example/Images.xcassets; sourceTree = ""; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = example/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = example/main.m; sourceTree = ""; }; 146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../../node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; }; 2D02E47B1E0B4A5D006451C7 /* example-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "example-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 2D16E6891FA4F8E400B85C8A /* libReact.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libReact.a; sourceTree = BUILT_PRODUCTS_DIR; }; 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = ""; }; 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; }; 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; }; ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTBlob.xcodeproj; path = "../../node_modules/react-native/Libraries/Blob/RCTBlob.xcodeproj"; sourceTree = ""; }; E73EAA9222AA4D7C0051DFD6 /* ART.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ART.xcodeproj; path = ../../ios/ART.xcodeproj; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; ED2971642150620600B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ED297163215061F000B7C4FE /* JavaScriptCore.framework in Frameworks */, E73EAAC822AA4D8E0051DFD6 /* libART.a in Frameworks */, ADBDB9381DFEBF1600ED6528 /* libRCTBlob.a in Frameworks */, 11D1A2F320CAFA9E000508D9 /* libRCTAnimation.a in Frameworks */, 146834051AC3E58100842450 /* libReact.a in Frameworks */, 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */, 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */, 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */, 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */, 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */, 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */, 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */, 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */, 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 2D02E4781E0B4A5D006451C7 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ED2971652150620600B7C4FE /* JavaScriptCore.framework in Frameworks */, 2D16E6881FA4F8E400B85C8A /* libReact.a in Frameworks */, 2D02E4C21E0B4AEC006451C7 /* libRCTAnimation.a in Frameworks */, 2D02E4C31E0B4AEC006451C7 /* libRCTImage-tvOS.a in Frameworks */, 2D02E4C41E0B4AEC006451C7 /* libRCTLinking-tvOS.a in Frameworks */, 2D02E4C51E0B4AEC006451C7 /* libRCTNetwork-tvOS.a in Frameworks */, 2D02E4C61E0B4AEC006451C7 /* libRCTSettings-tvOS.a in Frameworks */, 2D02E4C71E0B4AEC006451C7 /* libRCTText-tvOS.a in Frameworks */, 2D02E4C81E0B4AEC006451C7 /* libRCTWebSocket-tvOS.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 00C302A81ABCB8CE00DB3ED1 /* Products */ = { isa = PBXGroup; children = ( 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */, ); name = Products; sourceTree = ""; }; 00C302B61ABCB90400DB3ED1 /* Products */ = { isa = PBXGroup; children = ( 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */, ); name = Products; sourceTree = ""; }; 00C302BC1ABCB91800DB3ED1 /* Products */ = { isa = PBXGroup; children = ( 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */, 3DAD3E841DF850E9000B6D8A /* libRCTImage-tvOS.a */, ); name = Products; sourceTree = ""; }; 00C302D41ABCB9D200DB3ED1 /* Products */ = { isa = PBXGroup; children = ( 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */, 3DAD3E8C1DF850E9000B6D8A /* libRCTNetwork-tvOS.a */, ); name = Products; sourceTree = ""; }; 00C302E01ABCB9EE00DB3ED1 /* Products */ = { isa = PBXGroup; children = ( 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */, ); name = Products; sourceTree = ""; }; 139105B71AF99BAD00B5F7CC /* Products */ = { isa = PBXGroup; children = ( 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */, 3DAD3E901DF850E9000B6D8A /* libRCTSettings-tvOS.a */, ); name = Products; sourceTree = ""; }; 139FDEE71B06529A00C62182 /* Products */ = { isa = PBXGroup; children = ( 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */, 3DAD3E991DF850E9000B6D8A /* libRCTWebSocket-tvOS.a */, 2D16E6841FA4F8DC00B85C8A /* libfishhook.a */, 2D16E6861FA4F8DC00B85C8A /* libfishhook-tvOS.a */, ); name = Products; sourceTree = ""; }; 13B07FAE1A68108700A75B9A /* example */ = { isa = PBXGroup; children = ( 008F07F21AC5B25A0029DE68 /* main.jsbundle */, 13B07FAF1A68108700A75B9A /* AppDelegate.h */, 13B07FB01A68108700A75B9A /* AppDelegate.m */, 13B07FB51A68108700A75B9A /* Images.xcassets */, 13B07FB61A68108700A75B9A /* Info.plist */, 13B07FB11A68108700A75B9A /* LaunchScreen.xib */, 13B07FB71A68108700A75B9A /* main.m */, ); name = example; sourceTree = ""; }; 146834001AC3E56700842450 /* Products */ = { isa = PBXGroup; children = ( 146834041AC3E56700842450 /* libReact.a */, 3DAD3EA31DF850E9000B6D8A /* libReact.a */, 3DAD3EA51DF850E9000B6D8A /* libyoga.a */, 3DAD3EA71DF850E9000B6D8A /* libyoga.a */, 3DAD3EA91DF850E9000B6D8A /* libcxxreact.a */, 3DAD3EAB1DF850E9000B6D8A /* libcxxreact.a */, 2DF0FFDF2056DD460020B375 /* libjsinspector.a */, 2DF0FFE12056DD460020B375 /* libjsinspector-tvOS.a */, 2DF0FFE32056DD460020B375 /* libthird-party.a */, 2DF0FFE52056DD460020B375 /* libthird-party.a */, 2DF0FFE72056DD460020B375 /* libdouble-conversion.a */, 2DF0FFE92056DD460020B375 /* libdouble-conversion.a */, E73EAAC122AA4D7C0051DFD6 /* libjsi.a */, E73EAAC322AA4D7C0051DFD6 /* libjsiexecutor.a */, E73EAAC522AA4D7C0051DFD6 /* libjsi-tvOS.a */, E73EAAC722AA4D7C0051DFD6 /* libjsiexecutor-tvOS.a */, ); name = Products; sourceTree = ""; }; 2D16E6871FA4F8E400B85C8A /* Frameworks */ = { isa = PBXGroup; children = ( ED297162215061F000B7C4FE /* JavaScriptCore.framework */, ED2971642150620600B7C4FE /* JavaScriptCore.framework */, 2D16E6891FA4F8E400B85C8A /* libReact.a */, ); name = Frameworks; sourceTree = ""; }; 5E91572E1DD0AC6500FF2AA8 /* Products */ = { isa = PBXGroup; children = ( 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */, 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */, ); name = Products; sourceTree = ""; }; 78C398B11ACF4ADC00677621 /* Products */ = { isa = PBXGroup; children = ( 78C398B91ACF4ADC00677621 /* libRCTLinking.a */, 3DAD3E881DF850E9000B6D8A /* libRCTLinking-tvOS.a */, ); name = Products; sourceTree = ""; }; 832341AE1AAA6A7D00B99B32 /* Libraries */ = { isa = PBXGroup; children = ( E73EAA9222AA4D7C0051DFD6 /* ART.xcodeproj */, 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */, 146833FF1AC3E56700842450 /* React.xcodeproj */, 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */, ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */, 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */, 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */, 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */, 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */, 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */, 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */, 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */, 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */, ); name = Libraries; sourceTree = ""; }; 832341B11AAA6A8300B99B32 /* Products */ = { isa = PBXGroup; children = ( 832341B51AAA6A8300B99B32 /* libRCTText.a */, 3DAD3E941DF850E9000B6D8A /* libRCTText-tvOS.a */, ); name = Products; sourceTree = ""; }; 83CBB9F61A601CBA00E9B192 = { isa = PBXGroup; children = ( 13B07FAE1A68108700A75B9A /* example */, 832341AE1AAA6A7D00B99B32 /* Libraries */, 83CBBA001A601CBA00E9B192 /* Products */, 2D16E6871FA4F8E400B85C8A /* Frameworks */, ); indentWidth = 2; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 83CBBA001A601CBA00E9B192 /* Products */ = { isa = PBXGroup; children = ( 13B07F961A680F5B00A75B9A /* example.app */, 2D02E47B1E0B4A5D006451C7 /* example-tvOS.app */, ); name = Products; sourceTree = ""; }; ADBDB9201DFEBF0600ED6528 /* Products */ = { isa = PBXGroup; children = ( ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */, 2D16E6721FA4F8DC00B85C8A /* libRCTBlob-tvOS.a */, ); name = Products; sourceTree = ""; }; E73EAA9322AA4D7C0051DFD6 /* Products */ = { isa = PBXGroup; children = ( E73EAA9822AA4D7C0051DFD6 /* libART.a */, E73EAA9A22AA4D7C0051DFD6 /* libART-tvOS.a */, ); name = Products; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 13B07F861A680F5B00A75B9A /* example */ = { isa = PBXNativeTarget; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "example" */; buildPhases = ( 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, ); buildRules = ( ); dependencies = ( ); name = example; productName = "Hello World"; productReference = 13B07F961A680F5B00A75B9A /* example.app */; productType = "com.apple.product-type.application"; }; 2D02E47A1E0B4A5D006451C7 /* example-tvOS */ = { isa = PBXNativeTarget; buildConfigurationList = 2D02E4BA1E0B4A5E006451C7 /* Build configuration list for PBXNativeTarget "example-tvOS" */; buildPhases = ( 2D02E4771E0B4A5D006451C7 /* Sources */, 2D02E4781E0B4A5D006451C7 /* Frameworks */, 2D02E4791E0B4A5D006451C7 /* Resources */, 2D02E4CB1E0B4B27006451C7 /* Bundle React Native Code And Images */, ); buildRules = ( ); dependencies = ( ); name = "example-tvOS"; productName = "example-tvOS"; productReference = 2D02E47B1E0B4A5D006451C7 /* example-tvOS.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 83CBB9F71A601CBA00E9B192 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0940; ORGANIZATIONNAME = Facebook; TargetAttributes = { 2D02E47A1E0B4A5D006451C7 = { CreatedOnToolsVersion = 8.2.1; ProvisioningStyle = Automatic; }; }; }; buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "example" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( English, en, Base, ); mainGroup = 83CBB9F61A601CBA00E9B192; productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; projectDirPath = ""; projectReferences = ( { ProductGroup = E73EAA9322AA4D7C0051DFD6 /* Products */; ProjectRef = E73EAA9222AA4D7C0051DFD6 /* ART.xcodeproj */; }, { ProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */; ProjectRef = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */; }, { ProductGroup = 5E91572E1DD0AC6500FF2AA8 /* Products */; ProjectRef = 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */; }, { ProductGroup = ADBDB9201DFEBF0600ED6528 /* Products */; ProjectRef = ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */; }, { ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */; ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */; }, { ProductGroup = 00C302BC1ABCB91800DB3ED1 /* Products */; ProjectRef = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; }, { ProductGroup = 78C398B11ACF4ADC00677621 /* Products */; ProjectRef = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; }, { ProductGroup = 00C302D41ABCB9D200DB3ED1 /* Products */; ProjectRef = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; }, { ProductGroup = 139105B71AF99BAD00B5F7CC /* Products */; ProjectRef = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; }, { ProductGroup = 832341B11AAA6A8300B99B32 /* Products */; ProjectRef = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; }, { ProductGroup = 00C302E01ABCB9EE00DB3ED1 /* Products */; ProjectRef = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */; }, { ProductGroup = 139FDEE71B06529A00C62182 /* Products */; ProjectRef = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; }, { ProductGroup = 146834001AC3E56700842450 /* Products */; ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */; }, ); projectRoot = ""; targets = ( 13B07F861A680F5B00A75B9A /* example */, 2D02E47A1E0B4A5D006451C7 /* example-tvOS */, ); }; /* End PBXProject section */ /* Begin PBXReferenceProxy section */ 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libRCTActionSheet.a; remoteRef = 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libRCTGeolocation.a; remoteRef = 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libRCTImage.a; remoteRef = 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libRCTNetwork.a; remoteRef = 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libRCTVibration.a; remoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libRCTSettings.a; remoteRef = 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libRCTWebSocket.a; remoteRef = 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 146834041AC3E56700842450 /* libReact.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libReact.a; remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 2D16E6721FA4F8DC00B85C8A /* libRCTBlob-tvOS.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = "libRCTBlob-tvOS.a"; remoteRef = 2D16E6711FA4F8DC00B85C8A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 2D16E6841FA4F8DC00B85C8A /* libfishhook.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libfishhook.a; remoteRef = 2D16E6831FA4F8DC00B85C8A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 2D16E6861FA4F8DC00B85C8A /* libfishhook-tvOS.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = "libfishhook-tvOS.a"; remoteRef = 2D16E6851FA4F8DC00B85C8A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 2DF0FFDF2056DD460020B375 /* libjsinspector.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libjsinspector.a; remoteRef = 2DF0FFDE2056DD460020B375 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 2DF0FFE12056DD460020B375 /* libjsinspector-tvOS.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = "libjsinspector-tvOS.a"; remoteRef = 2DF0FFE02056DD460020B375 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 2DF0FFE32056DD460020B375 /* libthird-party.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = "libthird-party.a"; remoteRef = 2DF0FFE22056DD460020B375 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 2DF0FFE52056DD460020B375 /* libthird-party.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = "libthird-party.a"; remoteRef = 2DF0FFE42056DD460020B375 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 2DF0FFE72056DD460020B375 /* libdouble-conversion.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = "libdouble-conversion.a"; remoteRef = 2DF0FFE62056DD460020B375 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 2DF0FFE92056DD460020B375 /* libdouble-conversion.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = "libdouble-conversion.a"; remoteRef = 2DF0FFE82056DD460020B375 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 3DAD3E841DF850E9000B6D8A /* libRCTImage-tvOS.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = "libRCTImage-tvOS.a"; remoteRef = 3DAD3E831DF850E9000B6D8A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 3DAD3E881DF850E9000B6D8A /* libRCTLinking-tvOS.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = "libRCTLinking-tvOS.a"; remoteRef = 3DAD3E871DF850E9000B6D8A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 3DAD3E8C1DF850E9000B6D8A /* libRCTNetwork-tvOS.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = "libRCTNetwork-tvOS.a"; remoteRef = 3DAD3E8B1DF850E9000B6D8A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 3DAD3E901DF850E9000B6D8A /* libRCTSettings-tvOS.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = "libRCTSettings-tvOS.a"; remoteRef = 3DAD3E8F1DF850E9000B6D8A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 3DAD3E941DF850E9000B6D8A /* libRCTText-tvOS.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = "libRCTText-tvOS.a"; remoteRef = 3DAD3E931DF850E9000B6D8A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 3DAD3E991DF850E9000B6D8A /* libRCTWebSocket-tvOS.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = "libRCTWebSocket-tvOS.a"; remoteRef = 3DAD3E981DF850E9000B6D8A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 3DAD3EA31DF850E9000B6D8A /* libReact.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libReact.a; remoteRef = 3DAD3EA21DF850E9000B6D8A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 3DAD3EA51DF850E9000B6D8A /* libyoga.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libyoga.a; remoteRef = 3DAD3EA41DF850E9000B6D8A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 3DAD3EA71DF850E9000B6D8A /* libyoga.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libyoga.a; remoteRef = 3DAD3EA61DF850E9000B6D8A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 3DAD3EA91DF850E9000B6D8A /* libcxxreact.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libcxxreact.a; remoteRef = 3DAD3EA81DF850E9000B6D8A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 3DAD3EAB1DF850E9000B6D8A /* libcxxreact.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libcxxreact.a; remoteRef = 3DAD3EAA1DF850E9000B6D8A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libRCTAnimation.a; remoteRef = 5E9157321DD0AC6500FF2AA8 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libRCTAnimation.a; remoteRef = 5E9157341DD0AC6500FF2AA8 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libRCTLinking.a; remoteRef = 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 832341B51AAA6A8300B99B32 /* libRCTText.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libRCTText.a; remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libRCTBlob.a; remoteRef = ADBDB9261DFEBF0700ED6528 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E73EAA9822AA4D7C0051DFD6 /* libART.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libART.a; remoteRef = E73EAA9722AA4D7C0051DFD6 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E73EAA9A22AA4D7C0051DFD6 /* libART-tvOS.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = "libART-tvOS.a"; remoteRef = E73EAA9922AA4D7C0051DFD6 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E73EAAC122AA4D7C0051DFD6 /* libjsi.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libjsi.a; remoteRef = E73EAAC022AA4D7C0051DFD6 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E73EAAC322AA4D7C0051DFD6 /* libjsiexecutor.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libjsiexecutor.a; remoteRef = E73EAAC222AA4D7C0051DFD6 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E73EAAC522AA4D7C0051DFD6 /* libjsi-tvOS.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = "libjsi-tvOS.a"; remoteRef = E73EAAC422AA4D7C0051DFD6 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E73EAAC722AA4D7C0051DFD6 /* libjsiexecutor-tvOS.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = "libjsiexecutor-tvOS.a"; remoteRef = E73EAAC622AA4D7C0051DFD6 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXReferenceProxy section */ /* Begin PBXResourcesBuildPhase section */ 13B07F8E1A680F5B00A75B9A /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; 2D02E4791E0B4A5D006451C7 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 2D02E4BD1E0B4A84006451C7 /* Images.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "Bundle React Native code and images"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "export NODE_BINARY=node\n../../node_modules/react-native/scripts/react-native-xcode.sh"; }; 2D02E4CB1E0B4B27006451C7 /* Bundle React Native Code And Images */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "Bundle React Native Code And Images"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "export NODE_BINARY=node\n../../node_modules/react-native/scripts/react-native-xcode.sh"; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 13B07F871A680F5B00A75B9A /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 2D02E4771E0B4A5D006451C7 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 2D02E4BF1E0B4AB3006451C7 /* main.m in Sources */, 2D02E4BC1E0B4A80006451C7 /* AppDelegate.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = { isa = PBXVariantGroup; children = ( 13B07FB21A68108700A75B9A /* Base */, ); name = LaunchScreen.xib; path = example; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 13B07F941A680F5B00A75B9A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CURRENT_PROJECT_VERSION = 1; DEAD_CODE_STRIPPING = NO; INFOPLIST_FILE = example/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", "-lc++", ); PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = example; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; }; 13B07F951A680F5B00A75B9A /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CURRENT_PROJECT_VERSION = 1; INFOPLIST_FILE = example/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", "-lc++", ); PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = example; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; }; 2D02E4971E0B4A5E006451C7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; CLANG_ANALYZER_NONNULL = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; GCC_NO_COMMON_BLOCKS = YES; INFOPLIST_FILE = "example-tvOS/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = ( "-ObjC", "-lc++", ); PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.example-tvOS"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = appletvos; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.2; }; name = Debug; }; 2D02E4981E0B4A5E006451C7 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; CLANG_ANALYZER_NONNULL = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_NO_COMMON_BLOCKS = YES; INFOPLIST_FILE = "example-tvOS/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = ( "-ObjC", "-lc++", ); PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.example-tvOS"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = appletvos; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.2; }; name = Release; }; 83CBBA201A601CBA00E9B192 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; }; name = Debug; }; 83CBBA211A601CBA00E9B192 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "example" */ = { isa = XCConfigurationList; buildConfigurations = ( 13B07F941A680F5B00A75B9A /* Debug */, 13B07F951A680F5B00A75B9A /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 2D02E4BA1E0B4A5E006451C7 /* Build configuration list for PBXNativeTarget "example-tvOS" */ = { isa = XCConfigurationList; buildConfigurations = ( 2D02E4971E0B4A5E006451C7 /* Debug */, 2D02E4981E0B4A5E006451C7 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "example" */ = { isa = XCConfigurationList; buildConfigurations = ( 83CBBA201A601CBA00E9B192 /* Debug */, 83CBBA211A601CBA00E9B192 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; } ================================================ FILE: example/ios/example.xcodeproj/xcshareddata/xcschemes/example-tvOS.xcscheme ================================================ ================================================ FILE: example/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme ================================================ ================================================ FILE: example/metro.config.js ================================================ /** * Metro configuration for React Native * https://github.com/facebook/react-native * * @format */ module.exports = { transformer: { getTransformOptions: async () => ({ transform: { experimentalImportSupport: false, inlineRequires: false, }, }), }, }; ================================================ FILE: index.d.ts ================================================ declare module '@react-native-community/art' { import {ViewStyle, StyleProp} from 'react-native'; import React from 'react'; export interface ARTNodeMixin { opacity?: number; originX?: number; originY?: number; scaleX?: number; scaleY?: number; scale?: number; title?: string; x?: number; y?: number; visible?: boolean; shadowOpacity?: number; shadowColor?: string | number; shadowRadius?: number; shadowOffset?: { x: number, y: number, } } export interface ARTGroupProps extends ARTNodeMixin { width?: number; height?: number; } export interface ARTClippingRectangleProps extends ARTNodeMixin { width?: number; height?: number; } export interface ARTRenderableMixin extends ARTNodeMixin { fill?: string; stroke?: string; strokeCap?: 'butt' | 'square' | 'round'; strokeDash?: number[]; strokeJoin?: 'bevel' | 'miter' | 'round'; strokeWidth?: number; } export interface ARTShapeProps extends ARTRenderableMixin { d: string; width?: number; height?: number; } export interface ARTTextProps extends ARTRenderableMixin { font?: string; alignment?: string; } export interface ARTSurfaceProps { style?: StyleProp; width: number; height: number; } export class ClippingRectangle extends React.Component {} export class Group extends React.Component {} export class Shape extends React.Component {} export class Surface extends React.Component {} export class Text extends React.Component {} } ================================================ FILE: ios/ART.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 0CF68B051AF0549300FF9E5C /* ARTGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68ADE1AF0549300FF9E5C /* ARTGroup.m */; }; 0CF68B061AF0549300FF9E5C /* ARTNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AE01AF0549300FF9E5C /* ARTNode.m */; }; 0CF68B071AF0549300FF9E5C /* ARTRenderable.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AE21AF0549300FF9E5C /* ARTRenderable.m */; }; 0CF68B081AF0549300FF9E5C /* ARTShape.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AE41AF0549300FF9E5C /* ARTShape.m */; }; 0CF68B091AF0549300FF9E5C /* ARTSurfaceView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AE61AF0549300FF9E5C /* ARTSurfaceView.m */; }; 0CF68B0A1AF0549300FF9E5C /* ARTText.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AE81AF0549300FF9E5C /* ARTText.m */; }; 0CF68B0B1AF0549300FF9E5C /* ARTBrush.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AEC1AF0549300FF9E5C /* ARTBrush.m */; }; 0CF68B0C1AF0549300FF9E5C /* ARTLinearGradient.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AEE1AF0549300FF9E5C /* ARTLinearGradient.m */; }; 0CF68B0D1AF0549300FF9E5C /* ARTPattern.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AF01AF0549300FF9E5C /* ARTPattern.m */; }; 0CF68B0E1AF0549300FF9E5C /* ARTRadialGradient.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AF21AF0549300FF9E5C /* ARTRadialGradient.m */; }; 0CF68B0F1AF0549300FF9E5C /* ARTSolidColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AF41AF0549300FF9E5C /* ARTSolidColor.m */; }; 0CF68B101AF0549300FF9E5C /* RCTConvert+ART.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AF71AF0549300FF9E5C /* RCTConvert+ART.m */; }; 0CF68B111AF0549300FF9E5C /* ARTGroupManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AFA1AF0549300FF9E5C /* ARTGroupManager.m */; }; 0CF68B121AF0549300FF9E5C /* ARTNodeManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AFC1AF0549300FF9E5C /* ARTNodeManager.m */; }; 0CF68B131AF0549300FF9E5C /* ARTRenderableManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AFE1AF0549300FF9E5C /* ARTRenderableManager.m */; }; 0CF68B141AF0549300FF9E5C /* ARTShapeManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68B001AF0549300FF9E5C /* ARTShapeManager.m */; }; 0CF68B151AF0549300FF9E5C /* ARTSurfaceViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68B021AF0549300FF9E5C /* ARTSurfaceViewManager.m */; }; 0CF68B161AF0549300FF9E5C /* ARTTextManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68B041AF0549300FF9E5C /* ARTTextManager.m */; }; 325CF7AD1E5F2ABA00AC9606 /* ARTBrush.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AEC1AF0549300FF9E5C /* ARTBrush.m */; }; 325CF7AE1E5F2ABA00AC9606 /* ARTLinearGradient.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AEE1AF0549300FF9E5C /* ARTLinearGradient.m */; }; 325CF7AF1E5F2ABA00AC9606 /* ARTPattern.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AF01AF0549300FF9E5C /* ARTPattern.m */; }; 325CF7B01E5F2ABA00AC9606 /* ARTRadialGradient.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AF21AF0549300FF9E5C /* ARTRadialGradient.m */; }; 325CF7B11E5F2ABA00AC9606 /* ARTSolidColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AF41AF0549300FF9E5C /* ARTSolidColor.m */; }; 325CF7B21E5F2ABA00AC9606 /* ARTGroupManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AFA1AF0549300FF9E5C /* ARTGroupManager.m */; }; 325CF7B31E5F2ABA00AC9606 /* ARTNodeManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AFC1AF0549300FF9E5C /* ARTNodeManager.m */; }; 325CF7B41E5F2ABA00AC9606 /* ARTRenderableManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AFE1AF0549300FF9E5C /* ARTRenderableManager.m */; }; 325CF7B51E5F2ABA00AC9606 /* ARTShapeManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68B001AF0549300FF9E5C /* ARTShapeManager.m */; }; 325CF7B61E5F2ABA00AC9606 /* ARTSurfaceViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68B021AF0549300FF9E5C /* ARTSurfaceViewManager.m */; }; 325CF7B71E5F2ABA00AC9606 /* ARTTextManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68B041AF0549300FF9E5C /* ARTTextManager.m */; }; 325CF7B81E5F2ABA00AC9606 /* ARTGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68ADE1AF0549300FF9E5C /* ARTGroup.m */; }; 325CF7B91E5F2ABA00AC9606 /* ARTNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AE01AF0549300FF9E5C /* ARTNode.m */; }; 325CF7BA1E5F2ABA00AC9606 /* ARTRenderable.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AE21AF0549300FF9E5C /* ARTRenderable.m */; }; 325CF7BB1E5F2ABA00AC9606 /* ARTShape.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AE41AF0549300FF9E5C /* ARTShape.m */; }; 325CF7BC1E5F2ABA00AC9606 /* ARTSurfaceView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AE61AF0549300FF9E5C /* ARTSurfaceView.m */; }; 325CF7BD1E5F2ABA00AC9606 /* ARTText.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AE81AF0549300FF9E5C /* ARTText.m */; }; 325CF7BE1E5F2ABA00AC9606 /* RCTConvert+ART.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF68AF71AF0549300FF9E5C /* RCTConvert+ART.m */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ 0CF68ABF1AF0540F00FF9E5C /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = "include/$(PRODUCT_NAME)"; dstSubfolderSpec = 16; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 323A12851E5F266B004975B8 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = "include/$(PRODUCT_NAME)"; dstSubfolderSpec = 16; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 09966EAF23996E3900E9C452 /* ARTShadow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ARTShadow.h; sourceTree = ""; }; 0CF68AC11AF0540F00FF9E5C /* libART.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libART.a; sourceTree = BUILT_PRODUCTS_DIR; }; 0CF68ADB1AF0549300FF9E5C /* ARTCGFloatArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARTCGFloatArray.h; sourceTree = ""; }; 0CF68ADC1AF0549300FF9E5C /* ARTContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARTContainer.h; sourceTree = ""; }; 0CF68ADD1AF0549300FF9E5C /* ARTGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARTGroup.h; sourceTree = ""; }; 0CF68ADE1AF0549300FF9E5C /* ARTGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARTGroup.m; sourceTree = ""; }; 0CF68ADF1AF0549300FF9E5C /* ARTNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARTNode.h; sourceTree = ""; }; 0CF68AE01AF0549300FF9E5C /* ARTNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARTNode.m; sourceTree = ""; }; 0CF68AE11AF0549300FF9E5C /* ARTRenderable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARTRenderable.h; sourceTree = ""; }; 0CF68AE21AF0549300FF9E5C /* ARTRenderable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARTRenderable.m; sourceTree = ""; }; 0CF68AE31AF0549300FF9E5C /* ARTShape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARTShape.h; sourceTree = ""; }; 0CF68AE41AF0549300FF9E5C /* ARTShape.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARTShape.m; sourceTree = ""; }; 0CF68AE51AF0549300FF9E5C /* ARTSurfaceView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARTSurfaceView.h; sourceTree = ""; }; 0CF68AE61AF0549300FF9E5C /* ARTSurfaceView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARTSurfaceView.m; sourceTree = ""; }; 0CF68AE71AF0549300FF9E5C /* ARTText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARTText.h; sourceTree = ""; }; 0CF68AE81AF0549300FF9E5C /* ARTText.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARTText.m; sourceTree = ""; }; 0CF68AE91AF0549300FF9E5C /* ARTTextFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARTTextFrame.h; sourceTree = ""; }; 0CF68AEB1AF0549300FF9E5C /* ARTBrush.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARTBrush.h; sourceTree = ""; }; 0CF68AEC1AF0549300FF9E5C /* ARTBrush.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARTBrush.m; sourceTree = ""; }; 0CF68AED1AF0549300FF9E5C /* ARTLinearGradient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARTLinearGradient.h; sourceTree = ""; }; 0CF68AEE1AF0549300FF9E5C /* ARTLinearGradient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARTLinearGradient.m; sourceTree = ""; }; 0CF68AEF1AF0549300FF9E5C /* ARTPattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARTPattern.h; sourceTree = ""; }; 0CF68AF01AF0549300FF9E5C /* ARTPattern.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARTPattern.m; sourceTree = ""; }; 0CF68AF11AF0549300FF9E5C /* ARTRadialGradient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARTRadialGradient.h; sourceTree = ""; }; 0CF68AF21AF0549300FF9E5C /* ARTRadialGradient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARTRadialGradient.m; sourceTree = ""; }; 0CF68AF31AF0549300FF9E5C /* ARTSolidColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARTSolidColor.h; sourceTree = ""; }; 0CF68AF41AF0549300FF9E5C /* ARTSolidColor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARTSolidColor.m; sourceTree = ""; }; 0CF68AF61AF0549300FF9E5C /* RCTConvert+ART.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+ART.h"; sourceTree = ""; }; 0CF68AF71AF0549300FF9E5C /* RCTConvert+ART.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+ART.m"; sourceTree = ""; }; 0CF68AF91AF0549300FF9E5C /* ARTGroupManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARTGroupManager.h; sourceTree = ""; }; 0CF68AFA1AF0549300FF9E5C /* ARTGroupManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARTGroupManager.m; sourceTree = ""; }; 0CF68AFB1AF0549300FF9E5C /* ARTNodeManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARTNodeManager.h; sourceTree = ""; }; 0CF68AFC1AF0549300FF9E5C /* ARTNodeManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARTNodeManager.m; sourceTree = ""; }; 0CF68AFD1AF0549300FF9E5C /* ARTRenderableManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARTRenderableManager.h; sourceTree = ""; }; 0CF68AFE1AF0549300FF9E5C /* ARTRenderableManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARTRenderableManager.m; sourceTree = ""; }; 0CF68AFF1AF0549300FF9E5C /* ARTShapeManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARTShapeManager.h; sourceTree = ""; }; 0CF68B001AF0549300FF9E5C /* ARTShapeManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARTShapeManager.m; sourceTree = ""; }; 0CF68B011AF0549300FF9E5C /* ARTSurfaceViewManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARTSurfaceViewManager.h; sourceTree = ""; }; 0CF68B021AF0549300FF9E5C /* ARTSurfaceViewManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARTSurfaceViewManager.m; sourceTree = ""; }; 0CF68B031AF0549300FF9E5C /* ARTTextManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARTTextManager.h; sourceTree = ""; }; 0CF68B041AF0549300FF9E5C /* ARTTextManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARTTextManager.m; sourceTree = ""; }; 323A12871E5F266B004975B8 /* libART-tvOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libART-tvOS.a"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 0CF68ABE1AF0540F00FF9E5C /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 323A12841E5F266B004975B8 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 0CF68AB81AF0540F00FF9E5C = { isa = PBXGroup; children = ( 09966EAF23996E3900E9C452 /* ARTShadow.h */, 0CF68AEA1AF0549300FF9E5C /* Brushes */, 0CF68AF81AF0549300FF9E5C /* ViewManagers */, 0CF68ADB1AF0549300FF9E5C /* ARTCGFloatArray.h */, 0CF68ADC1AF0549300FF9E5C /* ARTContainer.h */, 0CF68ADD1AF0549300FF9E5C /* ARTGroup.h */, 0CF68ADE1AF0549300FF9E5C /* ARTGroup.m */, 0CF68ADF1AF0549300FF9E5C /* ARTNode.h */, 0CF68AE01AF0549300FF9E5C /* ARTNode.m */, 0CF68AE11AF0549300FF9E5C /* ARTRenderable.h */, 0CF68AE21AF0549300FF9E5C /* ARTRenderable.m */, 0CF68AE31AF0549300FF9E5C /* ARTShape.h */, 0CF68AE41AF0549300FF9E5C /* ARTShape.m */, 0CF68AE51AF0549300FF9E5C /* ARTSurfaceView.h */, 0CF68AE61AF0549300FF9E5C /* ARTSurfaceView.m */, 0CF68AE71AF0549300FF9E5C /* ARTText.h */, 0CF68AE81AF0549300FF9E5C /* ARTText.m */, 0CF68AE91AF0549300FF9E5C /* ARTTextFrame.h */, 0CF68AF61AF0549300FF9E5C /* RCTConvert+ART.h */, 0CF68AF71AF0549300FF9E5C /* RCTConvert+ART.m */, 0CF68AC21AF0540F00FF9E5C /* Products */, ); indentWidth = 2; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 0CF68AC21AF0540F00FF9E5C /* Products */ = { isa = PBXGroup; children = ( 0CF68AC11AF0540F00FF9E5C /* libART.a */, 323A12871E5F266B004975B8 /* libART-tvOS.a */, ); name = Products; sourceTree = ""; }; 0CF68AEA1AF0549300FF9E5C /* Brushes */ = { isa = PBXGroup; children = ( 0CF68AEB1AF0549300FF9E5C /* ARTBrush.h */, 0CF68AEC1AF0549300FF9E5C /* ARTBrush.m */, 0CF68AED1AF0549300FF9E5C /* ARTLinearGradient.h */, 0CF68AEE1AF0549300FF9E5C /* ARTLinearGradient.m */, 0CF68AEF1AF0549300FF9E5C /* ARTPattern.h */, 0CF68AF01AF0549300FF9E5C /* ARTPattern.m */, 0CF68AF11AF0549300FF9E5C /* ARTRadialGradient.h */, 0CF68AF21AF0549300FF9E5C /* ARTRadialGradient.m */, 0CF68AF31AF0549300FF9E5C /* ARTSolidColor.h */, 0CF68AF41AF0549300FF9E5C /* ARTSolidColor.m */, ); path = Brushes; sourceTree = ""; }; 0CF68AF81AF0549300FF9E5C /* ViewManagers */ = { isa = PBXGroup; children = ( 0CF68AF91AF0549300FF9E5C /* ARTGroupManager.h */, 0CF68AFA1AF0549300FF9E5C /* ARTGroupManager.m */, 0CF68AFB1AF0549300FF9E5C /* ARTNodeManager.h */, 0CF68AFC1AF0549300FF9E5C /* ARTNodeManager.m */, 0CF68AFD1AF0549300FF9E5C /* ARTRenderableManager.h */, 0CF68AFE1AF0549300FF9E5C /* ARTRenderableManager.m */, 0CF68AFF1AF0549300FF9E5C /* ARTShapeManager.h */, 0CF68B001AF0549300FF9E5C /* ARTShapeManager.m */, 0CF68B011AF0549300FF9E5C /* ARTSurfaceViewManager.h */, 0CF68B021AF0549300FF9E5C /* ARTSurfaceViewManager.m */, 0CF68B031AF0549300FF9E5C /* ARTTextManager.h */, 0CF68B041AF0549300FF9E5C /* ARTTextManager.m */, ); path = ViewManagers; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 0CF68AC01AF0540F00FF9E5C /* ART */ = { isa = PBXNativeTarget; buildConfigurationList = 0CF68AD51AF0540F00FF9E5C /* Build configuration list for PBXNativeTarget "ART" */; buildPhases = ( 0CF68ABD1AF0540F00FF9E5C /* Sources */, 0CF68ABE1AF0540F00FF9E5C /* Frameworks */, 0CF68ABF1AF0540F00FF9E5C /* CopyFiles */, ); buildRules = ( ); dependencies = ( ); name = ART; productName = ART; productReference = 0CF68AC11AF0540F00FF9E5C /* libART.a */; productType = "com.apple.product-type.library.static"; }; 323A12861E5F266B004975B8 /* ART-tvOS */ = { isa = PBXNativeTarget; buildConfigurationList = 323A128D1E5F266B004975B8 /* Build configuration list for PBXNativeTarget "ART-tvOS" */; buildPhases = ( 323A12831E5F266B004975B8 /* Sources */, 323A12841E5F266B004975B8 /* Frameworks */, 323A12851E5F266B004975B8 /* CopyFiles */, ); buildRules = ( ); dependencies = ( ); name = "ART-tvOS"; productName = "ART-tvOS"; productReference = 323A12871E5F266B004975B8 /* libART-tvOS.a */; productType = "com.apple.product-type.library.static"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 0CF68AB91AF0540F00FF9E5C /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0940; TargetAttributes = { 0CF68AC01AF0540F00FF9E5C = { CreatedOnToolsVersion = 6.2; }; 323A12861E5F266B004975B8 = { CreatedOnToolsVersion = 6.2; ProvisioningStyle = Automatic; }; }; }; buildConfigurationList = 0CF68ABC1AF0540F00FF9E5C /* Build configuration list for PBXProject "ART" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( English, en, ); mainGroup = 0CF68AB81AF0540F00FF9E5C; productRefGroup = 0CF68AC21AF0540F00FF9E5C /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 0CF68AC01AF0540F00FF9E5C /* ART */, 323A12861E5F266B004975B8 /* ART-tvOS */, ); }; /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ 0CF68ABD1AF0540F00FF9E5C /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 0CF68B161AF0549300FF9E5C /* ARTTextManager.m in Sources */, 0CF68B111AF0549300FF9E5C /* ARTGroupManager.m in Sources */, 0CF68B0D1AF0549300FF9E5C /* ARTPattern.m in Sources */, 0CF68B0A1AF0549300FF9E5C /* ARTText.m in Sources */, 0CF68B121AF0549300FF9E5C /* ARTNodeManager.m in Sources */, 0CF68B051AF0549300FF9E5C /* ARTGroup.m in Sources */, 0CF68B131AF0549300FF9E5C /* ARTRenderableManager.m in Sources */, 0CF68B091AF0549300FF9E5C /* ARTSurfaceView.m in Sources */, 0CF68B0E1AF0549300FF9E5C /* ARTRadialGradient.m in Sources */, 0CF68B151AF0549300FF9E5C /* ARTSurfaceViewManager.m in Sources */, 0CF68B081AF0549300FF9E5C /* ARTShape.m in Sources */, 0CF68B071AF0549300FF9E5C /* ARTRenderable.m in Sources */, 0CF68B101AF0549300FF9E5C /* RCTConvert+ART.m in Sources */, 0CF68B061AF0549300FF9E5C /* ARTNode.m in Sources */, 0CF68B0F1AF0549300FF9E5C /* ARTSolidColor.m in Sources */, 0CF68B0C1AF0549300FF9E5C /* ARTLinearGradient.m in Sources */, 0CF68B0B1AF0549300FF9E5C /* ARTBrush.m in Sources */, 0CF68B141AF0549300FF9E5C /* ARTShapeManager.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 323A12831E5F266B004975B8 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 325CF7B71E5F2ABA00AC9606 /* ARTTextManager.m in Sources */, 325CF7B21E5F2ABA00AC9606 /* ARTGroupManager.m in Sources */, 325CF7AF1E5F2ABA00AC9606 /* ARTPattern.m in Sources */, 325CF7BD1E5F2ABA00AC9606 /* ARTText.m in Sources */, 325CF7B31E5F2ABA00AC9606 /* ARTNodeManager.m in Sources */, 325CF7B81E5F2ABA00AC9606 /* ARTGroup.m in Sources */, 325CF7B41E5F2ABA00AC9606 /* ARTRenderableManager.m in Sources */, 325CF7BC1E5F2ABA00AC9606 /* ARTSurfaceView.m in Sources */, 325CF7B01E5F2ABA00AC9606 /* ARTRadialGradient.m in Sources */, 325CF7B61E5F2ABA00AC9606 /* ARTSurfaceViewManager.m in Sources */, 325CF7BB1E5F2ABA00AC9606 /* ARTShape.m in Sources */, 325CF7BA1E5F2ABA00AC9606 /* ARTRenderable.m in Sources */, 325CF7BE1E5F2ABA00AC9606 /* RCTConvert+ART.m in Sources */, 325CF7B91E5F2ABA00AC9606 /* ARTNode.m in Sources */, 325CF7B11E5F2ABA00AC9606 /* ARTSolidColor.m in Sources */, 325CF7AE1E5F2ABA00AC9606 /* ARTLinearGradient.m in Sources */, 325CF7AD1E5F2ABA00AC9606 /* ARTBrush.m in Sources */, 325CF7B51E5F2ABA00AC9606 /* ARTShapeManager.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 0CF68AD31AF0540F00FF9E5C /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SKIP_INSTALL = YES; }; name = Debug; }; 0CF68AD41AF0540F00FF9E5C /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SKIP_INSTALL = YES; VALIDATE_PRODUCT = YES; }; name = Release; }; 0CF68AD61AF0540F00FF9E5C /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 0CF68AD71AF0540F00FF9E5C /* Release */ = { isa = XCBuildConfiguration; buildSettings = { OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; 323A128E1E5F266B004975B8 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ANALYZER_NONNULL = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; GCC_NO_COMMON_BLOCKS = YES; OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = appletvos; SKIP_INSTALL = YES; TVOS_DEPLOYMENT_TARGET = 9.2; }; name = Debug; }; 323A128F1E5F266B004975B8 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ANALYZER_NONNULL = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_NO_COMMON_BLOCKS = YES; OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = appletvos; SKIP_INSTALL = YES; TVOS_DEPLOYMENT_TARGET = 9.2; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 0CF68ABC1AF0540F00FF9E5C /* Build configuration list for PBXProject "ART" */ = { isa = XCConfigurationList; buildConfigurations = ( 0CF68AD31AF0540F00FF9E5C /* Debug */, 0CF68AD41AF0540F00FF9E5C /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 0CF68AD51AF0540F00FF9E5C /* Build configuration list for PBXNativeTarget "ART" */ = { isa = XCConfigurationList; buildConfigurations = ( 0CF68AD61AF0540F00FF9E5C /* Debug */, 0CF68AD71AF0540F00FF9E5C /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 323A128D1E5F266B004975B8 /* Build configuration list for PBXNativeTarget "ART-tvOS" */ = { isa = XCConfigurationList; buildConfigurations = ( 323A128E1E5F266B004975B8 /* Debug */, 323A128F1E5F266B004975B8 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 0CF68AB91AF0540F00FF9E5C /* Project object */; } ================================================ FILE: ios/ARTCGFloatArray.h ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ // A little helper to make sure we have the right memory allocation ready for use. // We assume that we will only this in one place so no reference counting is necessary. // Needs to be freed when deallocated. // This is fragile since this relies on these values not getting reused. Consider // wrapping these in an Obj-C class or some ARC hackery to get refcounting. typedef struct { size_t count; CGFloat *array; } ARTCGFloatArray; ================================================ FILE: ios/ARTContainer.h ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import @protocol ARTContainer // This is used as a hook for child to mark it's parent as dirty. // This bubbles up to the root which gets marked as dirty. - (void)invalidate; @end ================================================ FILE: ios/ARTGroup.h ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import #import "ARTContainer.h" #import "ARTNode.h" @interface ARTGroup : ARTNode @property (nonatomic, assign) CGRect clipping; @end ================================================ FILE: ios/ARTGroup.m ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTGroup.h" @implementation ARTGroup - (void)renderLayerTo:(CGContextRef)context { if (!CGRectIsEmpty(self.clipping)) { CGContextClipToRect(context, self.clipping); } for (ARTNode *node in self.subviews) { [node renderTo:context]; } } @end ================================================ FILE: ios/ARTNode.h ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import #import "ARTShadow.h" /** * ART nodes are implemented as empty UIViews but this is just an implementation detail to fit * into the existing view management. They should also be shadow views and painted on a background * thread. */ @interface ARTNode : UIView @property (nonatomic, assign) CGFloat opacity; @property (nonatomic, assign) ARTShadow shadow; - (void)invalidate; - (void)renderTo:(CGContextRef)context; /** * renderTo will take opacity into account and draw renderLayerTo off-screen if there is opacity * specified, then composite that onto the context. renderLayerTo always draws at opacity=1. * @abstract */ - (void)renderLayerTo:(CGContextRef)context; @end ================================================ FILE: ios/ARTNode.m ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTNode.h" #import "ARTContainer.h" #import "RCTConvert+ART.h" @implementation ARTNode - (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex { [super insertReactSubview:subview atIndex:atIndex]; [self insertSubview:subview atIndex:atIndex]; [self invalidate]; } - (void)removeReactSubview:(UIView *)subview { [super removeReactSubview:subview]; [self invalidate]; } - (void)didUpdateReactSubviews { // Do nothing, as subviews are inserted by insertReactSubview: } - (void)setOpacity:(CGFloat)opacity { [self invalidate]; _opacity = opacity; } - (void)setTransform:(CGAffineTransform)transform { [self invalidate]; super.transform = transform; } - (void)setShadow:(ARTShadow)shadow { [self invalidate]; _shadow = shadow; } - (void)invalidate { id container = (id)self.superview; [container invalidate]; } - (void)renderTo:(CGContextRef)context { if (self.opacity <= 0) { // Nothing to paint return; } if (self.opacity >= 1) { // Just paint at full opacity [self renderContentTo:context]; [self renderLayerTo:context]; CGContextRestoreGState(context); return; } // This needs to be painted on a layer before being composited. [self renderContentTo:context]; CGContextBeginTransparencyLayer(context, NULL); [self renderLayerTo:context]; CGContextEndTransparencyLayer(context); CGContextRestoreGState(context); } - (void)renderContentTo:(CGContextRef)context { CGContextSaveGState(context); CGContextConcatCTM(context, self.transform); CGContextSetAlpha(context, self.opacity); UIColor *color = [UIColor colorWithCGColor:[RCTConvert CGColor:@(self.shadow.color)]]; color = [color colorWithAlphaComponent:self.shadow.alpha]; CGContextSetShadowWithColor(context, self.shadow.offset, self.shadow.blur, color.CGColor); } - (void)renderLayerTo:(CGContextRef)context { // abstract } @end ================================================ FILE: ios/ARTRenderable.h ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import #import "ARTBrush.h" #import "ARTCGFloatArray.h" #import "ARTNode.h" @interface ARTRenderable : ARTNode @property (nonatomic, strong) ARTBrush *fill; @property (nonatomic, assign) CGColorRef stroke; @property (nonatomic, assign) CGFloat strokeWidth; @property (nonatomic, assign) CGLineCap strokeCap; @property (nonatomic, assign) CGLineJoin strokeJoin; @property (nonatomic, assign) ARTCGFloatArray strokeDash; @end ================================================ FILE: ios/ARTRenderable.m ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTRenderable.h" @implementation ARTRenderable - (void)setFill:(ARTBrush *)fill { [self invalidate]; _fill = fill; } - (void)setStroke:(CGColorRef)stroke { if (stroke == _stroke) { return; } [self invalidate]; CGColorRelease(_stroke); _stroke = CGColorRetain(stroke); } - (void)setStrokeWidth:(CGFloat)strokeWidth { [self invalidate]; _strokeWidth = strokeWidth; } - (void)setStrokeCap:(CGLineCap)strokeCap { [self invalidate]; _strokeCap = strokeCap; } - (void)setStrokeJoin:(CGLineJoin)strokeJoin { [self invalidate]; _strokeJoin = strokeJoin; } - (void)setStrokeDash:(ARTCGFloatArray)strokeDash { if (strokeDash.array == _strokeDash.array) { return; } if (_strokeDash.array) { free(_strokeDash.array); } [self invalidate]; _strokeDash = strokeDash; } - (void)dealloc { CGColorRelease(_stroke); if (_strokeDash.array) { free(_strokeDash.array); } } - (void)renderTo:(CGContextRef)context { if (self.opacity <= 0 || self.opacity >= 1 || (self.fill && self.stroke)) { // If we have both fill and stroke, we will need to paint this using normal compositing [super renderTo: context]; return; } // This is a terminal with only one painting. Therefore we don't need to paint this // off-screen. We can just composite it straight onto the buffer. CGContextSaveGState(context); CGContextConcatCTM(context, self.transform); CGContextSetAlpha(context, self.opacity); [self renderLayerTo:context]; CGContextRestoreGState(context); } - (void)renderLayerTo:(CGContextRef)context { // abstract } @end ================================================ FILE: ios/ARTShadow.h ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ typedef struct { CGSize offset; CGFloat blur; CGFloat alpha; CGFloat color; } ARTShadow; ================================================ FILE: ios/ARTShape.h ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import #import "ARTRenderable.h" @interface ARTShape : ARTRenderable @property (nonatomic, assign) CGPathRef d; @end ================================================ FILE: ios/ARTShape.m ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTShape.h" @implementation ARTShape - (void)setD:(CGPathRef)d { if (d == _d) { return; } [self invalidate]; CGPathRelease(_d); _d = CGPathRetain(d); } - (void)dealloc { CGPathRelease(_d); } - (void)renderLayerTo:(CGContextRef)context { if ((!self.fill && !self.stroke) || !self.d) { return; } CGPathDrawingMode mode = kCGPathStroke; if (self.fill) { if ([self.fill applyFillColor:context]) { mode = kCGPathFill; } else { CGContextSaveGState(context); CGContextAddPath(context, self.d); CGContextClip(context); [self.fill paint:context]; CGContextRestoreGState(context); if (!self.stroke) { return; } } } if (self.stroke) { CGContextSetStrokeColorWithColor(context, self.stroke); CGContextSetLineWidth(context, self.strokeWidth); CGContextSetLineCap(context, self.strokeCap); CGContextSetLineJoin(context, self.strokeJoin); ARTCGFloatArray dash = self.strokeDash; if (dash.count) { CGContextSetLineDash(context, 0, dash.array, dash.count); } if (mode == kCGPathFill) { mode = kCGPathFillStroke; } } CGContextAddPath(context, self.d); CGContextDrawPath(context, mode); } @end ================================================ FILE: ios/ARTSurfaceView.h ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import #import "ARTContainer.h" @interface ARTSurfaceView : UIView @end ================================================ FILE: ios/ARTSurfaceView.m ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTSurfaceView.h" #import #import "ARTNode.h" @implementation ARTSurfaceView - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { self.opaque = NO; } return self; } - (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex { [super insertReactSubview:subview atIndex:atIndex]; [self insertSubview:subview atIndex:atIndex]; [self invalidate]; } - (void)removeReactSubview:(UIView *)subview { [super removeReactSubview:subview]; [self invalidate]; } - (void)didUpdateReactSubviews { // Do nothing, as subviews are inserted by insertReactSubview: } - (void)invalidate { [self setNeedsDisplay]; } - (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); for (ARTNode *node in self.subviews) { [node renderTo:context]; } } @end ================================================ FILE: ios/ARTText.h ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import #import "ARTRenderable.h" #import "ARTTextFrame.h" @interface ARTText : ARTRenderable @property (nonatomic, assign) CTTextAlignment alignment; @property (nonatomic, assign) ARTTextFrame textFrame; @end ================================================ FILE: ios/ARTText.m ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTText.h" #import @implementation ARTText - (void)setAlignment:(CTTextAlignment)alignment { [self invalidate]; _alignment = alignment; } static void ARTFreeTextFrame(ARTTextFrame frame) { if (frame.count) { // We must release each line before freeing up this struct for (int i = 0; i < frame.count; i++) { CFRelease(frame.lines[i]); } free(frame.lines); free(frame.widths); } } - (void)setTextFrame:(ARTTextFrame)frame { if (frame.lines != _textFrame.lines) { ARTFreeTextFrame(_textFrame); } [self invalidate]; _textFrame = frame; } - (void)dealloc { ARTFreeTextFrame(_textFrame); } - (void)renderLayerTo:(CGContextRef)context { ARTTextFrame frame = self.textFrame; if ((!self.fill && !self.stroke) || !frame.count) { return; } // to-do: draw along a path CGTextDrawingMode mode = kCGTextStroke; if (self.fill) { if ([self.fill applyFillColor:context]) { mode = kCGTextFill; } else { for (int i = 0; i < frame.count; i++) { CGContextSaveGState(context); // Inverse the coordinate space since CoreText assumes a bottom-up coordinate space CGContextScaleCTM(context, 1.0, -1.0); CGContextSetTextDrawingMode(context, kCGTextClip); [self renderLineTo:context atIndex:i]; // Inverse the coordinate space back to the original before filling CGContextScaleCTM(context, 1.0, -1.0); [self.fill paint:context]; // Restore the state so that the next line can be clipped separately CGContextRestoreGState(context); } if (!self.stroke) { return; } } } if (self.stroke) { CGContextSetStrokeColorWithColor(context, self.stroke); CGContextSetLineWidth(context, self.strokeWidth); CGContextSetLineCap(context, self.strokeCap); CGContextSetLineJoin(context, self.strokeJoin); ARTCGFloatArray dash = self.strokeDash; if (dash.count) { CGContextSetLineDash(context, 0, dash.array, dash.count); } if (mode == kCGTextFill) { mode = kCGTextFillStroke; } } CGContextSetTextDrawingMode(context, mode); // Inverse the coordinate space since CoreText assumes a bottom-up coordinate space CGContextScaleCTM(context, 1.0, -1.0); for (int i = 0; i < frame.count; i++) { [self renderLineTo:context atIndex:i]; } } - (void)renderLineTo:(CGContextRef)context atIndex:(int)index { ARTTextFrame frame = self.textFrame; CGFloat shift; switch (self.alignment) { case kCTTextAlignmentRight: shift = frame.widths[index]; break; case kCTTextAlignmentCenter: shift = (frame.widths[index] / 2); break; default: shift = 0; break; } // We should consider snapping this shift to device pixels to improve rendering quality // when a line has subpixel width. CGContextSetTextPosition(context, -shift, -frame.baseLine - frame.lineHeight * index); CTLineRef line = frame.lines[index]; CTLineDraw(line, context); } @end ================================================ FILE: ios/ARTTextFrame.h ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import // A little helper to make sure we have a set of lines including width ready for use. // We assume that we will only this in one place so no reference counting is necessary. // Needs to be freed when deallocated. // This is fragile since this relies on these values not getting reused. Consider // wrapping these in an Obj-C class or some ARC hackery to get refcounting. typedef struct { size_t count; CGFloat baseLine; // Distance from the origin to the base line of the first line CGFloat lineHeight; // Distance between lines CTLineRef *lines; CGFloat *widths; // Width of each line } ARTTextFrame; ================================================ FILE: ios/Brushes/ARTBrush.h ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import #import @interface ARTBrush : NSObject /* @abstract */ - (instancetype)initWithArray:(NSArray *)data NS_DESIGNATED_INITIALIZER; /** * For certain brushes we can fast path a combined fill and stroke. * For those brushes we override applyFillColor which sets the fill * color to be used by those batch paints. Those return YES. * We can't batch gradient painting in CoreGraphics, so those will * return NO and paint gets called instead. * @abstract */ - (BOOL)applyFillColor:(CGContextRef)context; /** * paint fills the context with a brush. The context is assumed to * be clipped. * @abstract */ - (void)paint:(CGContextRef)context; @end ================================================ FILE: ios/Brushes/ARTBrush.m ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTBrush.h" #import @implementation ARTBrush - (instancetype)initWithArray:(NSArray *)data { return [super init]; } RCT_NOT_IMPLEMENTED(- (instancetype)init) - (BOOL)applyFillColor:(CGContextRef)context { return NO; } - (void)paint:(CGContextRef)context { // abstract } @end ================================================ FILE: ios/Brushes/ARTLinearGradient.h ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTBrush.h" @interface ARTLinearGradient : ARTBrush @end ================================================ FILE: ios/Brushes/ARTLinearGradient.m ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTLinearGradient.h" #import #import "RCTConvert+ART.h" @implementation ARTLinearGradient { CGGradientRef _gradient; CGPoint _startPoint; CGPoint _endPoint; } - (instancetype)initWithArray:(NSArray *)array { if ((self = [super initWithArray:array])) { if (array.count < 5) { RCTLogError(@"-[%@ %@] expects 5 elements, received %@", self.class, NSStringFromSelector(_cmd), array); return nil; } _startPoint = [RCTConvert CGPoint:array offset:1]; _endPoint = [RCTConvert CGPoint:array offset:3]; _gradient = CGGradientRetain([RCTConvert CGGradient:array offset:5]); } return self; } - (void)dealloc { CGGradientRelease(_gradient); } - (void)paint:(CGContextRef)context { CGGradientDrawingOptions extendOptions = kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation; CGContextDrawLinearGradient(context, _gradient, _startPoint, _endPoint, extendOptions); } @end ================================================ FILE: ios/Brushes/ARTPattern.h ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTBrush.h" @interface ARTPattern : ARTBrush @end ================================================ FILE: ios/Brushes/ARTPattern.m ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTPattern.h" #import #import "RCTConvert+ART.h" @implementation ARTPattern { CGImageRef _image; CGRect _rect; } - (instancetype)initWithArray:(NSArray *)array { if ((self = [super initWithArray:array])) { if (array.count < 6) { RCTLogError(@"-[%@ %@] expects 6 elements, received %@", self.class, NSStringFromSelector(_cmd), array); return nil; } _image = CGImageRetain([RCTConvert CGImage:array[1]]); _rect = [RCTConvert CGRect:array offset:2]; } return self; } - (void)dealloc { CGImageRelease(_image); } // Note: This could use applyFillColor with a pattern. This could be more efficient but // to do that, we need to calculate our own user space CTM. - (void)paint:(CGContextRef)context { CGContextDrawTiledImage(context, _rect, _image); } @end ================================================ FILE: ios/Brushes/ARTRadialGradient.h ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTBrush.h" @interface ARTRadialGradient : ARTBrush @end ================================================ FILE: ios/Brushes/ARTRadialGradient.m ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTRadialGradient.h" #import #import "RCTConvert+ART.h" @implementation ARTRadialGradient { CGGradientRef _gradient; CGPoint _focusPoint; CGPoint _centerPoint; CGFloat _radius; CGFloat _radiusRatio; } - (instancetype)initWithArray:(NSArray *)array { if ((self = [super initWithArray:array])) { if (array.count < 7) { RCTLogError(@"-[%@ %@] expects 7 elements, received %@", self.class, NSStringFromSelector(_cmd), array); return nil; } _radius = [RCTConvert CGFloat:array[3]]; _radiusRatio = [RCTConvert CGFloat:array[4]] / _radius; _focusPoint.x = [RCTConvert CGFloat:array[1]]; _focusPoint.y = [RCTConvert CGFloat:array[2]] / _radiusRatio; _centerPoint.x = [RCTConvert CGFloat:array[5]]; _centerPoint.y = [RCTConvert CGFloat:array[6]] / _radiusRatio; _gradient = CGGradientRetain([RCTConvert CGGradient:array offset:7]); } return self; } - (void)dealloc { CGGradientRelease(_gradient); } - (void)paint:(CGContextRef)context { CGAffineTransform transform = CGAffineTransformMakeScale(1, _radiusRatio); CGContextConcatCTM(context, transform); CGGradientDrawingOptions extendOptions = kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation; CGContextDrawRadialGradient(context, _gradient, _focusPoint, 0, _centerPoint, _radius, extendOptions); } @end ================================================ FILE: ios/Brushes/ARTSolidColor.h ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTBrush.h" @interface ARTSolidColor : ARTBrush @end ================================================ FILE: ios/Brushes/ARTSolidColor.m ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTSolidColor.h" #import #import "RCTConvert+ART.h" @implementation ARTSolidColor { CGColorRef _color; } - (instancetype)initWithArray:(NSArray *)array { if ((self = [super initWithArray:array])) { _color = CGColorRetain([RCTConvert CGColor:array offset:1]); } return self; } - (void)dealloc { CGColorRelease(_color); } - (BOOL)applyFillColor:(CGContextRef)context { CGContextSetFillColorWithColor(context, _color); return YES; } @end ================================================ FILE: ios/RCTConvert+ART.h ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import #import #import "ARTBrush.h" #import "ARTShadow.h" #import "ARTCGFloatArray.h" #import "ARTTextFrame.h" @interface RCTConvert (ART) + (CGPathRef)CGPath:(id)json CF_RETURNS_NOT_RETAINED; + (CTTextAlignment)CTTextAlignment:(id)json; + (ARTTextFrame)ARTTextFrame:(id)json; + (ARTCGFloatArray)ARTCGFloatArray:(id)json; + (ARTBrush *)ARTBrush:(id)json; + (ARTShadow)ARTShadow:(id)json; + (CGPoint)CGPoint:(id)json offset:(NSUInteger)offset; + (CGRect)CGRect:(id)json offset:(NSUInteger)offset; + (CGColorRef)CGColor:(id)json offset:(NSUInteger)offset CF_RETURNS_NOT_RETAINED; + (CGGradientRef)CGGradient:(id)json offset:(NSUInteger)offset CF_RETURNS_NOT_RETAINED; @end ================================================ FILE: ios/RCTConvert+ART.m ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "RCTConvert+ART.h" #import #import #import "ARTLinearGradient.h" #import "ARTPattern.h" #import "ARTRadialGradient.h" #import "ARTSolidColor.h" @implementation RCTConvert (ART) + (CGPathRef)CGPath:(id)json { NSArray *arr = [self NSNumberArray:json]; NSUInteger count = [arr count]; #define NEXT_VALUE [self double:arr[i++]] CGMutablePathRef path = CGPathCreateMutable(); CGPathMoveToPoint(path, NULL, 0, 0); @try { NSUInteger i = 0; while (i < count) { NSUInteger type = [arr[i++] unsignedIntegerValue]; switch (type) { case 0: CGPathMoveToPoint(path, NULL, NEXT_VALUE, NEXT_VALUE); break; case 1: CGPathCloseSubpath(path); break; case 2: CGPathAddLineToPoint(path, NULL, NEXT_VALUE, NEXT_VALUE); break; case 3: CGPathAddCurveToPoint(path, NULL, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE); break; case 4: CGPathAddArc(path, NULL, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE == 0); break; default: RCTLogError(@"Invalid CGPath type %llu at element %llu of %@", (unsigned long long)type, (unsigned long long)i, arr); CGPathRelease(path); return NULL; } } } @catch (NSException *exception) { RCTLogError(@"Invalid CGPath format: %@", arr); CGPathRelease(path); return NULL; } return (CGPathRef)CFAutorelease(path); } RCT_ENUM_CONVERTER(CTTextAlignment, (@{ @"auto": @(kCTTextAlignmentNatural), @"left": @(kCTTextAlignmentLeft), @"center": @(kCTTextAlignmentCenter), @"right": @(kCTTextAlignmentRight), @"justify": @(kCTTextAlignmentJustified), }), kCTTextAlignmentNatural, integerValue) // This takes a tuple of text lines and a font to generate a CTLine for each text line. // This prepares everything for rendering a frame of text in ARTText. + (ARTTextFrame)ARTTextFrame:(id)json { NSDictionary *dict = [self NSDictionary:json]; ARTTextFrame frame; frame.count = 0; NSArray *lines = [self NSArray:dict[@"lines"]]; NSUInteger lineCount = [lines count]; if (lineCount == 0) { return frame; } CTFontRef font = (__bridge CTFontRef)[self UIFont:dict[@"font"]]; if (!font) { return frame; } // Create a dictionary for this font CFDictionaryRef attributes = (__bridge CFDictionaryRef)@{ (NSString *)kCTFontAttributeName:(__bridge id)font, (NSString *)kCTForegroundColorFromContextAttributeName: @YES }; // Set up text frame with font metrics CGFloat size = CTFontGetSize(font); frame.count = lineCount; frame.baseLine = size; // estimate base line frame.lineHeight = size * 1.1; // Base on ART canvas line height estimate frame.lines = malloc(sizeof(CTLineRef) * lineCount); frame.widths = malloc(sizeof(CGFloat) * lineCount); [lines enumerateObjectsUsingBlock:^(NSString *text, NSUInteger i, BOOL *stop) { CFStringRef string = (__bridge CFStringRef)text; CFAttributedStringRef attrString = CFAttributedStringCreate(kCFAllocatorDefault, string, attributes); CTLineRef line = CTLineCreateWithAttributedString(attrString); CFRelease(attrString); frame.lines[i] = line; frame.widths[i] = CTLineGetTypographicBounds(line, NULL, NULL, NULL); }]; return frame; } + (ARTCGFloatArray)ARTCGFloatArray:(id)json { NSArray *arr = [self NSNumberArray:json]; NSUInteger count = arr.count; ARTCGFloatArray array; array.count = count; array.array = NULL; if (count) { // Ideally, these arrays should already use the same memory layout. // In that case we shouldn't need this new malloc. array.array = malloc(sizeof(CGFloat) * count); for (NSUInteger i = 0; i < count; i++) { array.array[i] = [arr[i] doubleValue]; } } return array; } + (ARTBrush *)ARTBrush:(id)json { NSArray *arr = [self NSArray:json]; NSUInteger type = [self NSUInteger:arr.firstObject]; switch (type) { case 0: // solid color // These are probably expensive allocations since it's often the same value. // We should memoize colors but look ups may be just as expensive. return [[ARTSolidColor alloc] initWithArray:arr]; case 1: // linear gradient return [[ARTLinearGradient alloc] initWithArray:arr]; case 2: // radial gradient return [[ARTRadialGradient alloc] initWithArray:arr]; case 3: // pattern return [[ARTPattern alloc] initWithArray:arr]; default: RCTLogError(@"Unknown brush type: %llu", (unsigned long long)type); return nil; } } + (ARTShadow)ARTShadow:(id)json { NSArray *arr = [self NSArray:json]; return (ARTShadow){ .color = [[arr objectAtIndex:0] doubleValue], .alpha = [[arr objectAtIndex:1] floatValue], .blur = [[arr objectAtIndex:2] floatValue], .offset = (CGSize){ .width = [[arr objectAtIndex:3] floatValue], .height = [[arr objectAtIndex:4] floatValue] }, }; } + (CGPoint)CGPoint:(id)json offset:(NSUInteger)offset { NSArray *arr = [self NSArray:json]; if (arr.count < offset + 2) { RCTLogError(@"Too few elements in array (expected at least %llu): %@", (unsigned long long)(2 + offset), arr); return CGPointZero; } return (CGPoint){ [self CGFloat:arr[offset]], [self CGFloat:arr[offset + 1]], }; } + (CGRect)CGRect:(id)json offset:(NSUInteger)offset { NSArray *arr = [self NSArray:json]; if (arr.count < offset + 4) { RCTLogError(@"Too few elements in array (expected at least %llu): %@", (unsigned long long)(4 + offset), arr); return CGRectZero; } return (CGRect){ {[self CGFloat:arr[offset]], [self CGFloat:arr[offset + 1]]}, {[self CGFloat:arr[offset + 2]], [self CGFloat:arr[offset + 3]]}, }; } + (CGColorRef)CGColor:(id)json offset:(NSUInteger)offset { NSArray *arr = [self NSArray:json]; if (arr.count < offset + 4) { RCTLogError(@"Too few elements in array (expected at least %llu): %@", (unsigned long long)(4 + offset), arr); return NULL; } return [self CGColor:[arr subarrayWithRange:(NSRange){offset, 4}]]; } + (CGGradientRef)CGGradient:(id)json offset:(NSUInteger)offset { NSArray *arr = [self NSArray:json]; if (arr.count < offset) { RCTLogError(@"Too few elements in array (expected at least %llu): %@", (unsigned long long)offset, arr); return NULL; } arr = [arr subarrayWithRange:(NSRange){offset, arr.count - offset}]; ARTCGFloatArray colorsAndOffsets = [self ARTCGFloatArray:arr]; size_t stops = colorsAndOffsets.count / 5; CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); CGGradientRef gradient = CGGradientCreateWithColorComponents( rgb, colorsAndOffsets.array, colorsAndOffsets.array + stops * 4, stops ); CGColorSpaceRelease(rgb); free(colorsAndOffsets.array); return (CGGradientRef)CFAutorelease(gradient); } @end ================================================ FILE: ios/ViewManagers/ARTGroupManager.h ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTNodeManager.h" @interface ARTGroupManager : ARTNodeManager @end ================================================ FILE: ios/ViewManagers/ARTGroupManager.m ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTGroupManager.h" #import "ARTGroup.h" #import "RCTConvert+ART.h" @implementation ARTGroupManager RCT_EXPORT_MODULE() - (ARTNode *)node { return [ARTGroup new]; } RCT_EXPORT_VIEW_PROPERTY(clipping, CGRect) @end ================================================ FILE: ios/ViewManagers/ARTNodeManager.h ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import @class ARTNode; @interface ARTNodeManager : RCTViewManager - (ARTNode *)node; @end ================================================ FILE: ios/ViewManagers/ARTNodeManager.m ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTNodeManager.h" #import "ARTNode.h" @implementation ARTNodeManager RCT_EXPORT_MODULE() - (ARTNode *)node { return [ARTNode new]; } - (UIView *)view { return [self node]; } - (RCTShadowView *)shadowView { return nil; } RCT_EXPORT_VIEW_PROPERTY(opacity, CGFloat) RCT_EXPORT_VIEW_PROPERTY(transform, CGAffineTransform) RCT_EXPORT_VIEW_PROPERTY(shadow, ARTShadow) @end ================================================ FILE: ios/ViewManagers/ARTRenderableManager.h ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTNodeManager.h" #import "ARTRenderable.h" @interface ARTRenderableManager : ARTNodeManager - (ARTRenderable *)node; @end ================================================ FILE: ios/ViewManagers/ARTRenderableManager.m ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTRenderableManager.h" #import "RCTConvert+ART.h" @implementation ARTRenderableManager RCT_EXPORT_MODULE() - (ARTRenderable *)node { return [ARTRenderable new]; } RCT_EXPORT_VIEW_PROPERTY(strokeWidth, CGFloat) RCT_EXPORT_VIEW_PROPERTY(strokeCap, CGLineCap) RCT_EXPORT_VIEW_PROPERTY(strokeJoin, CGLineJoin) RCT_EXPORT_VIEW_PROPERTY(fill, ARTBrush) RCT_EXPORT_VIEW_PROPERTY(stroke, CGColor) RCT_EXPORT_VIEW_PROPERTY(strokeDash, ARTCGFloatArray) @end ================================================ FILE: ios/ViewManagers/ARTShapeManager.h ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTRenderableManager.h" @interface ARTShapeManager : ARTRenderableManager @end ================================================ FILE: ios/ViewManagers/ARTShapeManager.m ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTShapeManager.h" #import "ARTShape.h" #import "RCTConvert+ART.h" @implementation ARTShapeManager RCT_EXPORT_MODULE() - (ARTRenderable *)node { return [ARTShape new]; } RCT_EXPORT_VIEW_PROPERTY(d, CGPath) @end ================================================ FILE: ios/ViewManagers/ARTSurfaceViewManager.h ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import @interface ARTSurfaceViewManager : RCTViewManager @end ================================================ FILE: ios/ViewManagers/ARTSurfaceViewManager.m ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTSurfaceViewManager.h" #import "ARTSurfaceView.h" @implementation ARTSurfaceViewManager RCT_EXPORT_MODULE() - (UIView *)view { return [ARTSurfaceView new]; } @end ================================================ FILE: ios/ViewManagers/ARTTextManager.h ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTRenderableManager.h" @interface ARTTextManager : ARTRenderableManager @end ================================================ FILE: ios/ViewManagers/ARTTextManager.m ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "ARTTextManager.h" #import "ARTText.h" #import "RCTConvert+ART.h" @implementation ARTTextManager RCT_EXPORT_MODULE() - (ARTRenderable *)node { return [ARTText new]; } RCT_EXPORT_VIEW_PROPERTY(alignment, CTTextAlignment) RCT_REMAP_VIEW_PROPERTY(frame, textFrame, ARTTextFrame) @end ================================================ FILE: jest.config.js ================================================ module.exports = { preset: 'react-native', }; ================================================ FILE: lib/ARTSerializablePath.js ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow */ import Class from 'art/core/class'; import Path from 'art/core/path'; const MOVE_TO = 0; const CLOSE = 1; const LINE_TO = 2; const CURVE_TO = 3; const ARC = 4; // TODO: Refactor to class const SerializablePath = Class(Path, { initialize: function(path: string | SerializablePath) { this.reset(); if (path instanceof SerializablePath) { this.path = path.path.slice(0); } else if (path) { this.push(path); } }, onReset: function() { this.path = []; }, onMove: function(sx: number, sy: number, x: number, y: number) { this.path.push(MOVE_TO, x, y); }, onLine: function(sx: number, sy: number, x: number, y: number) { this.path.push(LINE_TO, x, y); }, onBezierCurve: function( sx: number, sy: number, p1x: number, p1y: number, p2x: number, p2y: number, x: number, y: number, ) { this.path.push(CURVE_TO, p1x, p1y, p2x, p2y, x, y); }, _arcToBezier: Path.prototype.onArc, onArc: function( sx: number, sy: number, ex: number, ey: number, cx: number, cy: number, rx: number, ry: number, sa: number, ea: number, ccw: boolean, rotation: number, ) { if (rx !== ry || rotation) { return this._arcToBezier( sx, sy, ex, ey, cx, cy, rx, ry, sa, ea, ccw, rotation, ); } this.path.push(ARC, cx, cy, rx, sa, ea, ccw ? 0 : 1); }, onClose: function() { this.path.push(CLOSE); }, toJSON: function() { return this.path; }, }); export default SerializablePath; ================================================ FILE: lib/ClippingRectangle.js ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow */ import * as React from 'react'; import {extractOpacity, extractTransform, extractShadow} from './helpers'; import {NativeGroup} from './nativeComponents'; import type {OpacityProps, TransformProps, ShadowProps} from './types'; type ClippingRectangleProps = OpacityProps & TransformProps & ShadowProps & { x: number, y: number, width: number, height: number, children?: React.Node, }; export default class ClippingRectangle extends React.Component { static defaultProps = { x: 0, y: 0, width: 0, height: 0, }; render() { const clipping = [ this.props.x, this.props.y, this.props.width, this.props.height, ]; // The current clipping API requires x and y to be ignored in the transform // $FlowFixMe const {x, y, ...propsExcludingXAndY} = this.props; return ( {this.props.children} ); } } ================================================ FILE: lib/Group.js ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow */ import * as React from 'react'; import PropTypes from 'prop-types'; import invariant from 'invariant'; import {NativeGroup} from './nativeComponents'; import {extractOpacity, extractTransform, extractShadow} from './helpers'; import type {OpacityProps, TransformProps, ShadowProps} from './types'; type GroupProps = OpacityProps & ShadowProps & TransformProps & { children: React.Node, }; export default class Group extends React.Component { static contextTypes = { isInSurface: PropTypes.bool.isRequired, }; render() { invariant( this.context.isInSurface, 'ART: must be a child of a ', ); return ( {this.props.children} ); } } ================================================ FILE: lib/LinearGradient.js ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow */ import {insertColorStopsIntoArray} from './helpers'; import type {GradientStops, Brush} from './types'; const LINEAR_GRADIENT = 1; export default function LinearGradient( stops: GradientStops, x1?: number, y1?: number, x2?: number, y2?: number, ): Brush { const type = LINEAR_GRADIENT; if (arguments.length < 5) { const angle = ((x1 == null ? 270 : x1) * Math.PI) / 180; let x = Math.cos(angle); let y = -Math.sin(angle); const l = (Math.abs(x) + Math.abs(y)) / 2; x *= l; y *= l; x1 = 0.5 - x; x2 = 0.5 + x; y1 = 0.5 - y; y2 = 0.5 + y; this._bb = true; } else { this._bb = false; } const brushData = [type, +x1, +y1, +x2, +y2]; insertColorStopsIntoArray(stops, brushData, 5); this._brush = brushData; return this; } ================================================ FILE: lib/Pattern.js ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow */ import type {Brush} from './types'; const PATTERN = 3; export default function Pattern( url: number, width: number, height: number, left?: number, top?: number, ): Brush { return { _brush: [PATTERN, url, +left || 0, +top || 0, +width, +height], }; } ================================================ FILE: lib/RadialGradient.js ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow */ import {insertDoubleColorStopsIntoArray} from './helpers'; import type {GradientStops, Brush} from './types'; const RADIAL_GRADIENT = 2; export default function RadialGradient( stops: GradientStops, fx?: number, fy?: number, rx?: number, ry?: number, cx?: number, cy?: number, ): Brush { if (ry == null) { ry = rx; } if (cx == null) { cx = fx; } if (cy == null) { cy = fy; } if (fx == null) { // As a convenience we allow the whole radial gradient to cover the // bounding box. We should consider dropping this API. fx = fy = rx = ry = cx = cy = 0.5; this._bb = true; } else { this._bb = false; } // The ART API expects the radial gradient to be repeated at the edges. // To simulate this we render the gradient twice as large and add double // color stops. Ideally this API would become more restrictive so that this // extra work isn't needed. const brushData = [RADIAL_GRADIENT, +fx, +fy, +rx * 2, +ry * 2, +cx, +cy]; insertDoubleColorStopsIntoArray(stops, brushData, 7); this._brush = brushData; return this; } ================================================ FILE: lib/Shape.js ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow */ import * as React from 'react'; import {NativeShape} from './nativeComponents'; import Path from './ARTSerializablePath'; import { extractTransform, extractShadow, extractOpacity, childrenAsString, extractColor, extractStrokeJoin, extractStrokeCap, extractBrush, } from './helpers'; import type { TransformProps, ShadowProps, OpacityProps, StrokeJoin, StrokeCap, Brush, } from './types'; export type ShapeProps = TransformProps & ShadowProps & OpacityProps & { fill?: string | Brush, stroke?: string, strokeCap?: StrokeCap, strokeDash?: Array, strokeJoin?: StrokeJoin, strokeWidth: number, children?: React.Node, d?: string | Path, children?: string | Array, width: number, height: number, }; export default class Shape extends React.Component { static defaultProps = { strokeWidth: 1, width: 0, height: 0, }; render() { const props = this.props; const path = props.d || childrenAsString(props.children); const d = (path instanceof Path ? path : new Path(path)).toJSON(); return ( ); } } ================================================ FILE: lib/Surface.js ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow */ import * as React from 'react'; import PropTypes from 'prop-types'; import {NativeSurfaceView} from './nativeComponents'; type SurfaceProps = { height: number, width: number, children: React.Node, style?: any, }; export default class Surface extends React.Component { static childContextTypes = { isInSurface: PropTypes.bool, }; static defaultProps = { height: 0, width: 0, }; getChildContext() { return {isInSurface: true}; } render() { const {height, width} = this.props; return ( {this.props.children} ); } } ================================================ FILE: lib/Text.js ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow */ import * as React from 'react'; import Path from './ARTSerializablePath'; import {NativeText} from './nativeComponents'; import { extractBrush, extractOpacity, extractColor, extractStrokeCap, extractStrokeJoin, extractTransform, extractShadow, extractAlignment, childrenAsString, extractFontAndLines, } from './helpers'; import type { TransformProps, ShadowProps, OpacityProps, Alignment, Brush, StrokeCap, StrokeJoin, Font, } from './types'; export type TextProps = TransformProps & ShadowProps & OpacityProps & { fill?: string | Brush, stroke?: string, strokeCap?: StrokeCap, strokeDash?: mixed, strokeJoin?: StrokeJoin, strokeWidth?: mixed, children?: string | Array, width: number, height: number, alignment?: Alignment, font?: string | Font, path?: string | Path, }; export default class Text extends React.Component { static defaultProps = { strokeWidth: 1, width: 0, height: 0, }; render() { const props = this.props; const path = props.path; const textPath = path ? (path instanceof Path ? path : new Path(path)).toJSON() : null; const textFrame = extractFontAndLines( props.font, childrenAsString(props.children), ); return ( ); } } ================================================ FILE: lib/__tests__/helpers.test.js ================================================ // @flow import { childrenAsString, extractOpacity, extractStrokeJoin, extractStrokeCap, extractAlignment, } from '../helpers'; describe('testing childrenAsString function', () => { it('returns a given string', () => { expect(childrenAsString('abc')).toBe('abc'); }); it('joins array of strings with \n', () => { let received = childrenAsString(['a', 'b', 'c', 'd']); expect(received.replace(new RegExp('\r?\n', 'g'), '')).toBe('abcd'); }); }); describe('testing extractOpacity function', () => { it('returns 0 if visible is false', () => { expect(extractOpacity({visible: false})).toBe(0); expect(extractOpacity({visible: false, opacity: 1})).toBe(0); expect(extractOpacity({visible: false, opacity: 0.5})).toBe(0); }); it('returns opacity if visible is true or undefined', () => { expect(extractOpacity({visible: true, opacity: 0.5})).toBe(0.5); expect(extractOpacity({opacity: 0.5})).toBe(0.5); }); }); describe('testing extractStrokeJoin', () => { const MITER = 0; const BEVEL = 2; const ROUND = 1; it('returns enum', () => { expect(extractStrokeJoin('miter')).toBe(MITER); expect(extractStrokeJoin('bevel')).toBe(BEVEL); expect(extractStrokeJoin('round')).toBe(ROUND); }); it('default to round', () => { expect(extractStrokeJoin()).toBe(ROUND); }); }); describe('testing extractStrokeCap', () => { const BUTT = 0; const SQUARE = 2; const ROUND = 1; it('returns enum', () => { expect(extractStrokeCap('butt')).toBe(BUTT); expect(extractStrokeCap('square')).toBe(SQUARE); expect(extractStrokeCap('round')).toBe(ROUND); }); it('default to round', () => { expect(extractStrokeCap()).toBe(ROUND); }); }); describe('testing extractAlignment', () => { const CENTER = 1; const RIGHT = 2; const LEFT = 0; it('returns enum', () => { expect(extractAlignment('center')).toBe(RIGHT); expect(extractAlignment('right')).toBe(CENTER); expect(extractAlignment('left')).toBe(LEFT); }); it('default to left', () => { expect(extractAlignment()).toBe(LEFT); }); }); ================================================ FILE: lib/helpers.js ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow */ import processColor from 'react-native/Libraries/StyleSheet/processColor'; import Color from 'art/core/color'; import Transform from 'art/core/transform'; import {Platform} from 'react-native'; import type { Alignment, Brush, ColorType, Font, GradientStops, OpacityProps, StrokeCap, StrokeJoin, TransformProps, ShadowProps, } from './types'; export function childrenAsString(children?: string | Array) { if (!children) { return ''; } if (typeof children === 'string') { return children; } if (children.length) { return children.join('\n'); } return ''; } export function extractOpacity({visible, opacity}: OpacityProps) { // TODO: visible === false should also have no hit detection if (visible === false) { return 0; } if (opacity == null) { return 1; } return +opacity; } const pooledTransform = new Transform(); export function extractTransform(props: TransformProps): Array { const scaleX = props.scaleX != null ? props.scaleX : props.scale != null ? props.scale : 1; const scaleY = props.scaleY != null ? props.scaleY : props.scale != null ? props.scale : 1; pooledTransform .transformTo(1, 0, 0, 1, 0, 0) .move(props.x || 0, props.y || 0) .rotate(props.rotation || 0, props.originX, props.originY) .scale(scaleX, scaleY); if (props.transform != null) { pooledTransform.transform(props.transform); } return [ pooledTransform.xx, pooledTransform.yx, pooledTransform.xy, pooledTransform.yy, pooledTransform.x, pooledTransform.y, ]; } function toHex(color: Color) { const intValues = [color.red, color.green, color.blue]; if (color.alpha < 1) { // Android uses AARRGGBB ; iOS uses RRGGBBAA // https://developer.android.com/reference/android/graphics/Color.html#parseColor(java.lang.String) const position = Platform.OS === 'android' ? 0 : 3; intValues.splice(position, 0, Math.round(color.alpha * 255)); } const hexValues = intValues.map(iv => { const sv = iv.toString(16); return sv.length === 1 ? '0' + sv : sv; }); return '#' + hexValues.join(''); } export function extractShadow( props: ShadowProps, ): Array | void { if ( !props.shadowColor && !props.shadowOpacity && !props.shadowRadius && !props.shadowOffset ) { return; } let opacity = props.shadowOpacity; if (opacity === null || opacity === undefined) { opacity = 1; } return [ processColor(props.shadowColor || 'black'), opacity, props.shadowRadius || 4, props.shadowOffset?.x || 0, props.shadowOffset?.y || 0, ]; } export function extractColor(color?: ColorType) { if (color == null) { return null; } return toHex(new Color(color)); } export function extractStrokeJoin(strokeJoin?: StrokeJoin) { switch (strokeJoin) { case 'miter': return 0; case 'bevel': return 2; default: return 1; // round } } export function extractStrokeCap(strokeCap?: StrokeCap) { switch (strokeCap) { case 'butt': return 0; case 'square': return 2; default: return 1; // round } } const SOLID_COLOR = 0; const LINEAR_GRADIENT = 1; const RADIAL_GRADIENT = 2; const PATTERN = 3; // TODO: Refactor and simplify applyBoundingBoxToBrushData and extractBrush function applyBoundingBoxToBrushData( brushData: Array, props: {width: number, height: number}, ) { const type = brushData[0]; const width = +props.width; const height = +props.height; if (type === LINEAR_GRADIENT) { brushData[1] *= width; brushData[2] *= height; brushData[3] *= width; brushData[4] *= height; } else if (type === RADIAL_GRADIENT) { brushData[1] *= width; brushData[2] *= height; brushData[3] *= width; brushData[4] *= height; brushData[5] *= width; brushData[6] *= height; } else if (type === PATTERN) { // todo } } export function extractBrush( colorOrBrush?: Brush | string, props: {width: number, height: number}, ) { if (colorOrBrush == null) { return null; } if (colorOrBrush._brush) { if (colorOrBrush._bb) { // The legacy API for Gradients allow for the bounding box to be used // as a convenience for specifying gradient positions. This should be // deprecated. It's not properly implemented in canvas mode. ReactART // doesn't handle update to the bounding box correctly. That's why we // mutate this so that if it's reused, we reuse the same resolved box. // $FlowFixMe applyBoundingBoxToBrushData(colorOrBrush._brush, props); // $FlowFixMe colorOrBrush._bb = false; } return colorOrBrush._brush; } const c = new Color(colorOrBrush); return [SOLID_COLOR, c.red / 255, c.green / 255, c.blue / 255, c.alpha]; } export function extractAlignment(alignment?: Alignment) { switch (alignment) { case 'right': return 1; case 'center': return 2; default: return 0; // left } } const cachedFontObjectsFromString = {}; const fontFamilyPrefix = /^[\s"']*/; const fontFamilySuffix = /[\s"']*$/; function extractSingleFontFamily(fontFamilyString: string) { // ART on the web allows for multiple font-families to be specified. // For compatibility, we extract the first font-family, hoping // we'll get a match. return fontFamilyString .split(',')[0] .replace(fontFamilyPrefix, '') .replace(fontFamilySuffix, ''); } function parseFontString(font: string) { if (cachedFontObjectsFromString.hasOwnProperty(font)) { return cachedFontObjectsFromString[font]; } const regexp = /^\s*((?:(?:normal|bold|italic)\s+)*)(?:(\d+(?:\.\d+)?)[ptexm\%]*(?:\s*\/.*?)?\s+)?\s*\"?([^\"]*)/i; const match = regexp.exec(font); if (!match) { return null; } const fontFamily = extractSingleFontFamily(match[3]); const fontSize = +match[2] || 12; const isBold = /bold/.exec(match[1]); const isItalic = /italic/.exec(match[1]); cachedFontObjectsFromString[font] = { fontFamily: fontFamily, fontSize: fontSize, fontWeight: isBold ? 'bold' : 'normal', fontStyle: isItalic ? 'italic' : 'normal', }; return cachedFontObjectsFromString[font]; } function extractFont(font?: string | Font) { if (font == null) { return null; } if (typeof font === 'string') { return parseFontString(font); } const fontFamily = extractSingleFontFamily(font.fontFamily); const fontSize = +font.fontSize || 12; const fontWeight = font.fontWeight != null ? font.fontWeight.toString() : '400'; return { // Normalize fontFamily: fontFamily, fontSize: fontSize, fontWeight: fontWeight, fontStyle: font.fontStyle, }; } const newLine = /\n/g; export function extractFontAndLines(font?: string | Font, text: string) { return {font: extractFont(font), lines: text.split(newLine)}; } function insertColorIntoArray(color: ColorType, targetArray, atIndex) { const c = new Color(color); targetArray[atIndex + 0] = c.red / 255; targetArray[atIndex + 1] = c.green / 255; targetArray[atIndex + 2] = c.blue / 255; targetArray[atIndex + 3] = c.alpha; } function insertColorsIntoArray( stops: GradientStops, targetArray: Array, atIndex: number, ) { let i = 0; if ('length' in stops) { // $FlowFixMe: stops is Array here while (i < stops.length) { // $FlowFixMe: stops is Array here insertColorIntoArray(stops[i], targetArray, atIndex + i * 4); i++; } } else { // $FlowFixMe stops is Object here for (const offset in stops) { insertColorIntoArray(stops[offset], targetArray, atIndex + i * 4); i++; } } return atIndex + i * 4; } function insertOffsetsIntoArray( stops: GradientStops, targetArray: Array, atIndex: number, multi: number, reverse: boolean, ) { let offsetNumber; let i = 0; if ('length' in stops) { // $FlowFixMe: stops is Array here while (i < stops.length) { // $FlowFixMe: stops is Array here offsetNumber = (i / (stops.length - 1)) * multi; targetArray[atIndex + i] = reverse ? 1 - offsetNumber : offsetNumber; i++; } } else { // $FlowFixMe stops is Object here for (const offsetString in stops) { offsetNumber = +offsetString * multi; targetArray[atIndex + i] = reverse ? 1 - offsetNumber : offsetNumber; i++; } } return atIndex + i; } export function insertColorStopsIntoArray( stops: GradientStops, targetArray: Array, atIndex: number, ) { const lastIndex = insertColorsIntoArray(stops, targetArray, atIndex); insertOffsetsIntoArray(stops, targetArray, lastIndex, 1, false); } export function insertDoubleColorStopsIntoArray( stops: GradientStops, targetArray: Array, atIndex: number, ) { let lastIndex = insertColorsIntoArray(stops, targetArray, atIndex); lastIndex = insertColorsIntoArray(stops, targetArray, lastIndex); lastIndex = insertOffsetsIntoArray(stops, targetArray, lastIndex, 0.5, false); insertOffsetsIntoArray(stops, targetArray, lastIndex, 0.5, true); } ================================================ FILE: lib/index.js ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow */ export {default as Transform} from 'art/core/transform'; export {default as Path} from './ARTSerializablePath'; export {default as Surface} from './Surface'; export {default as Group} from './Group'; export {default as Shape} from './Shape'; export {default as Text} from './Text'; export {default as ClippingRectangle} from './ClippingRectangle'; export {default as LinearGradient} from './LinearGradient'; export {default as RadialGradient} from './RadialGradient'; export {default as Pattern} from './Pattern'; ================================================ FILE: lib/nativeComponents.js ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow */ import {requireNativeComponent} from 'react-native'; const NativeSurfaceView = requireNativeComponent('ARTSurfaceView'); const NativeGroup = requireNativeComponent('ARTGroup'); const NativeShape = requireNativeComponent('ARTShape'); const NativeText = requireNativeComponent('ARTText'); export {NativeSurfaceView, NativeGroup, NativeShape, NativeText}; ================================================ FILE: lib/types.js ================================================ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow */ export type OpacityProps = { visible?: boolean, opacity?: number, }; export type TransformProps = { scaleX?: number, scaleY?: number, scale?: number, x?: number, y?: number, rotation?: number, originX?: number, originY?: number, transform?: { y?: number, x?: number, yy?: number, xx?: number, yx?: number, xy?: number, }, }; export type ShadowProps = { shadowOpacity?: number, shadowColor?: string | number, shadowRadius?: number, shadowOffset?: {x: number, y: number}, }; export type ARTColor = { isColor: true, red: string, green: string, blue: string, alpha: string, }; export type ColorType = string | number | ARTColor; export type StrokeJoin = 'miter' | 'bevel' | 'round'; export type StrokeCap = 'butt' | 'square' | 'round'; export type Alignment = 'center' | 'right' | 'left'; export type Brush = {_brush: Array, _bb?: boolean}; export type Font = { fontFamily: string, fontSize?: number, fontWeight?: string, fontStyle?: string, }; export type GradientStops = {[key: string]: ColorType} | Array; ================================================ FILE: package.json ================================================ { "name": "@react-native-community/art", "version": "1.2.0", "license": "MIT", "author": "@react-native-community", "homepage": "https://github.com/react-native-community/react-native-art", "description": "React Native module that allows you to draw vector graphics", "main": "./lib/index.js", "keywords": [ "react-native", "react native", "react-native-art", "react-native-community", "art" ], "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start", "android": "react-native run-android --root example", "ios": "react-native run-ios --project-path example/ios --scheme example", "flow-check": "flow check", "lint": "eslint . --cache", "test": "jest" }, "dependencies": { "art": "^0.10.3", "invariant": "^2.2.4", "prop-types": "^15.7.2" }, "peerDependencies": { "react": "*", "react-native": "*" }, "devDependencies": { "@babel/core": "^7.4.5", "@babel/runtime": "^7.4.5", "@react-native-community/eslint-config": "^0.0.5", "eslint": "^5.16.0", "flow-bin": "^0.92.0", "jest": "^24.8.0", "metro-react-native-babel-preset": "^0.54.1", "react": "16.8.3", "react-native": "0.59.9" } }