chore: add CI for JS, iOS and Android formatting (#1782)

Added CI workflow and local pre-commit hook for formatting and linting the newly added JS, iOS and Android code.
This commit is contained in:
Wojciech Lewicki
2022-08-16 12:00:32 +02:00
committed by GitHub
parent 77267be5fc
commit 98c14b4f45
177 changed files with 16855 additions and 16018 deletions

91
.clang-format Normal file
View File

@@ -0,0 +1,91 @@
---
AccessModifierOffset: -1
AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: true
AlignOperands: false
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: true
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: false
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ForEachMacros: [ FOR_EACH_RANGE, FOR_EACH, ]
IncludeCategories:
- Regex: '^<.*\.h(pp)?>'
Priority: 1
- Regex: '^<.*'
Priority: 2
- Regex: '.*'
Priority: 3
IndentCaseLabels: true
IndentWidth: 2
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Right
ReflowComments: true
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 8
UseTab: Never
---
Language: ObjC
ColumnLimit: 120
BreakBeforeBraces: WebKit
...

View File

@@ -25,10 +25,8 @@ jobs:
run: yarn run: yarn
- name: Build - name: Build
run: yarn bob run: yarn bob
- name: Lint - name: Test and lint
run: yarn lint run: yarn test
- name: Tests
run: yarn jest
- name: Build Example App - name: Build Example App
working-directory: Example/ working-directory: Example/
run: yarn && yarn tsc run: yarn && yarn tsc

4
.husky/pre-commit Executable file
View File

@@ -0,0 +1,4 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
yarn lint-staged

View File

@@ -501,7 +501,7 @@ SPEC CHECKSUMS:
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
DoubleConversion: 831926d9b8bf8166fd87886c4abab286c2422662 DoubleConversion: 831926d9b8bf8166fd87886c4abab286c2422662
FBLazyVector: bcdeff523be9f87a135b7c6fde8736db94904716 FBLazyVector: bcdeff523be9f87a135b7c6fde8736db94904716
FBReactNativeSpec: 226f8b0f1a2e736a49301883ee34bca88cdc24f6 FBReactNativeSpec: 0c3f104f594b34d7b3a923cd12e03b0d4e12eaf5
Flipper: 26fc4b7382499f1281eb8cb921e5c3ad6de91fe0 Flipper: 26fc4b7382499f1281eb8cb921e5c3ad6de91fe0
Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c
Flipper-DoubleConversion: 57ffbe81ef95306cc9e69c4aa3aeeeeb58a6a28c Flipper-DoubleConversion: 57ffbe81ef95306cc9e69c4aa3aeeeeb58a6a28c

View File

@@ -129,16 +129,20 @@ import * as React from 'react';
import { SvgUri } from 'react-native-svg'; import { SvgUri } from 'react-native-svg';
export default () => { export default () => {
const [uri, setUri] = React.useState('https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/not_existing.svg') const [uri, setUri] = React.useState(
'https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/not_existing.svg',
);
return ( return (
<SvgUri <SvgUri
onError={() => setUri('https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/ruby.svg')} onError={() =>
setUri('https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/ruby.svg')
}
width="100%" width="100%"
height="100%" height="100%"
uri={uri} uri={uri}
/> />
); );
} };
``` ```
# Use with svg files # Use with svg files

View File

@@ -10,6 +10,7 @@ buildscript {
dependencies { dependencies {
classpath("com.android.tools.build:gradle:3.6.1") classpath("com.android.tools.build:gradle:3.6.1")
classpath "com.diffplug.spotless:spotless-plugin-gradle:5.15.0"
} }
} }
} }
@@ -26,6 +27,10 @@ if (isNewArchitectureEnabled()) {
apply plugin: "com.facebook.react" apply plugin: "com.facebook.react"
} }
if (project == rootProject) {
apply from: 'spotless.gradle'
}
apply plugin: 'com.android.library' apply plugin: 'com.android.library'
def safeExtGet(prop, fallback) { def safeExtGet(prop, fallback) {

Binary file not shown.

View File

@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

240
android/gradlew vendored Executable file
View File

@@ -0,0 +1,240 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original 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
#
# https://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 POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${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 "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# 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 ;; #(
MSYS* | 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" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

91
android/gradlew.bat vendored Normal file
View File

@@ -0,0 +1,91 @@
@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 https://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 Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@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% equ 0 goto execute
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 execute
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
: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 %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 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!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

9
android/spotless.gradle Normal file
View File

@@ -0,0 +1,9 @@
// formatter & linter configuration for java
apply plugin: 'com.diffplug.spotless'
spotless {
java {
target 'src/fabric/**/*.java', 'src/main/java/**/*.java', 'src/paper/java/com/horcrux/svg/**/*.java'
googleJavaFormat()
}
}

View File

@@ -1,22 +1,21 @@
package com.horcrux.svg; package com.horcrux.svg;
import android.content.Context; import android.content.Context;
import android.view.ViewGroup;
import androidx.annotation.UiThread; import androidx.annotation.UiThread;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeMap; import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.uimanager.FabricViewStateManager; import com.facebook.react.uimanager.FabricViewStateManager;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.FabricViewStateManager.HasFabricViewStateManager; import com.facebook.react.uimanager.FabricViewStateManager.HasFabricViewStateManager;
import com.facebook.react.uimanager.FabricViewStateManager.StateUpdateCallback; import com.facebook.react.uimanager.FabricViewStateManager.StateUpdateCallback;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.views.view.ReactViewGroup; import com.facebook.react.views.view.ReactViewGroup;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public abstract class FabricEnabledViewGroup extends ReactViewGroup implements HasFabricViewStateManager { public abstract class FabricEnabledViewGroup extends ReactViewGroup
implements HasFabricViewStateManager {
private final FabricViewStateManager mFabricViewStateManager = new FabricViewStateManager(); private final FabricViewStateManager mFabricViewStateManager = new FabricViewStateManager();
@NotNull @NotNull
@@ -35,15 +34,19 @@ public abstract class FabricEnabledViewGroup extends ReactViewGroup implements H
ReadableMap currentState = this.mFabricViewStateManager.getStateData(); ReadableMap currentState = this.mFabricViewStateManager.getStateData();
if (currentState != null) { if (currentState != null) {
float delta = 0.9F; float delta = 0.9F;
float stateFrameHeight = currentState.hasKey("frameHeight") ? (float)currentState.getDouble("frameHeight") : 0.0F; float stateFrameHeight =
float stateFrameWidth = currentState.hasKey("frameWidth") ? (float)currentState.getDouble("frameWidth") : 0.0F; currentState.hasKey("frameHeight") ? (float) currentState.getDouble("frameHeight") : 0.0F;
if (Math.abs(stateFrameWidth - realWidth) < delta && float stateFrameWidth =
Math.abs(stateFrameHeight - realHeight) < delta) { currentState.hasKey("frameWidth") ? (float) currentState.getDouble("frameWidth") : 0.0F;
if (Math.abs(stateFrameWidth - realWidth) < delta
&& Math.abs(stateFrameHeight - realHeight) < delta) {
return; return;
} }
} }
this.mFabricViewStateManager.setState((StateUpdateCallback)(new StateUpdateCallback() { this.mFabricViewStateManager.setState(
(StateUpdateCallback)
(new StateUpdateCallback() {
public final WritableMap getStateUpdate() { public final WritableMap getStateUpdate() {
WritableMap map = (WritableMap) (new WritableNativeMap()); WritableMap map = (WritableMap) (new WritableNativeMap());
map.putDouble("frameWidth", (double) realWidth); map.putDouble("frameWidth", (double) realWidth);

View File

@@ -6,7 +6,6 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import android.graphics.Bitmap; import android.graphics.Bitmap;
@@ -19,7 +18,6 @@ import android.graphics.RadialGradient;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.RectF; import android.graphics.RectF;
import android.graphics.Shader; import android.graphics.Shader;
import com.facebook.common.logging.FLog; import com.facebook.common.logging.FLog;
import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.common.ReactConstants; import com.facebook.react.common.ReactConstants;
@@ -63,7 +61,8 @@ class Brush {
USER_SPACE_ON_USE USER_SPACE_ON_USE
} }
private static void parseGradientStops(ReadableArray value, int stopsCount, float[] stops, int[] stopsColors, float opacity) { private static void parseGradientStops(
ReadableArray value, int stopsCount, float[] stops, int[] stopsColors, float opacity) {
for (int i = 0; i < stopsCount; i++) { for (int i = 0; i < stopsCount; i++) {
int stopIndex = i * 2; int stopIndex = i * 2;
stops[i] = (float) value.getDouble(stopIndex); stops[i] = (float) value.getDouble(stopIndex);
@@ -102,8 +101,12 @@ class Brush {
} }
private double getVal(SVGLength length, double relative, float scale, float textSize) { private double getVal(SVGLength length, double relative, float scale, float textSize) {
return PropHelper.fromRelative(length, relative, 0, mUseObjectBoundingBox && return PropHelper.fromRelative(
length.unit == SVGLength.UnitType.NUMBER ? relative : scale, textSize); length,
relative,
0,
mUseObjectBoundingBox && length.unit == SVGLength.UnitType.NUMBER ? relative : scale,
textSize);
} }
void setupPaint(Paint paint, RectF pathBoundingBox, float scale, float opacity) { void setupPaint(Paint paint, RectF pathBoundingBox, float scale, float opacity) {
@@ -124,16 +127,14 @@ class Brush {
return; return;
} }
Bitmap bitmap = Bitmap.createBitmap( Bitmap bitmap = Bitmap.createBitmap((int) w, (int) h, Bitmap.Config.ARGB_8888);
(int) w,
(int) h,
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap); Canvas canvas = new Canvas(bitmap);
RectF vbRect = mPattern.getViewBox(); RectF vbRect = mPattern.getViewBox();
if (vbRect != null && vbRect.width() > 0 && vbRect.height() > 0) { if (vbRect != null && vbRect.width() > 0 && vbRect.height() > 0) {
RectF eRect = new RectF((float) x, (float) y, (float) w, (float) h); RectF eRect = new RectF((float) x, (float) y, (float) w, (float) h);
Matrix mViewBoxMatrix = ViewBox.getTransform(vbRect, eRect, mPattern.mAlign, mPattern.mMeetOrSlice); Matrix mViewBoxMatrix =
ViewBox.getTransform(vbRect, eRect, mPattern.mAlign, mPattern.mMeetOrSlice);
canvas.concat(mViewBoxMatrix); canvas.concat(mViewBoxMatrix);
} }
@@ -148,7 +149,8 @@ class Brush {
patternMatrix.preConcat(mMatrix); patternMatrix.preConcat(mMatrix);
} }
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); BitmapShader bitmapShader =
new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
bitmapShader.setLocalMatrix(patternMatrix); bitmapShader.setLocalMatrix(patternMatrix);
paint.setShader(bitmapShader); paint.setShader(bitmapShader);
return; return;
@@ -181,7 +183,8 @@ class Brush {
double x2 = getVal(mPoints[2], width, scale, textSize) + offsetX; double x2 = getVal(mPoints[2], width, scale, textSize) + offsetX;
double y2 = getVal(mPoints[3], height, scale, textSize) + offsetY; double y2 = getVal(mPoints[3], height, scale, textSize) + offsetY;
Shader linearGradient = new LinearGradient( Shader linearGradient =
new LinearGradient(
(float) x1, (float) x1,
(float) y1, (float) y1,
(float) x2, (float) x2,
@@ -210,14 +213,9 @@ class Brush {
// double fx = PropHelper.fromRelative(mPoints[0], width, offsetX, scale); // double fx = PropHelper.fromRelative(mPoints[0], width, offsetX, scale);
// double fy = PropHelper.fromRelative(mPoints[1], height, offsetY, scale) / (ry / rx); // double fy = PropHelper.fromRelative(mPoints[1], height, offsetY, scale) / (ry / rx);
Shader radialGradient = new RadialGradient( Shader radialGradient =
(float) cx, new RadialGradient(
(float) cy, (float) cx, (float) cy, (float) rx, stopsColors, stops, Shader.TileMode.CLAMP);
(float) rx,
stopsColors,
stops,
Shader.TileMode.CLAMP
);
Matrix radialMatrix = new Matrix(); Matrix radialMatrix = new Matrix();
radialMatrix.preScale(1f, (float) ratio); radialMatrix.preScale(1f, (float) ratio);

View File

@@ -6,15 +6,12 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Path; import android.graphics.Path;
import com.facebook.react.bridge.Dynamic; import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactProp;

View File

@@ -6,13 +6,11 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
import com.facebook.common.logging.FLog; import com.facebook.common.logging.FLog;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
import com.facebook.react.common.ReactConstants; import com.facebook.react.common.ReactConstants;
@@ -26,7 +24,9 @@ class ClipPathView extends GroupView {
@Override @Override
void draw(Canvas canvas, Paint paint, float opacity) { void draw(Canvas canvas, Paint paint, float opacity) {
FLog.w(ReactConstants.TAG, "RNSVG: ClipPath can't be drawn, it should be defined as a child component for `Defs` "); FLog.w(
ReactConstants.TAG,
"RNSVG: ClipPath can't be drawn, it should be defined as a child component for `Defs` ");
} }
@Override @Override

View File

@@ -6,14 +6,12 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Path; import android.graphics.Path;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
@SuppressLint("ViewConstructor") @SuppressLint("ViewConstructor")

View File

@@ -6,14 +6,12 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
import android.view.View; import android.view.View;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
@SuppressLint("ViewConstructor") @SuppressLint("ViewConstructor")

View File

@@ -6,7 +6,6 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
@@ -14,7 +13,6 @@ import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Path; import android.graphics.Path;
import android.graphics.RectF; import android.graphics.RectF;
import com.facebook.react.bridge.Dynamic; import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactProp;
@@ -81,7 +79,8 @@ class EllipseView extends RenderableView {
double cy = relativeOnHeight(mCy); double cy = relativeOnHeight(mCy);
double rx = relativeOnWidth(mRx); double rx = relativeOnWidth(mRx);
double ry = relativeOnHeight(mRy); double ry = relativeOnHeight(mRy);
RectF oval = new RectF((float) (cx - rx), (float) (cy - ry), (float) (cx + rx), (float) (cy + ry)); RectF oval =
new RectF((float) (cx - rx), (float) (cy - ry), (float) (cx + rx), (float) (cy + ry));
path.addOval(oval, Path.Direction.CW); path.addOval(oval, Path.Direction.CW);
return path; return path;

View File

@@ -1,21 +1,22 @@
package com.horcrux.svg; package com.horcrux.svg;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableType;
import static com.facebook.react.uimanager.ViewProps.FONT_FAMILY; import static com.facebook.react.uimanager.ViewProps.FONT_FAMILY;
import static com.facebook.react.uimanager.ViewProps.FONT_SIZE; import static com.facebook.react.uimanager.ViewProps.FONT_SIZE;
import static com.facebook.react.uimanager.ViewProps.FONT_STYLE; import static com.facebook.react.uimanager.ViewProps.FONT_STYLE;
import static com.facebook.react.uimanager.ViewProps.FONT_WEIGHT; import static com.facebook.react.uimanager.ViewProps.FONT_WEIGHT;
import static com.horcrux.svg.TextProperties.*; import static com.horcrux.svg.TextProperties.*;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableType;
class FontData { class FontData {
static class AbsoluteFontWeight { static class AbsoluteFontWeight {
static final int normal = 400; static final int normal = 400;
private static final FontWeight[] WEIGHTS = new FontWeight[]{ private static final FontWeight[] WEIGHTS =
new FontWeight[] {
FontWeight.w100, FontWeight.w100,
FontWeight.w100, FontWeight.w100,
FontWeight.w200, FontWeight.w200,
@@ -33,9 +34,8 @@ class FontData {
return WEIGHTS[Math.round(absoluteFontWeight / 100f)]; return WEIGHTS[Math.round(absoluteFontWeight / 100f)];
} }
private static final int[] absoluteFontWeights = new int[]{ private static final int[] absoluteFontWeights =
400, 700, 100, 200, 300, 400, 500, 600, 700, 800, 900 new int[] {400, 700, 100, 200, 300, 400, 500, 600, 700, 800, 900};
};
// https://drafts.csswg.org/css-fonts-4/#relative-weights // https://drafts.csswg.org/css-fonts-4/#relative-weights
static int from(FontWeight fontWeight, FontData parent) { static int from(FontWeight fontWeight, FontData parent) {
@@ -132,18 +132,14 @@ class FontData {
letterSpacing = DEFAULT_LETTER_SPACING; letterSpacing = DEFAULT_LETTER_SPACING;
} }
private double toAbsolute(ReadableMap font, String prop, double scale, double fontSize, double relative) { private double toAbsolute(
ReadableMap font, String prop, double scale, double fontSize, double relative) {
ReadableType propType = font.getType(prop); ReadableType propType = font.getType(prop);
if (propType == ReadableType.Number) { if (propType == ReadableType.Number) {
return font.getDouble(prop); return font.getDouble(prop);
} else { } else {
String string = font.getString(prop); String string = font.getString(prop);
return PropHelper.fromRelative( return PropHelper.fromRelative(string, relative, scale, fontSize);
string,
relative,
scale,
fontSize
);
} }
} }
@@ -193,13 +189,29 @@ class FontData {
fontData = font.hasKey(FONT_DATA) ? font.getMap(FONT_DATA) : parent.fontData; fontData = font.hasKey(FONT_DATA) ? font.getMap(FONT_DATA) : parent.fontData;
fontFamily = font.hasKey(FONT_FAMILY) ? font.getString(FONT_FAMILY) : parent.fontFamily; fontFamily = font.hasKey(FONT_FAMILY) ? font.getString(FONT_FAMILY) : parent.fontFamily;
fontStyle = font.hasKey(FONT_STYLE) ? FontStyle.valueOf(font.getString(FONT_STYLE)) : parent.fontStyle; fontStyle =
fontFeatureSettings = font.hasKey(FONT_FEATURE_SETTINGS) ? font.getString(FONT_FEATURE_SETTINGS) : parent.fontFeatureSettings; font.hasKey(FONT_STYLE) ? FontStyle.valueOf(font.getString(FONT_STYLE)) : parent.fontStyle;
fontVariationSettings = font.hasKey(FONT_VARIATION_SETTINGS) ? font.getString(FONT_VARIATION_SETTINGS) : parent.fontVariationSettings; fontFeatureSettings =
fontVariantLigatures = font.hasKey(FONT_VARIANT_LIGATURES) ? FontVariantLigatures.valueOf(font.getString(FONT_VARIANT_LIGATURES)) : parent.fontVariantLigatures; font.hasKey(FONT_FEATURE_SETTINGS)
? font.getString(FONT_FEATURE_SETTINGS)
: parent.fontFeatureSettings;
fontVariationSettings =
font.hasKey(FONT_VARIATION_SETTINGS)
? font.getString(FONT_VARIATION_SETTINGS)
: parent.fontVariationSettings;
fontVariantLigatures =
font.hasKey(FONT_VARIANT_LIGATURES)
? FontVariantLigatures.valueOf(font.getString(FONT_VARIANT_LIGATURES))
: parent.fontVariantLigatures;
textAnchor = font.hasKey(TEXT_ANCHOR) ? TextAnchor.valueOf(font.getString(TEXT_ANCHOR)) : parent.textAnchor; textAnchor =
textDecoration = font.hasKey(TEXT_DECORATION) ? TextDecoration.getEnum(font.getString(TEXT_DECORATION)) : parent.textDecoration; font.hasKey(TEXT_ANCHOR)
? TextAnchor.valueOf(font.getString(TEXT_ANCHOR))
: parent.textAnchor;
textDecoration =
font.hasKey(TEXT_DECORATION)
? TextDecoration.getEnum(font.getString(TEXT_DECORATION))
: parent.textDecoration;
final boolean hasKerning = font.hasKey(KERNING); final boolean hasKerning = font.hasKey(KERNING);
manualKerning = hasKerning || parent.manualKerning; manualKerning = hasKerning || parent.manualKerning;
@@ -208,7 +220,13 @@ class FontData {
// https://drafts.csswg.org/css-text-3/#spacing // https://drafts.csswg.org/css-text-3/#spacing
// calculated values for units in: kerning, word-spacing, and, letter-spacing. // calculated values for units in: kerning, word-spacing, and, letter-spacing.
kerning = hasKerning ? toAbsolute(font, KERNING, scale, fontSize, 0) : parent.kerning; kerning = hasKerning ? toAbsolute(font, KERNING, scale, fontSize, 0) : parent.kerning;
wordSpacing = font.hasKey(WORD_SPACING) ? toAbsolute(font, WORD_SPACING, scale, fontSize, 0) : parent.wordSpacing; wordSpacing =
letterSpacing = font.hasKey(LETTER_SPACING) ? toAbsolute(font, LETTER_SPACING, scale, fontSize, 0) : parent.letterSpacing; font.hasKey(WORD_SPACING)
? toAbsolute(font, WORD_SPACING, scale, fontSize, 0)
: parent.wordSpacing;
letterSpacing =
font.hasKey(LETTER_SPACING)
? toAbsolute(font, LETTER_SPACING, scale, fontSize, 0)
: parent.letterSpacing;
} }
} }

View File

@@ -6,7 +6,6 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
@@ -15,9 +14,7 @@ import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.RectF; import android.graphics.RectF;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.facebook.react.bridge.Dynamic; import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactProp;

View File

@@ -6,13 +6,10 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableMap;
import java.util.ArrayList; import java.util.ArrayList;
import javax.annotation.Nullable; import javax.annotation.Nullable;
// https://www.w3.org/TR/SVG/text.html#TSpanElement // https://www.w3.org/TR/SVG/text.html#TSpanElement
@@ -174,7 +171,6 @@ class GlyphContext {
mFontSize = data.fontSize; mFontSize = data.fontSize;
mFontContext.add(data); mFontContext.add(data);
topFont = data; topFont = data;
} }
void pushContext(GroupView node, @Nullable ReadableMap font) { void pushContext(GroupView node, @Nullable ReadableMap font) {
@@ -209,8 +205,7 @@ class GlyphContext {
@Nullable ArrayList<SVGLength> y, @Nullable ArrayList<SVGLength> y,
@Nullable ArrayList<SVGLength> deltaX, @Nullable ArrayList<SVGLength> deltaX,
@Nullable ArrayList<SVGLength> deltaY, @Nullable ArrayList<SVGLength> deltaY,
@Nullable ArrayList<SVGLength> rotate @Nullable ArrayList<SVGLength> rotate) {
) {
if (reset) { if (reset) {
this.reset(); this.reset();
} }
@@ -321,32 +316,24 @@ class GlyphContext {
/** /**
* Get font size from context. * Get font size from context.
* <p> *
* font-size * <p>font-size Value: < absolute-size > | < relative-size > | < length > | < percentage > |
* Value: < absolute-size > | < relative-size > | < length > | < percentage > | inherit * inherit Initial: medium Applies to: text content elements Inherited: yes, the computed value is
* Initial: medium * inherited Percentages: refer to parent element's font size Media: visual Animatable: yes
* Applies to: text content elements *
* Inherited: yes, the computed value is inherited * <p>This property refers to the size of the font from baseline to baseline when multiple lines
* Percentages: refer to parent element's font size * of text are set solid in a multiline layout environment.
* Media: visual *
* Animatable: yes * <p>For SVG, if a < length > is provided without a unit identifier (e.g., an unqualified number
* <p> * such as 128), the SVG user agent processes the < length > as a height value in the current user
* This property refers to the size of the font from baseline to
* baseline when multiple lines of text are set solid in a multiline
* layout environment.
* <p>
* For SVG, if a < length > is provided without a unit identifier
* (e.g., an unqualified number such as 128), the SVG user agent
* processes the < length > as a height value in the current user
* coordinate system. * coordinate system.
* <p> *
* If a < length > is provided with one of the unit identifiers * <p>If a < length > is provided with one of the unit identifiers (e.g., 12pt or 10%), then the
* (e.g., 12pt or 10%), then the SVG user agent converts the * SVG user agent converts the < length > into a corresponding value in the current user
* < length > into a corresponding value in the current user
* coordinate system by applying the rules described in Units. * coordinate system by applying the rules described in Units.
* <p> *
* Except for any additional information provided in this specification, * <p>Except for any additional information provided in this specification, the normative
* the normative definition of the property is in CSS2 ([CSS2], section 15.2.4). * definition of the property is in CSS2 ([CSS2], section 15.2.4).
*/ */
double getFontSize() { double getFontSize() {
return mFontSize; return mFontSize;

View File

@@ -2,7 +2,6 @@ package com.horcrux.svg;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Path; import android.graphics.Path;
import java.util.ArrayList; import java.util.ArrayList;
class GlyphPathBag { class GlyphPathBag {

View File

@@ -6,7 +6,6 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
@@ -19,12 +18,9 @@ import android.graphics.RectF;
import android.graphics.Region; import android.graphics.Region;
import android.os.Build; import android.os.Build;
import android.view.View; import android.view.View;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.views.view.ReactViewGroup;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@SuppressLint("ViewConstructor") @SuppressLint("ViewConstructor")
@@ -58,8 +54,7 @@ class GroupView extends RenderableView {
} }
private static <T> T requireNonNull(T obj) { private static <T> T requireNonNull(T obj) {
if (obj == null) if (obj == null) throw new NullPointerException();
throw new NullPointerException();
return obj; return obj;
} }

View File

@@ -6,7 +6,6 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
@@ -17,7 +16,6 @@ import android.graphics.Paint;
import android.graphics.Path; import android.graphics.Path;
import android.graphics.RectF; import android.graphics.RectF;
import android.net.Uri; import android.net.Uri;
import com.facebook.common.executors.UiThreadImmediateExecutorService; import com.facebook.common.executors.UiThreadImmediateExecutorService;
import com.facebook.common.logging.FLog; import com.facebook.common.logging.FLog;
import com.facebook.common.references.CloseableReference; import com.facebook.common.references.CloseableReference;
@@ -35,9 +33,7 @@ import com.facebook.react.common.ReactConstants;
import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.views.imagehelper.ImageSource; import com.facebook.react.views.imagehelper.ImageSource;
import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper; import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -102,7 +98,6 @@ class ImageView extends RenderableView {
invalidate(); invalidate();
} }
@ReactProp(name = "src") @ReactProp(name = "src")
public void setSrc(@Nullable ReadableMap src) { public void setSrc(@Nullable ReadableMap src) {
if (src != null) { if (src != null) {
@@ -164,9 +159,10 @@ class ImageView extends RenderableView {
private void loadBitmap(final ImagePipeline imagePipeline, final ImageRequest request) { private void loadBitmap(final ImagePipeline imagePipeline, final ImageRequest request) {
mLoading.set(true); mLoading.set(true);
final DataSource<CloseableReference<CloseableImage>> dataSource final DataSource<CloseableReference<CloseableImage>> dataSource =
= imagePipeline.fetchDecodedImage(request, mContext); imagePipeline.fetchDecodedImage(request, mContext);
BaseBitmapDataSubscriber subscriber = new BaseBitmapDataSubscriber() { BaseBitmapDataSubscriber subscriber =
new BaseBitmapDataSubscriber() {
@Override @Override
public void onNewResultImpl(Bitmap bitmap) { public void onNewResultImpl(Bitmap bitmap) {
mLoading.set(false); mLoading.set(false);
@@ -181,7 +177,10 @@ class ImageView extends RenderableView {
// No cleanup required here. // No cleanup required here.
// TODO: more details about this failure // TODO: more details about this failure
mLoading.set(false); mLoading.set(false);
FLog.w(ReactConstants.TAG, dataSource.getFailureCause(), "RNSVG: fetchDecodedImage failed!"); FLog.w(
ReactConstants.TAG,
dataSource.getFailureCause(),
"RNSVG: fetchDecodedImage failed!");
} }
}; };
dataSource.subscribe(subscriber, UiThreadImmediateExecutorService.getInstance()); dataSource.subscribe(subscriber, UiThreadImmediateExecutorService.getInstance());
@@ -228,9 +227,14 @@ class ImageView extends RenderableView {
this.setClientRect(vbRect); this.setClientRect(vbRect);
} }
private void tryRenderFromBitmapCache(ImagePipeline imagePipeline, ImageRequest request, Canvas canvas, Paint paint, float opacity) { private void tryRenderFromBitmapCache(
final DataSource<CloseableReference<CloseableImage>> dataSource ImagePipeline imagePipeline,
= imagePipeline.fetchImageFromBitmapCache(request, mContext); ImageRequest request,
Canvas canvas,
Paint paint,
float opacity) {
final DataSource<CloseableReference<CloseableImage>> dataSource =
imagePipeline.fetchImageFromBitmapCache(request, mContext);
try { try {
final CloseableReference<CloseableImage> imageReference = dataSource.getResult(); final CloseableReference<CloseableImage> imageReference = dataSource.getResult();
@@ -265,5 +269,4 @@ class ImageView extends RenderableView {
dataSource.close(); dataSource.close();
} }
} }
} }

View File

@@ -6,14 +6,12 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Path; import android.graphics.Path;
import com.facebook.react.bridge.Dynamic; import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactProp;

View File

@@ -6,19 +6,16 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.graphics.Matrix; import android.graphics.Matrix;
import com.facebook.common.logging.FLog; import com.facebook.common.logging.FLog;
import com.facebook.react.bridge.Dynamic; import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.common.ReactConstants; import com.facebook.react.common.ReactConstants;
import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactProp;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@SuppressLint("ViewConstructor") @SuppressLint("ViewConstructor")
@@ -31,7 +28,8 @@ class LinearGradientView extends DefinitionView {
private ReadableArray mGradient; private ReadableArray mGradient;
private Brush.BrushUnits mGradientUnits; private Brush.BrushUnits mGradientUnits;
private static final float[] sRawMatrix = new float[]{ private static final float[] sRawMatrix =
new float[] {
1, 0, 0, 1, 0, 0,
0, 1, 0, 0, 1, 0,
0, 0, 1 0, 0, 1

View File

@@ -6,7 +6,6 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
@@ -15,7 +14,6 @@ import android.graphics.Matrix;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.RectF; import android.graphics.RectF;
import android.view.View; import android.view.View;
import com.facebook.react.bridge.Dynamic; import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactProp;
@@ -149,7 +147,8 @@ class MarkerView extends GroupView {
} }
} }
void renderMarker(Canvas canvas, Paint paint, float opacity, RNSVGMarkerPosition position, float strokeWidth) { void renderMarker(
Canvas canvas, Paint paint, float opacity, RNSVGMarkerPosition position, float strokeWidth) {
int count = saveAndSetupCanvas(canvas, mCTM); int count = saveAndSetupCanvas(canvas, mCTM);
markerTransform.reset(); markerTransform.reset();
@@ -169,7 +168,12 @@ class MarkerView extends GroupView {
double height = relativeOnHeight(mMarkerHeight) / mScale; double height = relativeOnHeight(mMarkerHeight) / mScale;
RectF eRect = new RectF(0, 0, (float) width, (float) height); RectF eRect = new RectF(0, 0, (float) width, (float) height);
if (mAlign != null) { if (mAlign != null) {
RectF vbRect = new RectF(mMinX * mScale, mMinY * mScale, (mMinX + mVbWidth) * mScale, (mMinY + mVbHeight) * mScale); RectF vbRect =
new RectF(
mMinX * mScale,
mMinY * mScale,
(mMinX + mVbWidth) * mScale,
(mMinY + mVbHeight) * mScale);
Matrix viewBoxMatrix = ViewBox.getTransform(vbRect, eRect, mAlign, mMeetOrSlice); Matrix viewBoxMatrix = ViewBox.getTransform(vbRect, eRect, mAlign, mMeetOrSlice);
float[] values = new float[9]; float[] values = new float[9];
viewBoxMatrix.getValues(values); viewBoxMatrix.getValues(values);

View File

@@ -6,19 +6,16 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.graphics.Matrix; import android.graphics.Matrix;
import com.facebook.common.logging.FLog; import com.facebook.common.logging.FLog;
import com.facebook.react.bridge.Dynamic; import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.common.ReactConstants; import com.facebook.react.common.ReactConstants;
import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactProp;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@SuppressLint("ViewConstructor") @SuppressLint("ViewConstructor")
@@ -32,10 +29,12 @@ class MaskView extends GroupView {
// TODO implement proper support for units // TODO implement proper support for units
@SuppressWarnings({"FieldCanBeLocal", "unused"}) @SuppressWarnings({"FieldCanBeLocal", "unused"})
private Brush.BrushUnits mMaskUnits; private Brush.BrushUnits mMaskUnits;
@SuppressWarnings({"FieldCanBeLocal", "unused"}) @SuppressWarnings({"FieldCanBeLocal", "unused"})
private Brush.BrushUnits mMaskContentUnits; private Brush.BrushUnits mMaskContentUnits;
private static final float[] sRawMatrix = new float[]{ private static final float[] sRawMatrix =
new float[] {
1, 0, 0, 1, 0, 0,
0, 1, 0, 0, 1, 0,
0, 0, 1 0, 0, 1

View File

@@ -2,12 +2,12 @@ package com.horcrux.svg;
import android.graphics.Path; import android.graphics.Path;
import android.graphics.RectF; import android.graphics.RectF;
import java.util.ArrayList; import java.util.ArrayList;
class PathElement { class PathElement {
ElementType type; ElementType type;
Point[] points; Point[] points;
PathElement(ElementType type, Point[] points) { PathElement(ElementType type, Point[] points) {
this.type = type; this.type = type;
this.points = points; this.points = points;
@@ -98,89 +98,138 @@ class PathParser {
boolean absolute = is_absolute(cmd); boolean absolute = is_absolute(cmd);
switch (cmd) { switch (cmd) {
case 'm': { case 'm':
{
move(parse_list_number(), parse_list_number()); move(parse_list_number(), parse_list_number());
break; break;
} }
case 'M': { case 'M':
{
moveTo(parse_list_number(), parse_list_number()); moveTo(parse_list_number(), parse_list_number());
break; break;
} }
case 'l': { case 'l':
{
line(parse_list_number(), parse_list_number()); line(parse_list_number(), parse_list_number());
break; break;
} }
case 'L': { case 'L':
{
lineTo(parse_list_number(), parse_list_number()); lineTo(parse_list_number(), parse_list_number());
break; break;
} }
case 'h': { case 'h':
{
line(parse_list_number(), 0); line(parse_list_number(), 0);
break; break;
} }
case 'H': { case 'H':
{
lineTo(parse_list_number(), mPenY); lineTo(parse_list_number(), mPenY);
break; break;
} }
case 'v': { case 'v':
{
line(0, parse_list_number()); line(0, parse_list_number());
break; break;
} }
case 'V': { case 'V':
{
lineTo(mPenX, parse_list_number()); lineTo(mPenX, parse_list_number());
break; break;
} }
case 'c': { case 'c':
curve(parse_list_number(), parse_list_number(), parse_list_number(), parse_list_number(), parse_list_number(), parse_list_number()); {
curve(
parse_list_number(),
parse_list_number(),
parse_list_number(),
parse_list_number(),
parse_list_number(),
parse_list_number());
break; break;
} }
case 'C': { case 'C':
curveTo(parse_list_number(), parse_list_number(), parse_list_number(), parse_list_number(), parse_list_number(), parse_list_number()); {
curveTo(
parse_list_number(),
parse_list_number(),
parse_list_number(),
parse_list_number(),
parse_list_number(),
parse_list_number());
break; break;
} }
case 's': { case 's':
smoothCurve(parse_list_number(), parse_list_number(), parse_list_number(), parse_list_number()); {
smoothCurve(
parse_list_number(), parse_list_number(), parse_list_number(), parse_list_number());
break; break;
} }
case 'S': { case 'S':
smoothCurveTo(parse_list_number(), parse_list_number(), parse_list_number(), parse_list_number()); {
smoothCurveTo(
parse_list_number(), parse_list_number(), parse_list_number(), parse_list_number());
break; break;
} }
case 'q': { case 'q':
quadraticBezierCurve(parse_list_number(), parse_list_number(), parse_list_number(), parse_list_number()); {
quadraticBezierCurve(
parse_list_number(), parse_list_number(), parse_list_number(), parse_list_number());
break; break;
} }
case 'Q': { case 'Q':
quadraticBezierCurveTo(parse_list_number(), parse_list_number(), parse_list_number(), parse_list_number()); {
quadraticBezierCurveTo(
parse_list_number(), parse_list_number(), parse_list_number(), parse_list_number());
break; break;
} }
case 't': { case 't':
{
smoothQuadraticBezierCurve(parse_list_number(), parse_list_number()); smoothQuadraticBezierCurve(parse_list_number(), parse_list_number());
break; break;
} }
case 'T': { case 'T':
{
smoothQuadraticBezierCurveTo(parse_list_number(), parse_list_number()); smoothQuadraticBezierCurveTo(parse_list_number(), parse_list_number());
break; break;
} }
case 'a': { case 'a':
arc(parse_list_number(), parse_list_number(), parse_list_number(), parse_flag(), parse_flag(), parse_list_number(), parse_list_number()); {
arc(
parse_list_number(),
parse_list_number(),
parse_list_number(),
parse_flag(),
parse_flag(),
parse_list_number(),
parse_list_number());
break; break;
} }
case 'A': { case 'A':
arcTo(parse_list_number(), parse_list_number(), parse_list_number(), parse_flag(), parse_flag(), parse_list_number(), parse_list_number()); {
arcTo(
parse_list_number(),
parse_list_number(),
parse_list_number(),
parse_flag(),
parse_flag(),
parse_list_number(),
parse_list_number());
break; break;
} }
case 'z': case 'z':
case 'Z': { case 'Z':
{
close(); close();
break; break;
} }
default: { default:
{
throw new Error(String.format("Unexpected comand '%c' (s=%s)", cmd, s)); throw new Error(String.format("Unexpected comand '%c' (s=%s)", cmd, s));
} }
} }
if (is_implicit_move_to) { if (is_implicit_move_to) {
if (absolute) { if (absolute) {
prev_cmd = 'M'; prev_cmd = 'M';
@@ -190,7 +239,6 @@ class PathParser {
} else { } else {
prev_cmd = cmd; prev_cmd = cmd;
} }
} }
return mPath; return mPath;
@@ -205,7 +253,8 @@ class PathParser {
mPenDownX = mPivotX = mPenX = x; mPenDownX = mPivotX = mPenX = x;
mPenDownY = mPivotY = mPenY = y; mPenDownY = mPivotY = mPenY = y;
mPath.moveTo(x * mScale, y * mScale); mPath.moveTo(x * mScale, y * mScale);
elements.add(new PathElement(ElementType.kCGPathElementMoveToPoint, new Point[]{new Point(x,y)})); elements.add(
new PathElement(ElementType.kCGPathElementMoveToPoint, new Point[] {new Point(x, y)}));
} }
private static void line(float x, float y) { private static void line(float x, float y) {
@@ -218,7 +267,8 @@ class PathParser {
mPivotX = mPenX = x; mPivotX = mPenX = x;
mPivotY = mPenY = y; mPivotY = mPenY = y;
mPath.lineTo(x * mScale, y * mScale); mPath.lineTo(x * mScale, y * mScale);
elements.add(new PathElement(ElementType.kCGPathElementAddLineToPoint, new Point[]{new Point(x,y)})); elements.add(
new PathElement(ElementType.kCGPathElementAddLineToPoint, new Point[] {new Point(x, y)}));
} }
private static void curve(float c1x, float c1y, float c2x, float c2y, float ex, float ey) { private static void curve(float c1x, float c1y, float c2x, float c2y, float ex, float ey) {
@@ -226,7 +276,8 @@ class PathParser {
} }
private static void curveTo(float c1x, float c1y, float c2x, float c2y, float ex, float ey) { private static void curveTo(float c1x, float c1y, float c2x, float c2y, float ex, float ey) {
//FLog.w(ReactConstants.TAG, "curve c1x: " + c1x + " c1y: " + c1y + "ex: " + ex + " ey: " + ey); // FLog.w(ReactConstants.TAG, "curve c1x: " + c1x + " c1y: " + c1y + "ex: " + ex + " ey: " +
// ey);
mPivotX = c2x; mPivotX = c2x;
mPivotY = c2y; mPivotY = c2y;
cubicTo(c1x, c1y, c2x, c2y, ex, ey); cubicTo(c1x, c1y, c2x, c2y, ex, ey);
@@ -237,7 +288,10 @@ class PathParser {
mPenX = ex; mPenX = ex;
mPenY = ey; mPenY = ey;
mPath.cubicTo(c1x * mScale, c1y * mScale, c2x * mScale, c2y * mScale, ex * mScale, ey * mScale); mPath.cubicTo(c1x * mScale, c1y * mScale, c2x * mScale, c2y * mScale, ex * mScale, ey * mScale);
elements.add(new PathElement(ElementType.kCGPathElementAddCurveToPoint, new Point[]{new Point(c1x, c1y), new Point(c2x, c2y), new Point(ex, ey)})); elements.add(
new PathElement(
ElementType.kCGPathElementAddCurveToPoint,
new Point[] {new Point(c1x, c1y), new Point(c2x, c2y), new Point(ex, ey)}));
} }
private static void smoothCurve(float c1x, float c1y, float ex, float ey) { private static void smoothCurve(float c1x, float c1y, float ex, float ey) {
@@ -245,7 +299,8 @@ class PathParser {
} }
private static void smoothCurveTo(float c1x, float c1y, float ex, float ey) { private static void smoothCurveTo(float c1x, float c1y, float ex, float ey) {
//FLog.w(ReactConstants.TAG, "smoothcurve c1x: " + c1x + " c1y: " + c1y + "ex: " + ex + " ey: " + ey); // FLog.w(ReactConstants.TAG, "smoothcurve c1x: " + c1x + " c1y: " + c1y + "ex: " + ex + " ey: "
// + ey);
float c2x = c1x; float c2x = c1x;
float c2y = c1y; float c2y = c1y;
c1x = (mPenX * 2) - mPivotX; c1x = (mPenX * 2) - mPivotX;
@@ -260,7 +315,8 @@ class PathParser {
} }
private static void quadraticBezierCurveTo(float c1x, float c1y, float c2x, float c2y) { private static void quadraticBezierCurveTo(float c1x, float c1y, float c2x, float c2y) {
//FLog.w(ReactConstants.TAG, "quad c1x: " + c1x + " c1y: " + c1y + "c2x: " + c2x + " c2y: " + c2y); // FLog.w(ReactConstants.TAG, "quad c1x: " + c1x + " c1y: " + c1y + "c2x: " + c2x + " c2y: " +
// c2y);
mPivotX = c1x; mPivotX = c1x;
mPivotY = c1y; mPivotY = c1y;
float ex = c2x; float ex = c2x;
@@ -285,12 +341,15 @@ class PathParser {
quadraticBezierCurveTo(c1x, c1y, c2x, c2y); quadraticBezierCurveTo(c1x, c1y, c2x, c2y);
} }
private static void arc(float rx, float ry, float rotation, boolean outer, boolean clockwise, float x, float y) { private static void arc(
float rx, float ry, float rotation, boolean outer, boolean clockwise, float x, float y) {
arcTo(rx, ry, rotation, outer, clockwise, x + mPenX, y + mPenY); arcTo(rx, ry, rotation, outer, clockwise, x + mPenX, y + mPenY);
} }
private static void arcTo(float rx, float ry, float rotation, boolean outer, boolean clockwise, float x, float y) { private static void arcTo(
//FLog.w(ReactConstants.TAG, "arc rx: " + rx + " ry: " + ry + " rotation: " + rotation + " outer: " + outer + " clockwise: " + clockwise + " x: " + x + " y: " + y); float rx, float ry, float rotation, boolean outer, boolean clockwise, float x, float y) {
// FLog.w(ReactConstants.TAG, "arc rx: " + rx + " ry: " + ry + " rotation: " + rotation + "
// outer: " + outer + " clockwise: " + clockwise + " x: " + x + " y: " + y);
float tX = mPenX; float tX = mPenX;
float tY = mPenY; float tY = mPenY;
@@ -376,14 +435,13 @@ class PathParser {
sweep = -sweep; sweep = -sweep;
} }
RectF oval = new RectF( RectF oval =
(cx - rx) * mScale, new RectF((cx - rx) * mScale, (cy - rx) * mScale, (cx + rx) * mScale, (cy + rx) * mScale);
(cy - rx) * mScale,
(cx + rx) * mScale,
(cy + rx) * mScale);
mPath.arcTo(oval, start, sweep); mPath.arcTo(oval, start, sweep);
elements.add(new PathElement(ElementType.kCGPathElementAddCurveToPoint, new Point[]{new Point(x, y)})); elements.add(
new PathElement(
ElementType.kCGPathElementAddCurveToPoint, new Point[] {new Point(x, y)}));
} }
} }
@@ -393,11 +451,14 @@ class PathParser {
mPenY = mPenDownY; mPenY = mPenDownY;
mPenDown = false; mPenDown = false;
mPath.close(); mPath.close();
elements.add(new PathElement(ElementType.kCGPathElementCloseSubpath, new Point[]{new Point(mPenX, mPenY)})); elements.add(
new PathElement(
ElementType.kCGPathElementCloseSubpath, new Point[] {new Point(mPenX, mPenY)}));
} }
} }
private static void arcToBezier(float cx, float cy, float rx, float ry, float sa, float ea, boolean clockwise, float rad) { private static void arcToBezier(
float cx, float cy, float rx, float ry, float sa, float ea, boolean clockwise, float rad) {
// Inverse Rotation + Scale Transform // Inverse Rotation + Scale Transform
float cos = (float) Math.cos(rad); float cos = (float) Math.cos(rad);
float sin = (float) Math.sin(rad); float sin = (float) Math.sin(rad);
@@ -440,8 +501,12 @@ class PathParser {
float ex = (cx + xx * x + yx * y); float ex = (cx + xx * x + yx * y);
float ey = (cy + xy * x + yy * y); float ey = (cy + xy * x + yy * y);
mPath.cubicTo(c1x * mScale, c1y * mScale, c2x * mScale, c2y * mScale, ex * mScale, ey * mScale); mPath.cubicTo(
elements.add(new PathElement(ElementType.kCGPathElementAddCurveToPoint, new Point[]{new Point(c1x, c1y), new Point(c2x, c2y), new Point(ex, ey)})); c1x * mScale, c1y * mScale, c2x * mScale, c2y * mScale, ex * mScale, ey * mScale);
elements.add(
new PathElement(
ElementType.kCGPathElementAddCurveToPoint,
new Point[] {new Point(c1x, c1y), new Point(c2x, c2y), new Point(ex, ey)}));
} }
} }
@@ -505,7 +570,8 @@ class PathParser {
char c = s.charAt(i); char c = s.charAt(i);
switch (c) { switch (c) {
case '0': case '0':
case '1': { case '1':
{
i += 1; i += 1;
if (i < l && s.charAt(i) == ',') { if (i < l && s.charAt(i) == ',') {
i += 1; i += 1;
@@ -557,7 +623,8 @@ class PathParser {
c = s.charAt(i); c = s.charAt(i);
} }
} else if (c != '.') { } else if (c != '.') {
throw new Error(String.format("Invalid number formating character '%c' (i=%d, s=%s)", c ,i, s)); throw new Error(
String.format("Invalid number formating character '%c' (i=%d, s=%s)", c, i, s));
} }
// Consume fraction. // Consume fraction.
@@ -582,7 +649,8 @@ class PathParser {
} else if (c >= '0' && c <= '9') { } else if (c >= '0' && c <= '9') {
skip_digits(); skip_digits();
} else { } else {
throw new Error(String.format("Invalid number formating character '%c' (i=%d, s=%s)", c, i, s)); throw new Error(
String.format("Invalid number formating character '%c' (i=%d, s=%s)", c, i, s));
} }
} }
} }
@@ -592,7 +660,8 @@ class PathParser {
// inf, nan, etc. are an error. // inf, nan, etc. are an error.
if (Float.isInfinite(n) || Float.isNaN(n)) { if (Float.isInfinite(n) || Float.isNaN(n)) {
throw new Error(String.format("Invalid number '%s' (start=%d, i=%d, s=%s)", num, start, i, s)); throw new Error(
String.format("Invalid number '%s' (start=%d, i=%d, s=%s)", num, start, i, s));
} }
return n; return n;

View File

@@ -6,14 +6,12 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Path; import android.graphics.Path;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactProp;
@@ -38,5 +36,4 @@ class PathView extends RenderableView {
Path getPath(Canvas canvas, Paint paint) { Path getPath(Canvas canvas, Paint paint) {
return mPath; return mPath;
} }
} }

View File

@@ -6,20 +6,17 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.graphics.Matrix; import android.graphics.Matrix;
import android.graphics.RectF; import android.graphics.RectF;
import com.facebook.common.logging.FLog; import com.facebook.common.logging.FLog;
import com.facebook.react.bridge.Dynamic; import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.common.ReactConstants; import com.facebook.react.common.ReactConstants;
import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactProp;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@SuppressLint("ViewConstructor") @SuppressLint("ViewConstructor")
@@ -39,7 +36,8 @@ class PatternView extends GroupView {
String mAlign; String mAlign;
int mMeetOrSlice; int mMeetOrSlice;
private static final float[] sRawMatrix = new float[]{ private static final float[] sRawMatrix =
new float[] {
1, 0, 0, 1, 0, 0,
0, 1, 0, 0, 1, 0,
0, 0, 1 0, 0, 1
@@ -82,6 +80,7 @@ class PatternView extends GroupView {
mW = SVGLength.from(width); mW = SVGLength.from(width);
invalidate(); invalidate();
} }
@ReactProp(name = "height") @ReactProp(name = "height")
public void setHeight(Dynamic height) { public void setHeight(Dynamic height) {
mH = SVGLength.from(height); mH = SVGLength.from(height);
@@ -174,9 +173,9 @@ class PatternView extends GroupView {
invalidate(); invalidate();
} }
RectF getViewBox() { RectF getViewBox() {
return new RectF(mMinX * mScale, mMinY * mScale, (mMinX + mVbWidth) * mScale, (mMinY + mVbHeight) * mScale); return new RectF(
mMinX * mScale, mMinY * mScale, (mMinX + mVbWidth) * mScale, (mMinY + mVbHeight) * mScale);
} }
@Override @Override
@@ -192,7 +191,8 @@ class PatternView extends GroupView {
} }
SvgView svg = getSvgView(); SvgView svg = getSvgView();
if (mPatternUnits == Brush.BrushUnits.USER_SPACE_ON_USE || mPatternContentUnits == Brush.BrushUnits.USER_SPACE_ON_USE) { if (mPatternUnits == Brush.BrushUnits.USER_SPACE_ON_USE
|| mPatternContentUnits == Brush.BrushUnits.USER_SPACE_ON_USE) {
brush.setUserSpaceBoundingBox(svg.getCanvasBounds()); brush.setUserSpaceBoundingBox(svg.getCanvasBounds());
} }

View File

@@ -6,25 +6,22 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableArray;
/** /** Contains static helper methods for accessing props. */
* Contains static helper methods for accessing props.
*/
class PropHelper { class PropHelper {
private static final int inputMatrixDataSize = 6; private static final int inputMatrixDataSize = 6;
/** /**
* Converts given {@link ReadableArray} to a matrix data array, {@code float[6]}. * Converts given {@link ReadableArray} to a matrix data array, {@code float[6]}. Writes result to
* Writes result to the array passed in {@param into}. * the array passed in {@param into}. This method will write exactly six items to the output array
* This method will write exactly six items to the output array from the input array. * from the input array.
* *
* If the input array has a different size, then only the size is returned; * <p>If the input array has a different size, then only the size is returned; Does not check
* Does not check output array size. Ensure space for at least six elements. * output array size. Ensure space for at least six elements.
* *
* @param value input array * @param value input array
* @param sRawMatrix output matrix * @param sRawMatrix output matrix
@@ -48,8 +45,7 @@ class PropHelper {
} }
/** /**
* Converts length string into px / user units * Converts length string into px / user units in the current user coordinate system
* in the current user coordinate system
* *
* @param length length string * @param length length string
* @param relative relative size for percentages * @param relative relative size for percentages
@@ -141,8 +137,7 @@ class PropHelper {
} }
} }
/** /**
* Converts SVGLength into px / user units * Converts SVGLength into px / user units in the current user coordinate system
* in the current user coordinate system
* *
* @param length length string * @param length length string
* @param relative relative size for percentages * @param relative relative size for percentages
@@ -151,7 +146,8 @@ class PropHelper {
* @param fontSize current font size * @param fontSize current font size
* @return value in the current user coordinate system * @return value in the current user coordinate system
*/ */
static double fromRelative(SVGLength length, double relative, double offset, double scale, double fontSize) { static double fromRelative(
SVGLength length, double relative, double offset, double scale, double fontSize) {
/* /*
TODO list TODO list

View File

@@ -19,6 +19,7 @@ enum ElementType {
class Point { class Point {
double x; double x;
double y; double y;
Point(double x, double y) { Point(double x, double y) {
this.x = x; this.x = x;
this.y = y; this.y = y;
@@ -33,14 +34,15 @@ class SegmentData {
class RNSVGMarkerPosition { class RNSVGMarkerPosition {
static private ArrayList<RNSVGMarkerPosition> positions_; private static ArrayList<RNSVGMarkerPosition> positions_;
static private int element_index_; private static int element_index_;
static private Point origin_; private static Point origin_;
static private Point subpath_start_; private static Point subpath_start_;
static private Point in_slope_; private static Point in_slope_;
static private Point out_slope_; private static Point out_slope_;
@SuppressWarnings("unused") @SuppressWarnings("unused")
static private boolean auto_start_reverse_; // TODO private static boolean auto_start_reverse_; // TODO
RNSVGMarkerType type; RNSVGMarkerType type;
Point origin; Point origin;
@@ -71,8 +73,7 @@ class RNSVGMarkerPosition {
private static double BisectingAngle(double in_angle, double out_angle) { private static double BisectingAngle(double in_angle, double out_angle) {
// WK193015: Prevent bugs due to angles being non-continuous. // WK193015: Prevent bugs due to angles being non-continuous.
if (Math.abs(in_angle - out_angle) > 180) if (Math.abs(in_angle - out_angle) > 180) in_angle += 360;
in_angle += 360;
return (in_angle + out_angle) / 2; return (in_angle + out_angle) / 2;
} }
@@ -92,8 +93,7 @@ class RNSVGMarkerPosition {
double out_angle = rad2deg(SlopeAngleRadians(out_slope_)); double out_angle = rad2deg(SlopeAngleRadians(out_slope_));
switch (type) { switch (type) {
case kStartMarker: case kStartMarker:
if (auto_start_reverse_) if (auto_start_reverse_) out_angle += 180;
out_angle += 180;
return out_angle; return out_angle;
case kMidMarker: case kMidMarker:
return BisectingAngle(in_angle, out_angle); return BisectingAngle(in_angle, out_angle);
@@ -111,16 +111,11 @@ class RNSVGMarkerPosition {
return p.x == 0 && p.y == 0; return p.x == 0 && p.y == 0;
} }
private static void ComputeQuadTangents(SegmentData data, private static void ComputeQuadTangents(SegmentData data, Point start, Point control, Point end) {
Point start,
Point control,
Point end) {
data.start_tangent = subtract(control, start); data.start_tangent = subtract(control, start);
data.end_tangent = subtract(end, control); data.end_tangent = subtract(end, control);
if (isZero(data.start_tangent)) if (isZero(data.start_tangent)) data.start_tangent = data.end_tangent;
data.start_tangent = data.end_tangent; else if (isZero(data.end_tangent)) data.end_tangent = data.start_tangent;
else if (isZero(data.end_tangent))
data.end_tangent = data.start_tangent;
} }
private static SegmentData ExtractPathElementFeatures(PathElement element) { private static SegmentData ExtractPathElementFeatures(PathElement element) {
@@ -131,10 +126,8 @@ class RNSVGMarkerPosition {
data.position = points[2]; data.position = points[2];
data.start_tangent = subtract(points[0], origin_); data.start_tangent = subtract(points[0], origin_);
data.end_tangent = subtract(points[2], points[1]); data.end_tangent = subtract(points[2], points[1]);
if (isZero(data.start_tangent)) if (isZero(data.start_tangent)) ComputeQuadTangents(data, points[0], points[1], points[2]);
ComputeQuadTangents(data, points[0], points[1], points[2]); else if (isZero(data.end_tangent)) ComputeQuadTangents(data, origin_, points[0], points[1]);
else if (isZero(data.end_tangent))
ComputeQuadTangents(data, origin_, points[0], points[1]);
break; break;
case kCGPathElementAddQuadCurveToPoint: case kCGPathElementAddQuadCurveToPoint:
data.position = points[1]; data.position = points[1];
@@ -171,8 +164,7 @@ class RNSVGMarkerPosition {
// Update marker position. // Update marker position.
origin_ = segment_data.position; origin_ = segment_data.position;
// If this is a 'move to' segment, save the point for use with 'close'. // If this is a 'move to' segment, save the point for use with 'close'.
if (element.type == ElementType.kCGPathElementMoveToPoint) if (element.type == ElementType.kCGPathElementMoveToPoint) subpath_start_ = element.points[0];
subpath_start_ = element.points[0];
else if (element.type == ElementType.kCGPathElementCloseSubpath) else if (element.type == ElementType.kCGPathElementCloseSubpath)
subpath_start_ = new Point(0, 0); subpath_start_ = new Point(0, 0);
++element_index_; ++element_index_;

View File

@@ -6,16 +6,16 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import static com.facebook.react.common.StandardCharsets.UTF_8;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Matrix; import android.graphics.Matrix;
import android.graphics.Path; import android.graphics.Path;
import android.graphics.PathMeasure; import android.graphics.PathMeasure;
import android.graphics.RectF; import android.graphics.RectF;
import android.graphics.Region; import android.graphics.Region;
import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactApplicationContext;
@@ -23,15 +23,11 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableMap;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import static com.facebook.react.common.StandardCharsets.UTF_8;
class RNSVGRenderableManager extends ReactContextBaseJavaModule { class RNSVGRenderableManager extends ReactContextBaseJavaModule {
RNSVGRenderableManager(ReactApplicationContext reactContext) { RNSVGRenderableManager(ReactApplicationContext reactContext) {
super(reactContext); super(reactContext);

View File

@@ -6,19 +6,16 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.graphics.Matrix; import android.graphics.Matrix;
import com.facebook.common.logging.FLog; import com.facebook.common.logging.FLog;
import com.facebook.react.bridge.Dynamic; import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.common.ReactConstants; import com.facebook.react.common.ReactConstants;
import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactProp;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@SuppressLint("ViewConstructor") @SuppressLint("ViewConstructor")
@@ -32,7 +29,8 @@ class RadialGradientView extends DefinitionView {
private ReadableArray mGradient; private ReadableArray mGradient;
private Brush.BrushUnits mGradientUnits; private Brush.BrushUnits mGradientUnits;
private static final float[] sRawMatrix = new float[]{ private static final float[] sRawMatrix =
new float[] {
1, 0, 0, 1, 0, 0,
0, 1, 0, 0, 1, 0,
0, 0, 1 0, 0, 1

View File

@@ -6,7 +6,6 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
@@ -15,7 +14,6 @@ import android.graphics.Paint;
import android.graphics.Path; import android.graphics.Path;
import android.graphics.RectF; import android.graphics.RectF;
import android.os.Build; import android.os.Build;
import com.facebook.react.bridge.Dynamic; import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactProp;
@@ -129,13 +127,25 @@ class RectView extends RenderableView {
ry = h / 2; ry = h / 2;
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
path.addRoundRect((float) x, (float) y, (float) (x + w), (float) (y + h), (float) rx, (float) ry, Path.Direction.CW); path.addRoundRect(
(float) x,
(float) y,
(float) (x + w),
(float) (y + h),
(float) rx,
(float) ry,
Path.Direction.CW);
} else { } else {
path.addRoundRect(new RectF((float) x, (float) y, (float) (x + w), (float) (y + h)), (float) rx, (float) ry, Path.Direction.CW); path.addRoundRect(
new RectF((float) x, (float) y, (float) (x + w), (float) (y + h)),
(float) rx,
(float) ry,
Path.Direction.CW);
} }
} else { } else {
path.addRect((float) x, (float) y, (float) (x + w), (float) (y + h), Path.Direction.CW); path.addRect((float) x, (float) y, (float) (x + w), (float) (y + h), Path.Direction.CW);
path.close(); // Ensure isSimplePath = false such that rect doesn't become represented using integers path.close(); // Ensure isSimplePath = false such that rect doesn't become represented using
// integers
} }
return path; return path;
} }

View File

@@ -6,7 +6,6 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import android.graphics.Bitmap; import android.graphics.Bitmap;
@@ -20,7 +19,7 @@ import android.graphics.PorterDuffXfermode;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.RectF; import android.graphics.RectF;
import android.graphics.Region; import android.graphics.Region;
import com.facebook.react.bridge.ColorPropConverter;
import com.facebook.react.bridge.Dynamic; import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
import com.facebook.react.bridge.JavaOnlyArray; import com.facebook.react.bridge.JavaOnlyArray;
@@ -28,19 +27,16 @@ import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableType; import com.facebook.react.bridge.ReadableType;
import com.facebook.react.bridge.ColorPropConverter;
import com.facebook.react.uimanager.PointerEvents; import com.facebook.react.uimanager.PointerEvents;
import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactProp;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@SuppressWarnings({"WeakerAccess", "RedundantSuppression"}) @SuppressWarnings({"WeakerAccess", "RedundantSuppression"})
abstract public class RenderableView extends VirtualView { public abstract class RenderableView extends VirtualView {
RenderableView(ReactContext reactContext) { RenderableView(ReactContext reactContext) {
super(reactContext); super(reactContext);
@@ -125,7 +121,6 @@ abstract public class RenderableView extends VirtualView {
setFill(fillMap); setFill(fillMap);
} }
// This code will probably never be reached with current changes // This code will probably never be reached with current changes
if (fillType.equals(ReadableType.Number)) { if (fillType.equals(ReadableType.Number)) {
this.fill = JavaOnlyArray.of(0, fill.asInt()); this.fill = JavaOnlyArray.of(0, fill.asInt());
@@ -182,8 +177,7 @@ abstract public class RenderableView extends VirtualView {
case FILL_RULE_NONZERO: case FILL_RULE_NONZERO:
break; break;
default: default:
throw new JSApplicationIllegalArgumentException( throw new JSApplicationIllegalArgumentException("fillRule " + fillRule + " unrecognized");
"fillRule " + fillRule + " unrecognized");
} }
invalidate(); invalidate();
@@ -363,7 +357,8 @@ abstract public class RenderableView extends VirtualView {
Paint maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG); Paint maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mask.draw(maskCanvas, maskPaint, 1); mask.draw(maskCanvas, maskPaint, 1);
// Apply luminanceToAlpha filter primitive https://www.w3.org/TR/SVG11/filters.html#feColorMatrixElement // Apply luminanceToAlpha filter primitive
// https://www.w3.org/TR/SVG11/filters.html#feColorMatrixElement
int nPixels = width * height; int nPixels = width * height;
int[] pixels = new int[nPixels]; int[] pixels = new int[nPixels];
maskBitmap.getPixels(pixels, 0, width, 0, 0, width, height); maskBitmap.getPixels(pixels, 0, width, 0, 0, width, height);
@@ -483,8 +478,8 @@ abstract public class RenderableView extends VirtualView {
} }
/** /**
* Sets up paint according to the props set on a view. Returns {@code true} * Sets up paint according to the props set on a view. Returns {@code true} if the fill should be
* if the fill should be drawn, {@code false} if not. * drawn, {@code false} if not.
*/ */
boolean setupFillPaint(Paint paint, float opacity) { boolean setupFillPaint(Paint paint, float opacity) {
if (fill != null && fill.size() > 0) { if (fill != null && fill.size() > 0) {
@@ -498,8 +493,8 @@ abstract public class RenderableView extends VirtualView {
} }
/** /**
* Sets up paint according to the props set on a view. Returns {@code true} * Sets up paint according to the props set on a view. Returns {@code true} if the stroke should
* if the stroke should be drawn, {@code false} if not. * be drawn, {@code false} if not.
*/ */
boolean setupStrokePaint(Paint paint, float opacity) { boolean setupStrokePaint(Paint paint, float opacity) {
paint.reset(); paint.reset();
@@ -551,32 +546,35 @@ abstract public class RenderableView extends VirtualView {
(int) (colors.getDouble(3) * 255)); (int) (colors.getDouble(3) * 255));
} }
break; break;
case 1: { case 1:
{
Brush brush = getSvgView().getDefinedBrush(colors.getString(1)); Brush brush = getSvgView().getDefinedBrush(colors.getString(1));
if (brush != null) { if (brush != null) {
brush.setupPaint(paint, mBox, mScale, opacity); brush.setupPaint(paint, mBox, mScale, opacity);
} }
break; break;
} }
case 2: { case 2:
{
int brush = getSvgView().mTintColor; int brush = getSvgView().mTintColor;
paint.setColor(brush); paint.setColor(brush);
break; break;
} }
case 3: { case 3:
{
if (contextElement != null && contextElement.fill != null) { if (contextElement != null && contextElement.fill != null) {
setupPaint(paint, opacity, contextElement.fill); setupPaint(paint, opacity, contextElement.fill);
} }
break; break;
} }
case 4: { case 4:
{
if (contextElement != null && contextElement.stroke != null) { if (contextElement != null && contextElement.stroke != null) {
setupPaint(paint, opacity, contextElement.stroke); setupPaint(paint, opacity, contextElement.stroke);
} }
break; break;
} }
} }
} }
abstract Path getPath(Canvas canvas, Paint paint); abstract Path getPath(Canvas canvas, Paint paint);
@@ -599,11 +597,10 @@ abstract public class RenderableView extends VirtualView {
initBounds(); initBounds();
if ( if ((mRegion == null || !mRegion.contains(x, y))
(mRegion == null || !mRegion.contains(x, y)) && && (mStrokeRegion == null
(mStrokeRegion == null || !mStrokeRegion.contains(x, y) && || !mStrokeRegion.contains(x, y)
(mMarkerRegion == null || !mMarkerRegion.contains(x, y))) && (mMarkerRegion == null || !mMarkerRegion.contains(x, y)))) {
) {
return -1; return -1;
} }
@@ -651,14 +648,13 @@ abstract public class RenderableView extends VirtualView {
Region getRegion(Path path, RectF rectF) { Region getRegion(Path path, RectF rectF) {
Region region = new Region(); Region region = new Region();
region.setPath(path, region.setPath(
path,
new Region( new Region(
(int) Math.floor(rectF.left), (int) Math.floor(rectF.left),
(int) Math.floor(rectF.top), (int) Math.floor(rectF.top),
(int) Math.ceil(rectF.right), (int) Math.ceil(rectF.right),
(int) Math.ceil(rectF.bottom) (int) Math.ceil(rectF.bottom)));
)
);
return region; return region;
} }
@@ -670,8 +666,7 @@ abstract public class RenderableView extends VirtualView {
void mergeProperties(RenderableView target) { void mergeProperties(RenderableView target) {
ArrayList<String> targetAttributeList = target.getAttributeList(); ArrayList<String> targetAttributeList = target.getAttributeList();
if (targetAttributeList == null || if (targetAttributeList == null || targetAttributeList.size() == 0) {
targetAttributeList.size() == 0) {
return; return;
} }

View File

@@ -6,77 +6,8 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import android.graphics.Matrix;
import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;
import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.JavaOnlyMap;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableType;
import com.facebook.react.uimanager.DisplayMetricsHolder;
import com.facebook.react.uimanager.LayoutShadowNode;
import com.facebook.react.uimanager.MatrixMathHelper;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.PointerEvents;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.TransformHelper;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.react.uimanager.ViewManagerDelegate;
import com.facebook.react.uimanager.ViewProps;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.annotations.ReactPropGroup;
import com.facebook.react.viewmanagers.RNSVGCircleManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGCircleManagerInterface;
import com.facebook.react.viewmanagers.RNSVGClipPathManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGClipPathManagerInterface;
import com.facebook.react.viewmanagers.RNSVGDefsManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGDefsManagerInterface;
import com.facebook.react.viewmanagers.RNSVGEllipseManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGEllipseManagerInterface;
import com.facebook.react.viewmanagers.RNSVGForeignObjectManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGForeignObjectManagerInterface;
import com.facebook.react.viewmanagers.RNSVGGroupManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGGroupManagerInterface;
import com.facebook.react.viewmanagers.RNSVGImageManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGImageManagerInterface;
import com.facebook.react.viewmanagers.RNSVGLineManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGLineManagerInterface;
import com.facebook.react.viewmanagers.RNSVGLinearGradientManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGLinearGradientManagerInterface;
import com.facebook.react.viewmanagers.RNSVGMarkerManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGMarkerManagerInterface;
import com.facebook.react.viewmanagers.RNSVGMaskManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGMaskManagerInterface;
import com.facebook.react.viewmanagers.RNSVGPathManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGPathManagerInterface;
import com.facebook.react.viewmanagers.RNSVGPatternManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGPatternManagerInterface;
import com.facebook.react.viewmanagers.RNSVGRadialGradientManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGRadialGradientManagerInterface;
import com.facebook.react.viewmanagers.RNSVGRectManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGRectManagerInterface;
import com.facebook.react.viewmanagers.RNSVGSymbolManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGSymbolManagerInterface;
import com.facebook.react.viewmanagers.RNSVGTSpanManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGTSpanManagerInterface;
import com.facebook.react.viewmanagers.RNSVGTextManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGTextManagerInterface;
import com.facebook.react.viewmanagers.RNSVGTextPathManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGTextPathManagerInterface;
import com.facebook.react.viewmanagers.RNSVGUseManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGUseManagerInterface;
import java.util.Locale;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static com.facebook.react.uimanager.MatrixMathHelper.determinant; import static com.facebook.react.uimanager.MatrixMathHelper.determinant;
import static com.facebook.react.uimanager.MatrixMathHelper.inverse; import static com.facebook.react.uimanager.MatrixMathHelper.inverse;
import static com.facebook.react.uimanager.MatrixMathHelper.multiplyVectorByMatrix; import static com.facebook.react.uimanager.MatrixMathHelper.multiplyVectorByMatrix;
@@ -142,9 +73,72 @@ import static com.horcrux.svg.RenderableView.CAP_ROUND;
import static com.horcrux.svg.RenderableView.FILL_RULE_NONZERO; import static com.horcrux.svg.RenderableView.FILL_RULE_NONZERO;
import static com.horcrux.svg.RenderableView.JOIN_ROUND; import static com.horcrux.svg.RenderableView.JOIN_ROUND;
/** import android.graphics.Matrix;
* ViewManager for DefinitionView RNSVG views import android.util.SparseArray;
*/ import android.view.View;
import android.view.ViewGroup;
import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.JavaOnlyMap;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableType;
import com.facebook.react.uimanager.DisplayMetricsHolder;
import com.facebook.react.uimanager.LayoutShadowNode;
import com.facebook.react.uimanager.MatrixMathHelper;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.PointerEvents;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.TransformHelper;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.react.uimanager.ViewManagerDelegate;
import com.facebook.react.uimanager.ViewProps;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.annotations.ReactPropGroup;
import com.facebook.react.viewmanagers.RNSVGCircleManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGCircleManagerInterface;
import com.facebook.react.viewmanagers.RNSVGClipPathManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGClipPathManagerInterface;
import com.facebook.react.viewmanagers.RNSVGDefsManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGDefsManagerInterface;
import com.facebook.react.viewmanagers.RNSVGEllipseManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGEllipseManagerInterface;
import com.facebook.react.viewmanagers.RNSVGForeignObjectManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGForeignObjectManagerInterface;
import com.facebook.react.viewmanagers.RNSVGGroupManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGGroupManagerInterface;
import com.facebook.react.viewmanagers.RNSVGImageManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGImageManagerInterface;
import com.facebook.react.viewmanagers.RNSVGLineManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGLineManagerInterface;
import com.facebook.react.viewmanagers.RNSVGLinearGradientManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGLinearGradientManagerInterface;
import com.facebook.react.viewmanagers.RNSVGMarkerManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGMarkerManagerInterface;
import com.facebook.react.viewmanagers.RNSVGMaskManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGMaskManagerInterface;
import com.facebook.react.viewmanagers.RNSVGPathManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGPathManagerInterface;
import com.facebook.react.viewmanagers.RNSVGPatternManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGPatternManagerInterface;
import com.facebook.react.viewmanagers.RNSVGRadialGradientManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGRadialGradientManagerInterface;
import com.facebook.react.viewmanagers.RNSVGRectManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGRectManagerInterface;
import com.facebook.react.viewmanagers.RNSVGSymbolManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGSymbolManagerInterface;
import com.facebook.react.viewmanagers.RNSVGTSpanManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGTSpanManagerInterface;
import com.facebook.react.viewmanagers.RNSVGTextManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGTextManagerInterface;
import com.facebook.react.viewmanagers.RNSVGTextPathManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGTextPathManagerInterface;
import com.facebook.react.viewmanagers.RNSVGUseManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGUseManagerInterface;
import java.util.Locale;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/** ViewManager for DefinitionView RNSVG views */
class VirtualViewManager<V extends VirtualView> extends ViewGroupManager<VirtualView> { class VirtualViewManager<V extends VirtualView> extends ViewGroupManager<VirtualView> {
protected final SVGClass svgClass; protected final SVGClass svgClass;
@@ -212,7 +206,6 @@ class VirtualViewManager<V extends VirtualView> extends ViewGroupManager<Virtual
PADDING_BOTTOM, PADDING_BOTTOM,
PADDING_START, PADDING_START,
PADDING_END, PADDING_END,
BORDER_WIDTH, BORDER_WIDTH,
BORDER_START_WIDTH, BORDER_START_WIDTH,
BORDER_END_WIDTH, BORDER_END_WIDTH,
@@ -220,8 +213,7 @@ class VirtualViewManager<V extends VirtualView> extends ViewGroupManager<Virtual
BORDER_BOTTOM_WIDTH, BORDER_BOTTOM_WIDTH,
BORDER_LEFT_WIDTH, BORDER_LEFT_WIDTH,
BORDER_RIGHT_WIDTH, BORDER_RIGHT_WIDTH,
} })
)
public void ignoreLayoutProps(int index, Dynamic value) {} public void ignoreLayoutProps(int index, Dynamic value) {}
} }
@@ -294,12 +286,8 @@ class VirtualViewManager<V extends VirtualView> extends ViewGroupManager<Virtual
// Solve the equation by inverting perspectiveMatrix and multiplying // Solve the equation by inverting perspectiveMatrix and multiplying
// rightHandSide by the inverse. // rightHandSide by the inverse.
double[] inversePerspectiveMatrix = inverse( double[] inversePerspectiveMatrix = inverse(perspectiveMatrix);
perspectiveMatrix double[] transposedInversePerspectiveMatrix = transpose(inversePerspectiveMatrix);
);
double[] transposedInversePerspectiveMatrix = transpose(
inversePerspectiveMatrix
);
multiplyVectorByMatrix(rightHandSide, transposedInversePerspectiveMatrix, perspective); multiplyVectorByMatrix(rightHandSide, transposedInversePerspectiveMatrix, perspective);
} else { } else {
// no perspective // no perspective
@@ -365,7 +353,10 @@ class VirtualViewManager<V extends VirtualView> extends ViewGroupManager<Virtual
// Based on: http://nghiaho.com/?page_id=846 // Based on: http://nghiaho.com/?page_id=846
double conv = 180 / Math.PI; double conv = 180 / Math.PI;
rotationDegrees[0] = roundTo3Places(-Math.atan2(row[2][1], row[2][2]) * conv); rotationDegrees[0] = roundTo3Places(-Math.atan2(row[2][1], row[2][2]) * conv);
rotationDegrees[1] = roundTo3Places(-Math.atan2(-row[2][0], Math.sqrt(row[2][1] * row[2][1] + row[2][2] * row[2][2])) * conv); rotationDegrees[1] =
roundTo3Places(
-Math.atan2(-row[2][0], Math.sqrt(row[2][1] * row[2][1] + row[2][2] * row[2][2]))
* conv);
rotationDegrees[2] = roundTo3Places(-Math.atan2(row[1][0], row[0][0]) * conv); rotationDegrees[2] = roundTo3Places(-Math.atan2(row[1][0], row[0][0]) * conv);
} }
@@ -385,7 +376,8 @@ class VirtualViewManager<V extends VirtualView> extends ViewGroupManager<Virtual
double[] perspectiveArray = sMatrixDecompositionContext.perspective; double[] perspectiveArray = sMatrixDecompositionContext.perspective;
if (perspectiveArray.length > PERSPECTIVE_ARRAY_INVERTED_CAMERA_DISTANCE_INDEX) { if (perspectiveArray.length > PERSPECTIVE_ARRAY_INVERTED_CAMERA_DISTANCE_INDEX) {
float invertedCameraDistance = (float) perspectiveArray[PERSPECTIVE_ARRAY_INVERTED_CAMERA_DISTANCE_INDEX]; float invertedCameraDistance =
(float) perspectiveArray[PERSPECTIVE_ARRAY_INVERTED_CAMERA_DISTANCE_INDEX];
if (invertedCameraDistance == 0) { if (invertedCameraDistance == 0) {
// Default camera distance, before scale multiplier (1280) // Default camera distance, before scale multiplier (1280)
invertedCameraDistance = 0.00078125f; invertedCameraDistance = 0.00078125f;
@@ -399,9 +391,9 @@ class VirtualViewManager<V extends VirtualView> extends ViewGroupManager<Virtual
// calculation, so squaring and a normalization value of // calculation, so squaring and a normalization value of
// sqrt(5) produces an exact replica with iOS. // sqrt(5) produces an exact replica with iOS.
// For more information, see https://github.com/facebook/react-native/pull/18302 // For more information, see https://github.com/facebook/react-native/pull/18302
float normalizedCameraDistance = scale * scale * cameraDistance * CAMERA_DISTANCE_NORMALIZATION_MULTIPLIER; float normalizedCameraDistance =
scale * scale * cameraDistance * CAMERA_DISTANCE_NORMALIZATION_MULTIPLIER;
view.setCameraDistance(normalizedCameraDistance); view.setCameraDistance(normalizedCameraDistance);
} }
} }
@@ -487,7 +479,6 @@ class VirtualViewManager<V extends VirtualView> extends ViewGroupManager<Virtual
node.setDisplay(display); node.setDisplay(display);
} }
@ReactProp(name = "matrix") @ReactProp(name = "matrix")
public void setMatrix(V node, Dynamic matrixArray) { public void setMatrix(V node, Dynamic matrixArray) {
node.setMatrix(matrixArray); node.setMatrix(matrixArray);
@@ -524,9 +515,11 @@ class VirtualViewManager<V extends VirtualView> extends ViewGroupManager<Virtual
} }
@Override @Override
protected void addEventEmitters(@Nonnull ThemedReactContext reactContext, @Nonnull VirtualView view) { protected void addEventEmitters(
@Nonnull ThemedReactContext reactContext, @Nonnull VirtualView view) {
super.addEventEmitters(reactContext, view); super.addEventEmitters(reactContext, view);
view.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() { view.setOnHierarchyChangeListener(
new ViewGroup.OnHierarchyChangeListener() {
@Override @Override
public void onChildViewAdded(View view, View view1) { public void onChildViewAdded(View view, View view1) {
if (view instanceof VirtualView) { if (view instanceof VirtualView) {
@@ -546,8 +539,8 @@ class VirtualViewManager<V extends VirtualView> extends ViewGroupManager<Virtual
/** /**
* Callback that will be triggered after all properties are updated in current update transaction * Callback that will be triggered after all properties are updated in current update transaction
* (all @ReactProp handlers for properties updated in current transaction have been called). If * (all @ReactProp handlers for properties updated in current transaction have been called). If
* you want to override this method you should call super.onAfterUpdateTransaction from it as * you want to override this method you should call super.onAfterUpdateTransaction from it as the
* the parent class of the ViewManager may rely on callback being executed. * parent class of the ViewManager may rely on callback being executed.
*/ */
protected void onAfterUpdateTransaction(@Nonnull V node) { protected void onAfterUpdateTransaction(@Nonnull V node) {
super.onAfterUpdateTransaction(node); super.onAfterUpdateTransaction(node);
@@ -626,7 +619,6 @@ class VirtualViewManager<V extends VirtualView> extends ViewGroupManager<Virtual
} }
} }
private static final SparseArray<RenderableView> mTagToRenderableView = new SparseArray<>(); private static final SparseArray<RenderableView> mTagToRenderableView = new SparseArray<>();
private static final SparseArray<Runnable> mTagToRunnable = new SparseArray<>(); private static final SparseArray<Runnable> mTagToRunnable = new SparseArray<>();
@@ -652,16 +644,14 @@ class VirtualViewManager<V extends VirtualView> extends ViewGroupManager<Virtual
super.onDropViewInstance(view); super.onDropViewInstance(view);
mTagToRenderableView.remove(view.getId()); mTagToRenderableView.remove(view.getId());
} }
} }
/** /** ViewManager for Renderable RNSVG views */
* ViewManager for Renderable RNSVG views
*/
class RenderableViewManager<T extends RenderableView> extends VirtualViewManager<T> { class RenderableViewManager<T extends RenderableView> extends VirtualViewManager<T> {
RenderableViewManager(SVGClass svgclass) { RenderableViewManager(SVGClass svgclass) {
super(svgclass); super(svgclass);
} }
static class GroupViewManagerAbstract<U extends GroupView> extends RenderableViewManager<U> { static class GroupViewManagerAbstract<U extends GroupView> extends RenderableViewManager<U> {
GroupViewManagerAbstract(SVGClass svgClass) { GroupViewManagerAbstract(SVGClass svgClass) {
super(svgClass); super(svgClass);
@@ -717,7 +707,8 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
} }
} }
static class GroupViewManager extends GroupViewManagerAbstract<GroupView> implements RNSVGGroupManagerInterface<GroupView> { static class GroupViewManager extends GroupViewManagerAbstract<GroupView>
implements RNSVGGroupManagerInterface<GroupView> {
GroupViewManager() { GroupViewManager() {
super(SVGClass.RNSVGGroup); super(SVGClass.RNSVGGroup);
mDelegate = new RNSVGGroupManagerDelegate(this); mDelegate = new RNSVGGroupManagerDelegate(this);
@@ -728,10 +719,10 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
protected ViewManagerDelegate getDelegate() { protected ViewManagerDelegate getDelegate() {
return mDelegate; return mDelegate;
} }
} }
static class PathViewManager extends RenderableViewManager<PathView> implements RNSVGPathManagerInterface<PathView> { static class PathViewManager extends RenderableViewManager<PathView>
implements RNSVGPathManagerInterface<PathView> {
PathViewManager() { PathViewManager() {
super(SVGClass.RNSVGPath); super(SVGClass.RNSVGPath);
mDelegate = new RNSVGPathManagerDelegate(this); mDelegate = new RNSVGPathManagerDelegate(this);
@@ -863,7 +854,8 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
} }
} }
static class TextViewManager extends TextViewManagerAbstract<TextView> implements RNSVGTextManagerInterface<TextView> { static class TextViewManager extends TextViewManagerAbstract<TextView>
implements RNSVGTextManagerInterface<TextView> {
TextViewManager() { TextViewManager() {
super(SVGClass.RNSVGText); super(SVGClass.RNSVGText);
mDelegate = new RNSVGTextManagerDelegate(this); mDelegate = new RNSVGTextManagerDelegate(this);
@@ -879,10 +871,10 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
super(svgClass); super(svgClass);
mDelegate = new RNSVGTextManagerDelegate(this); mDelegate = new RNSVGTextManagerDelegate(this);
} }
} }
static class TSpanViewManager extends TextViewManagerAbstract<TSpanView> implements RNSVGTSpanManagerInterface<TSpanView> { static class TSpanViewManager extends TextViewManagerAbstract<TSpanView>
implements RNSVGTSpanManagerInterface<TSpanView> {
TSpanViewManager() { TSpanViewManager() {
super(SVGClass.RNSVGTSpan); super(SVGClass.RNSVGTSpan);
mDelegate = new RNSVGTSpanManagerDelegate(this); mDelegate = new RNSVGTSpanManagerDelegate(this);
@@ -903,10 +895,10 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
public void setContent(TSpanView node, @Nullable String content) { public void setContent(TSpanView node, @Nullable String content) {
node.setContent(content); node.setContent(content);
} }
} }
static class TextPathViewManager extends TextViewManagerAbstract<TextPathView> implements RNSVGTextPathManagerInterface<TextPathView> { static class TextPathViewManager extends TextViewManagerAbstract<TextPathView>
implements RNSVGTextPathManagerInterface<TextPathView> {
TextPathViewManager() { TextPathViewManager() {
super(SVGClass.RNSVGTextPath); super(SVGClass.RNSVGTextPath);
mDelegate = new RNSVGTextPathManagerDelegate(this); mDelegate = new RNSVGTextPathManagerDelegate(this);
@@ -964,7 +956,8 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
} }
} }
static class ImageViewManager extends RenderableViewManager<ImageView> implements RNSVGImageManagerInterface<ImageView> { static class ImageViewManager extends RenderableViewManager<ImageView>
implements RNSVGImageManagerInterface<ImageView> {
ImageViewManager() { ImageViewManager() {
super(SVGClass.RNSVGImage); super(SVGClass.RNSVGImage);
mDelegate = new RNSVGImageManagerDelegate(this); mDelegate = new RNSVGImageManagerDelegate(this);
@@ -1031,7 +1024,6 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
node.setSrc(src); node.setSrc(src);
} }
@ReactProp(name = "align") @ReactProp(name = "align")
public void setAlign(ImageView node, String align) { public void setAlign(ImageView node, String align) {
node.setAlign(align); node.setAlign(align);
@@ -1043,7 +1035,8 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
} }
} }
static class CircleViewManager extends RenderableViewManager<CircleView> implements RNSVGCircleManagerInterface<CircleView> { static class CircleViewManager extends RenderableViewManager<CircleView>
implements RNSVGCircleManagerInterface<CircleView> {
CircleViewManager() { CircleViewManager() {
super(SVGClass.RNSVGCircle); super(SVGClass.RNSVGCircle);
mDelegate = new RNSVGCircleManagerDelegate(this); mDelegate = new RNSVGCircleManagerDelegate(this);
@@ -1086,7 +1079,8 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
} }
} }
static class EllipseViewManager extends RenderableViewManager<EllipseView> implements RNSVGEllipseManagerInterface<EllipseView> { static class EllipseViewManager extends RenderableViewManager<EllipseView>
implements RNSVGEllipseManagerInterface<EllipseView> {
EllipseViewManager() { EllipseViewManager() {
super(SVGClass.RNSVGEllipse); super(SVGClass.RNSVGEllipse);
mDelegate = new RNSVGEllipseManagerDelegate(this); mDelegate = new RNSVGEllipseManagerDelegate(this);
@@ -1139,7 +1133,8 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
} }
} }
static class LineViewManager extends RenderableViewManager<LineView> implements RNSVGLineManagerInterface<LineView> { static class LineViewManager extends RenderableViewManager<LineView>
implements RNSVGLineManagerInterface<LineView> {
LineViewManager() { LineViewManager() {
super(SVGClass.RNSVGLine); super(SVGClass.RNSVGLine);
@@ -1193,7 +1188,8 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
} }
} }
static class RectViewManager extends RenderableViewManager<RectView> implements RNSVGRectManagerInterface<RectView> { static class RectViewManager extends RenderableViewManager<RectView>
implements RNSVGRectManagerInterface<RectView> {
RectViewManager() { RectViewManager() {
super(SVGClass.RNSVGRect); super(SVGClass.RNSVGRect);
@@ -1244,47 +1240,41 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
@Override @Override
public void setY(RectView view, @Nullable String value) { public void setY(RectView view, @Nullable String value) {
view.setY(value); view.setY(value);
} }
@Override @Override
public void setRectheight(RectView view, @Nullable String value) { public void setRectheight(RectView view, @Nullable String value) {
view.setHeight(value); view.setHeight(value);
} }
@Override @Override
public void setRectwidth(RectView view, @Nullable String value) { public void setRectwidth(RectView view, @Nullable String value) {
view.setWidth(value); view.setWidth(value);
} }
@Override @Override
public void setHeight(RectView view, @Nullable String value) { public void setHeight(RectView view, @Nullable String value) {
view.setHeight(value); view.setHeight(value);
} }
@Override @Override
public void setWidth(RectView view, @Nullable String value) { public void setWidth(RectView view, @Nullable String value) {
view.setWidth(value); view.setWidth(value);
} }
@Override @Override
public void setRx(RectView view, @Nullable String value) { public void setRx(RectView view, @Nullable String value) {
view.setRx(value); view.setRx(value);
} }
@Override @Override
public void setRy(RectView view, @Nullable String value) { public void setRy(RectView view, @Nullable String value) {
view.setRy(value); view.setRy(value);
} }
} }
static class ClipPathViewManager extends GroupViewManagerAbstract<ClipPathView> implements RNSVGClipPathManagerInterface<ClipPathView>{ static class ClipPathViewManager extends GroupViewManagerAbstract<ClipPathView>
implements RNSVGClipPathManagerInterface<ClipPathView> {
ClipPathViewManager() { ClipPathViewManager() {
super(SVGClass.RNSVGClipPath); super(SVGClass.RNSVGClipPath);
mDelegate = new RNSVGClipPathManagerDelegate(this); mDelegate = new RNSVGClipPathManagerDelegate(this);
@@ -1297,7 +1287,8 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
} }
} }
static class DefsViewManager extends VirtualViewManager<DefsView> implements RNSVGDefsManagerInterface<DefsView> { static class DefsViewManager extends VirtualViewManager<DefsView>
implements RNSVGDefsManagerInterface<DefsView> {
DefsViewManager() { DefsViewManager() {
super(SVGClass.RNSVGDefs); super(SVGClass.RNSVGDefs);
@@ -1311,7 +1302,8 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
} }
} }
static class UseViewManager extends RenderableViewManager<UseView> implements RNSVGUseManagerInterface<UseView> { static class UseViewManager extends RenderableViewManager<UseView>
implements RNSVGUseManagerInterface<UseView> {
UseViewManager() { UseViewManager() {
super(SVGClass.RNSVGUse); super(SVGClass.RNSVGUse);
@@ -1380,7 +1372,8 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
} }
} }
static class SymbolManager extends GroupViewManagerAbstract<SymbolView> implements RNSVGSymbolManagerInterface<SymbolView> { static class SymbolManager extends GroupViewManagerAbstract<SymbolView>
implements RNSVGSymbolManagerInterface<SymbolView> {
SymbolManager() { SymbolManager() {
super(SVGClass.RNSVGSymbol); super(SVGClass.RNSVGSymbol);
mDelegate = new RNSVGSymbolManagerDelegate(this); mDelegate = new RNSVGSymbolManagerDelegate(this);
@@ -1423,7 +1416,8 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
} }
} }
static class PatternManager extends GroupViewManagerAbstract<PatternView> implements RNSVGPatternManagerInterface<PatternView> { static class PatternManager extends GroupViewManagerAbstract<PatternView>
implements RNSVGPatternManagerInterface<PatternView> {
PatternManager() { PatternManager() {
super(SVGClass.RNSVGPattern); super(SVGClass.RNSVGPattern);
mDelegate = new RNSVGPatternManagerDelegate(this); mDelegate = new RNSVGPatternManagerDelegate(this);
@@ -1531,7 +1525,8 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
} }
} }
static class MaskManager extends GroupViewManagerAbstract<MaskView> implements RNSVGMaskManagerInterface<MaskView> { static class MaskManager extends GroupViewManagerAbstract<MaskView>
implements RNSVGMaskManagerInterface<MaskView> {
MaskManager() { MaskManager() {
super(SVGClass.RNSVGMask); super(SVGClass.RNSVGMask);
mDelegate = new RNSVGMaskManagerDelegate(this); mDelegate = new RNSVGMaskManagerDelegate(this);
@@ -1609,7 +1604,8 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
} }
} }
static class ForeignObjectManager extends GroupViewManagerAbstract<ForeignObjectView> implements RNSVGForeignObjectManagerInterface<ForeignObjectView> { static class ForeignObjectManager extends GroupViewManagerAbstract<ForeignObjectView>
implements RNSVGForeignObjectManagerInterface<ForeignObjectView> {
ForeignObjectManager() { ForeignObjectManager() {
super(SVGClass.RNSVGForeignObject); super(SVGClass.RNSVGForeignObject);
mDelegate = new RNSVGForeignObjectManagerDelegate(this); mDelegate = new RNSVGForeignObjectManagerDelegate(this);
@@ -1620,6 +1616,7 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
protected ViewManagerDelegate getDelegate() { protected ViewManagerDelegate getDelegate() {
return mDelegate; return mDelegate;
} }
@ReactProp(name = "x") @ReactProp(name = "x")
public void setX(ForeignObjectView node, Dynamic x) { public void setX(ForeignObjectView node, Dynamic x) {
node.setX(x); node.setX(x);
@@ -1671,7 +1668,8 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
} }
} }
static class MarkerManager extends GroupViewManagerAbstract<MarkerView> implements RNSVGMarkerManagerInterface<MarkerView> { static class MarkerManager extends GroupViewManagerAbstract<MarkerView>
implements RNSVGMarkerManagerInterface<MarkerView> {
MarkerManager() { MarkerManager() {
super(SVGClass.RNSVGMarker); super(SVGClass.RNSVGMarker);
mDelegate = new RNSVGMarkerManagerDelegate(this); mDelegate = new RNSVGMarkerManagerDelegate(this);
@@ -1764,7 +1762,8 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
} }
} }
static class LinearGradientManager extends VirtualViewManager<LinearGradientView> implements RNSVGLinearGradientManagerInterface<LinearGradientView> { static class LinearGradientManager extends VirtualViewManager<LinearGradientView>
implements RNSVGLinearGradientManagerInterface<LinearGradientView> {
LinearGradientManager() { LinearGradientManager() {
super(SVGClass.RNSVGLinearGradient); super(SVGClass.RNSVGLinearGradient);
@@ -1777,7 +1776,6 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
return mDelegate; return mDelegate;
} }
@ReactProp(name = "x1") @ReactProp(name = "x1")
public void setX1(LinearGradientView node, Dynamic x1) { public void setX1(LinearGradientView node, Dynamic x1) {
node.setX1(x1); node.setX1(x1);
@@ -1834,7 +1832,8 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
} }
} }
static class RadialGradientManager extends VirtualViewManager<RadialGradientView> implements RNSVGRadialGradientManagerInterface<RadialGradientView> { static class RadialGradientManager extends VirtualViewManager<RadialGradientView>
implements RNSVGRadialGradientManagerInterface<RadialGradientView> {
RadialGradientManager() { RadialGradientManager() {
super(SVGClass.RNSVGRadialGradient); super(SVGClass.RNSVGRadialGradient);
@@ -1942,7 +1941,6 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
node.setFillRule(fillRule); node.setFillRule(fillRule);
} }
@ReactProp(name = "stroke") @ReactProp(name = "stroke")
public void setStroke(T node, @Nullable Dynamic strokeColors) { public void setStroke(T node, @Nullable Dynamic strokeColors) {
node.setStroke(strokeColors); node.setStroke(strokeColors);
@@ -2000,5 +1998,4 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
public void setPropList(T node, @Nullable ReadableArray propList) { public void setPropList(T node, @Nullable ReadableArray propList) {
node.setPropList(propList); node.setPropList(propList);
} }
} }

View File

@@ -2,7 +2,6 @@ package com.horcrux.svg;
import com.facebook.react.bridge.Dynamic; import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableArray;
import java.util.ArrayList; import java.util.ArrayList;
class SVGLength { class SVGLength {
@@ -121,12 +120,14 @@ class SVGLength {
static ArrayList<SVGLength> arrayFrom(Dynamic dynamic) { static ArrayList<SVGLength> arrayFrom(Dynamic dynamic) {
switch (dynamic.getType()) { switch (dynamic.getType()) {
case Number: { case Number:
{
ArrayList<SVGLength> list = new ArrayList<>(1); ArrayList<SVGLength> list = new ArrayList<>(1);
list.add(new SVGLength(dynamic.asDouble())); list.add(new SVGLength(dynamic.asDouble()));
return list; return list;
} }
case Array: { case Array:
{
ReadableArray arr = dynamic.asArray(); ReadableArray arr = dynamic.asArray();
int size = arr.size(); int size = arr.size();
ArrayList<SVGLength> list = new ArrayList<>(size); ArrayList<SVGLength> list = new ArrayList<>(size);
@@ -136,7 +137,8 @@ class SVGLength {
} }
return list; return list;
} }
case String: { case String:
{
ArrayList<SVGLength> list = new ArrayList<>(1); ArrayList<SVGLength> list = new ArrayList<>(1);
list.add(new SVGLength(dynamic.asString())); list.add(new SVGLength(dynamic.asString()));
return list; return list;

View File

@@ -6,24 +6,21 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import static com.horcrux.svg.RenderableViewManager.*;
import com.facebook.react.ReactPackage; import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule; import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager; import com.facebook.react.uimanager.ViewManager;
import com.facebook.soloader.SoLoader; import com.facebook.soloader.SoLoader;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import static com.horcrux.svg.RenderableViewManager.*;
public class SvgPackage implements ReactPackage { public class SvgPackage implements ReactPackage {
@Nonnull @Nonnull
@@ -64,9 +61,7 @@ public class SvgPackage implements ReactPackage {
SoLoader.loadLibrary("rnsvg_modules"); SoLoader.loadLibrary("rnsvg_modules");
} }
return Arrays.<NativeModule>asList( return Arrays.<NativeModule>asList(
new SvgViewModule(reactContext), new SvgViewModule(reactContext), new RNSVGRenderableManager(reactContext));
new RNSVGRenderableManager(reactContext)
);
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")

View File

@@ -6,7 +6,6 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
@@ -20,9 +19,6 @@ import android.graphics.Typeface;
import android.util.Base64; import android.util.Base64;
import android.view.View; import android.view.View;
import android.view.ViewParent; import android.view.ViewParent;
import androidx.annotation.NonNull;
import com.facebook.react.bridge.ColorPropConverter; import com.facebook.react.bridge.ColorPropConverter;
import com.facebook.react.bridge.Dynamic; import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
@@ -30,20 +26,16 @@ import com.facebook.react.uimanager.DisplayMetricsHolder;
import com.facebook.react.uimanager.ReactCompoundView; import com.facebook.react.uimanager.ReactCompoundView;
import com.facebook.react.uimanager.ReactCompoundViewGroup; import com.facebook.react.uimanager.ReactCompoundViewGroup;
import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.views.view.ReactViewGroup;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
/** /** Custom {@link View} implementation that draws an RNSVGSvg React view and its children. */
* Custom {@link View} implementation that draws an RNSVGSvg React view and its children.
*/
@SuppressLint("ViewConstructor") @SuppressLint("ViewConstructor")
public class SvgView extends FabricEnabledViewGroup implements ReactCompoundView, ReactCompoundViewGroup { public class SvgView extends FabricEnabledViewGroup
implements ReactCompoundView, ReactCompoundViewGroup {
@Override @Override
public boolean interceptsTouchEvent(float touchX, float touchY) { public boolean interceptsTouchEvent(float touchX, float touchY) {
@@ -269,14 +261,16 @@ public class SvgView extends FabricEnabledViewGroup implements ReactCompoundView
mRendered = true; mRendered = true;
float width = getWidth(); float width = getWidth();
float height = getHeight(); float height = getHeight();
boolean invalid = Float.isNaN(width) || Float.isNaN(height) || width < 1 || height < 1 || (Math.log10(width) + Math.log10(height) > 42); boolean invalid =
Float.isNaN(width)
|| Float.isNaN(height)
|| width < 1
|| height < 1
|| (Math.log10(width) + Math.log10(height) > 42);
if (invalid) { if (invalid) {
return null; return null;
} }
Bitmap bitmap = Bitmap.createBitmap( Bitmap bitmap = Bitmap.createBitmap((int) width, (int) height, Bitmap.Config.ARGB_8888);
(int) width,
(int) height,
Bitmap.Config.ARGB_8888);
drawChildren(new Canvas(bitmap)); drawChildren(new Canvas(bitmap));
return bitmap; return bitmap;
@@ -314,7 +308,6 @@ public class SvgView extends FabricEnabledViewGroup implements ReactCompoundView
paint.setTypeface(Typeface.DEFAULT); paint.setTypeface(Typeface.DEFAULT);
for (int i = 0; i < getChildCount(); i++) { for (int i = 0; i < getChildCount(); i++) {
View node = getChildAt(i); View node = getChildAt(i);
if (node instanceof VirtualView) { if (node instanceof VirtualView) {
@@ -338,14 +331,12 @@ public class SvgView extends FabricEnabledViewGroup implements ReactCompoundView
} }
private RectF getViewBox() { private RectF getViewBox() {
return new RectF(mMinX * mScale, mMinY * mScale, (mMinX + mVbWidth) * mScale, (mMinY + mVbHeight) * mScale); return new RectF(
mMinX * mScale, mMinY * mScale, (mMinX + mVbWidth) * mScale, (mMinY + mVbHeight) * mScale);
} }
String toDataURL() { String toDataURL() {
Bitmap bitmap = Bitmap.createBitmap( Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
getWidth(),
getHeight(),
Bitmap.Config.ARGB_8888);
clearChildCache(); clearChildCache();
drawChildren(new Canvas(bitmap)); drawChildren(new Canvas(bitmap));
@@ -359,10 +350,7 @@ public class SvgView extends FabricEnabledViewGroup implements ReactCompoundView
} }
String toDataURL(int width, int height) { String toDataURL(int width, int height) {
Bitmap bitmap = Bitmap.createBitmap( Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
width,
height,
Bitmap.Config.ARGB_8888);
clearChildCache(); clearChildCache();
drawChildren(new Canvas(bitmap)); drawChildren(new Canvas(bitmap));

View File

@@ -6,26 +6,23 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import android.util.SparseArray; import android.util.SparseArray;
import com.facebook.react.bridge.Dynamic; import com.facebook.react.bridge.Dynamic;
import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewManagerDelegate; import com.facebook.react.uimanager.ViewManagerDelegate;
import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.views.view.ReactViewGroup;
import com.facebook.react.views.view.ReactViewManager;
import com.facebook.react.viewmanagers.RNSVGSvgViewManagerDelegate; import com.facebook.react.viewmanagers.RNSVGSvgViewManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGSvgViewManagerInterface; import com.facebook.react.viewmanagers.RNSVGSvgViewManagerInterface;
import com.facebook.react.views.view.ReactViewGroup;
import com.facebook.react.views.view.ReactViewManager;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
/** /**
* ViewManager for RNSVGSvgView React views. Renders as a {@link SvgView} and handles * ViewManager for RNSVGSvgView React views. Renders as a {@link SvgView} and handles invalidating
* invalidating the native view on view updates happening in the underlying tree. * the native view on view updates happening in the underlying tree.
*/ */
class SvgViewManager extends ReactViewManager implements RNSVGSvgViewManagerInterface<SvgView> { class SvgViewManager extends ReactViewManager implements RNSVGSvgViewManagerInterface<SvgView> {
@@ -165,5 +162,4 @@ class SvgViewManager extends ReactViewManager implements RNSVGSvgViewManagerInte
public void setBbHeight(SvgView view, @Nullable String value) { public void setBbHeight(SvgView view, @Nullable String value) {
view.setBbHeight(value); view.setBbHeight(value);
} }
} }

View File

@@ -6,7 +6,6 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.Callback;
@@ -15,7 +14,6 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.UiThreadUtil; import com.facebook.react.bridge.UiThreadUtil;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
class SvgViewModule extends ReactContextBaseJavaModule { class SvgViewModule extends ReactContextBaseJavaModule {
@@ -29,7 +27,8 @@ class SvgViewModule extends ReactContextBaseJavaModule {
return "RNSVGSvgViewManager"; return "RNSVGSvgViewManager";
} }
private static void toDataURL(final int tag, final ReadableMap options, final Callback successCallback, final int attempt) { private static void toDataURL(
final int tag, final ReadableMap options, final Callback successCallback, final int attempt) {
UiThreadUtil.runOnUiThread( UiThreadUtil.runOnUiThread(
new Runnable() { new Runnable() {
@Override @Override
@@ -37,14 +36,17 @@ class SvgViewModule extends ReactContextBaseJavaModule {
SvgView svg = SvgViewManager.getSvgViewByTag(tag); SvgView svg = SvgViewManager.getSvgViewByTag(tag);
if (svg == null) { if (svg == null) {
SvgViewManager.runWhenViewIsAvailable(tag, new Runnable() { SvgViewManager.runWhenViewIsAvailable(
tag,
new Runnable() {
@Override @Override
public void run() { public void run() {
SvgView svg = SvgViewManager.getSvgViewByTag(tag); SvgView svg = SvgViewManager.getSvgViewByTag(tag);
if (svg == null) { // Should never happen if (svg == null) { // Should never happen
return; return;
} }
svg.setToDataUrlTask(new Runnable() { svg.setToDataUrlTask(
new Runnable() {
@Override @Override
public void run() { public void run() {
toDataURL(tag, options, successCallback, attempt + 1); toDataURL(tag, options, successCallback, attempt + 1);
@@ -53,7 +55,8 @@ class SvgViewModule extends ReactContextBaseJavaModule {
} }
}); });
} else if (svg.notRendered()) { } else if (svg.notRendered()) {
svg.setToDataUrlTask(new Runnable() { svg.setToDataUrlTask(
new Runnable() {
@Override @Override
public void run() { public void run() {
toDataURL(tag, options, successCallback, attempt + 1); toDataURL(tag, options, successCallback, attempt + 1);
@@ -62,18 +65,13 @@ class SvgViewModule extends ReactContextBaseJavaModule {
} else { } else {
if (options != null) { if (options != null) {
successCallback.invoke( successCallback.invoke(
svg.toDataURL( svg.toDataURL(options.getInt("width"), options.getInt("height")));
options.getInt("width"),
options.getInt("height")
)
);
} else { } else {
successCallback.invoke(svg.toDataURL()); successCallback.invoke(svg.toDataURL());
} }
} }
} }
} });
);
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")

View File

@@ -6,7 +6,6 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
@@ -14,7 +13,6 @@ import android.graphics.Canvas;
import android.graphics.Matrix; import android.graphics.Matrix;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.RectF; import android.graphics.RectF;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactProp;
@@ -75,7 +73,12 @@ class SymbolView extends GroupView {
void drawSymbol(Canvas canvas, Paint paint, float opacity, float width, float height) { void drawSymbol(Canvas canvas, Paint paint, float opacity, float width, float height) {
if (mAlign != null) { if (mAlign != null) {
RectF vbRect = new RectF(mMinX * mScale, mMinY * mScale, (mMinX + mVbWidth) * mScale, (mMinY + mVbHeight) * mScale); RectF vbRect =
new RectF(
mMinX * mScale,
mMinY * mScale,
(mMinX + mVbWidth) * mScale,
(mMinY + mVbHeight) * mScale);
RectF eRect = new RectF(0, 0, width, height); RectF eRect = new RectF(0, 0, width, height);
Matrix viewBoxMatrix = ViewBox.getTransform(vbRect, eRect, mAlign, mMeetOrSlice); Matrix viewBoxMatrix = ViewBox.getTransform(vbRect, eRect, mAlign, mMeetOrSlice);
canvas.concat(viewBoxMatrix); canvas.concat(viewBoxMatrix);

View File

@@ -6,9 +6,19 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import static android.graphics.Matrix.MTRANS_X;
import static android.graphics.Matrix.MTRANS_Y;
import static android.graphics.PathMeasure.POSITION_MATRIX_FLAG;
import static android.graphics.PathMeasure.TANGENT_MATRIX_FLAG;
import static com.horcrux.svg.TextProperties.AlignmentBaseline;
import static com.horcrux.svg.TextProperties.FontStyle;
import static com.horcrux.svg.TextProperties.FontVariantLigatures;
import static com.horcrux.svg.TextProperties.FontWeight;
import static com.horcrux.svg.TextProperties.TextAnchor;
import static com.horcrux.svg.TextProperties.TextPathMidLine;
import static com.horcrux.svg.TextProperties.TextPathSide;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.res.AssetManager; import android.content.res.AssetManager;
@@ -27,30 +37,14 @@ import android.text.StaticLayout;
import android.text.TextPaint; import android.text.TextPaint;
import android.view.View; import android.view.View;
import android.view.ViewParent; import android.view.ViewParent;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.views.text.ReactFontManager; import com.facebook.react.views.text.ReactFontManager;
import java.util.ArrayList;
import java.text.Bidi; import java.text.Bidi;
import java.util.ArrayList;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import static android.graphics.Matrix.MTRANS_X;
import static android.graphics.Matrix.MTRANS_Y;
import static android.graphics.PathMeasure.POSITION_MATRIX_FLAG;
import static android.graphics.PathMeasure.TANGENT_MATRIX_FLAG;
import static com.horcrux.svg.TextProperties.AlignmentBaseline;
import static com.horcrux.svg.TextProperties.FontStyle;
import static com.horcrux.svg.TextProperties.FontVariantLigatures;
import static com.horcrux.svg.TextProperties.FontWeight;
import static com.horcrux.svg.TextProperties.TextAnchor;
import static com.horcrux.svg.TextProperties.TextPathMidLine;
import static com.horcrux.svg.TextProperties.TextPathSide;
@SuppressLint("ViewConstructor") @SuppressLint("ViewConstructor")
class TSpanView extends TextView { class TSpanView extends TextView {
private static final double tau = 2 * Math.PI; private static final double tau = 2 * Math.PI;
@@ -149,7 +143,8 @@ class TSpanView extends TextView {
boolean includeFontPadding = true; boolean includeFontPadding = true;
SpannableString text = new SpannableString(mContent); SpannableString text = new SpannableString(mContent);
final double width = PropHelper.fromRelative(mInlineSize, canvas.getWidth(), 0, mScale, fontSize); final double width =
PropHelper.fromRelative(mInlineSize, canvas.getWidth(), 0, mScale, fontSize);
StaticLayout layout = getStaticLayout(tp, align, includeFontPadding, text, (int) width); StaticLayout layout = getStaticLayout(tp, align, includeFontPadding, text, (int) width);
int lineAscent = layout.getLineAscent(0); int lineAscent = layout.getLineAscent(0);
@@ -165,16 +160,14 @@ class TSpanView extends TextView {
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
private StaticLayout getStaticLayout(TextPaint tp, Layout.Alignment align, boolean includeFontPadding, SpannableString text, int width) { private StaticLayout getStaticLayout(
TextPaint tp,
Layout.Alignment align,
boolean includeFontPadding,
SpannableString text,
int width) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return new StaticLayout( return new StaticLayout(text, tp, width, align, 1.f, 0.f, includeFontPadding);
text,
tp,
width,
align,
1.f,
0.f,
includeFontPadding);
} else { } else {
return StaticLayout.Builder.obtain(text, 0, text.length(), tp, width) return StaticLayout.Builder.obtain(text, 0, text.length(), tp, width)
.setAlignment(align) .setAlignment(align)
@@ -186,26 +179,21 @@ class TSpanView extends TextView {
} }
} }
/** /**
* Implements visual to logical order converter. * Implements visual to logical order converter.
* *
* @author <a href="http://www.nesterovsky-bros.com">Nesterovsky bros</a> * @author <a href="http://www.nesterovsky-bros.com">Nesterovsky bros</a>
*
* @param text an input text in visual order to convert. * @param text an input text in visual order to convert.
* @return a String value in logical order. * @return a String value in logical order.
*/ */
public static String visualToLogical(String text) public static String visualToLogical(String text) {
{ if ((text == null) || (text.length() == 0)) {
if ((text == null) || (text.length() == 0))
{
return text; return text;
} }
Bidi bidi = new Bidi(text, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT); Bidi bidi = new Bidi(text, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
if (bidi.isLeftToRight()) if (bidi.isLeftToRight()) {
{
return text; return text;
} }
@@ -213,8 +201,7 @@ class TSpanView extends TextView {
byte[] levels = new byte[count]; byte[] levels = new byte[count];
Integer[] runs = new Integer[count]; Integer[] runs = new Integer[count];
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++) {
{
levels[i] = (byte) bidi.getRunLevel(i); levels[i] = (byte) bidi.getRunLevel(i);
runs[i] = i; runs[i] = i;
} }
@@ -223,22 +210,17 @@ class TSpanView extends TextView {
StringBuilder result = new StringBuilder(); StringBuilder result = new StringBuilder();
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++) {
{
int index = runs[i]; int index = runs[i];
int start = bidi.getRunStart(index); int start = bidi.getRunStart(index);
int end = bidi.getRunLimit(index); int end = bidi.getRunLimit(index);
int level = levels[index]; int level = levels[index];
if ((level & 1) != 0) if ((level & 1) != 0) {
{ for (; --end >= start; ) {
for (; --end >= start;)
{
result.append(text.charAt(end)); result.append(text.charAt(end));
} }
} } else {
else
{
result.append(text, start, end); result.append(text, start, end);
} }
} }
@@ -302,28 +284,33 @@ class TSpanView extends TextView {
return cachedAdvance; return cachedAdvance;
} }
final static String requiredFontFeatures = "'rlig', 'liga', 'clig', 'calt', 'locl', 'ccmp', 'mark', 'mkmk',"; static final String requiredFontFeatures =
final static String disableDiscretionaryLigatures = "'liga' 0, 'clig' 0, 'dlig' 0, 'hlig' 0, 'cala' 0, "; "'rlig', 'liga', 'clig', 'calt', 'locl', 'ccmp', 'mark', 'mkmk',";
final static String defaultFeatures = requiredFontFeatures + "'kern', "; static final String disableDiscretionaryLigatures =
final static String additionalLigatures = "'hlig', 'cala', "; "'liga' 0, 'clig' 0, 'dlig' 0, 'hlig' 0, 'cala' 0, ";
final static String fontWeightTag = "'wght' "; static final String defaultFeatures = requiredFontFeatures + "'kern', ";
static final String additionalLigatures = "'hlig', 'cala', ";
static final String fontWeightTag = "'wght' ";
private void applySpacingAndFeatures(Paint paint, FontData font) { private void applySpacingAndFeatures(Paint paint, FontData font) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
double letterSpacing = font.letterSpacing; double letterSpacing = font.letterSpacing;
paint.setLetterSpacing((float) (letterSpacing / (font.fontSize * mScale))); paint.setLetterSpacing((float) (letterSpacing / (font.fontSize * mScale)));
final boolean allowOptionalLigatures = letterSpacing == 0 && final boolean allowOptionalLigatures =
font.fontVariantLigatures == FontVariantLigatures.normal; letterSpacing == 0 && font.fontVariantLigatures == FontVariantLigatures.normal;
if (allowOptionalLigatures) { if (allowOptionalLigatures) {
paint.setFontFeatureSettings(defaultFeatures + additionalLigatures + font.fontFeatureSettings); paint.setFontFeatureSettings(
defaultFeatures + additionalLigatures + font.fontFeatureSettings);
} else { } else {
paint.setFontFeatureSettings(defaultFeatures + disableDiscretionaryLigatures + font.fontFeatureSettings); paint.setFontFeatureSettings(
defaultFeatures + disableDiscretionaryLigatures + font.fontFeatureSettings);
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
paint.setFontVariationSettings(fontWeightTag + font.absoluteFontWeight + font.fontVariationSettings); paint.setFontVariationSettings(
fontWeightTag + font.absoluteFontWeight + font.fontVariationSettings);
} }
} }
} }
@@ -432,8 +419,8 @@ class TSpanView extends TextView {
user agents should not apply optional ligatures. user agents should not apply optional ligatures.
https://www.w3.org/TR/css-text-3/#letter-spacing-property https://www.w3.org/TR/css-text-3/#letter-spacing-property
*/ */
final boolean allowOptionalLigatures = letterSpacing == 0 && final boolean allowOptionalLigatures =
font.fontVariantLigatures == FontVariantLigatures.normal; letterSpacing == 0 && font.fontVariantLigatures == FontVariantLigatures.normal;
/* /*
For OpenType fonts, discretionary ligatures include those enabled by For OpenType fonts, discretionary ligatures include those enabled by
@@ -494,13 +481,16 @@ class TSpanView extends TextView {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// String arabic = "'isol', 'fina', 'medi', 'init', 'rclt', 'mset', 'curs', "; // String arabic = "'isol', 'fina', 'medi', 'init', 'rclt', 'mset', 'curs', ";
if (allowOptionalLigatures) { if (allowOptionalLigatures) {
paint.setFontFeatureSettings(defaultFeatures + additionalLigatures + font.fontFeatureSettings); paint.setFontFeatureSettings(
defaultFeatures + additionalLigatures + font.fontFeatureSettings);
} else { } else {
paint.setFontFeatureSettings(defaultFeatures + disableDiscretionaryLigatures + font.fontFeatureSettings); paint.setFontFeatureSettings(
defaultFeatures + disableDiscretionaryLigatures + font.fontFeatureSettings);
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
paint.setFontVariationSettings(fontWeightTag + font.absoluteFontWeight + font.fontVariationSettings); paint.setFontVariationSettings(
fontWeightTag + font.absoluteFontWeight + font.fontVariationSettings);
} }
} }
// OpenType.js font data // OpenType.js font data
@@ -607,11 +597,13 @@ class TSpanView extends TextView {
a point on the path equal distance in both directions from the initial position on a point on the path equal distance in both directions from the initial position on
the path is reached. the path is reached.
*/ */
final double absoluteStartOffset = getAbsoluteStartOffset(textPath.getStartOffset(), pathLength, fontSize); final double absoluteStartOffset =
getAbsoluteStartOffset(textPath.getStartOffset(), pathLength, fontSize);
offset += absoluteStartOffset; offset += absoluteStartOffset;
if (isClosed) { if (isClosed) {
final double halfPathDistance = pathLength / 2; final double halfPathDistance = pathLength / 2;
startOfRendering = absoluteStartOffset + (textAnchor == TextAnchor.middle ? -halfPathDistance : 0); startOfRendering =
absoluteStartOffset + (textAnchor == TextAnchor.middle ? -halfPathDistance : 0);
endOfRendering = startOfRendering + pathLength; endOfRendering = startOfRendering + pathLength;
} }
/* /*
@@ -700,7 +692,8 @@ class TSpanView extends TextView {
*/ */
double scaleSpacingAndGlyphs = 1; double scaleSpacingAndGlyphs = 1;
if (mTextLength != null) { if (mTextLength != null) {
final double author = PropHelper.fromRelative(mTextLength, canvas.getWidth(), 0, mScale, fontSize); final double author =
PropHelper.fromRelative(mTextLength, canvas.getWidth(), 0, mScale, fontSize);
if (author < 0) { if (author < 0) {
throw new IllegalArgumentException("Negative textLength value"); throw new IllegalArgumentException("Negative textLength value");
} }
@@ -784,7 +777,8 @@ class TSpanView extends TextView {
break; break;
case middle: case middle:
// Align the vertical midpoint of the box with the baseline of the parent box plus half the x-height of the parent. // Align the vertical midpoint of the box with the baseline of the parent box plus half
// the x-height of the parent.
// middle = x height / 2 // middle = x height / 2
Rect bounds = new Rect(); Rect bounds = new Rect();
// this will just retrieve the bounding rect for 'x' // this will just retrieve the bounding rect for 'x'
@@ -907,7 +901,8 @@ class TSpanView extends TextView {
break; break;
default: default:
baselineShift -= PropHelper.fromRelative(baselineShiftString, mScale * fontSize, mScale, fontSize); baselineShift -=
PropHelper.fromRelative(baselineShiftString, mScale * fontSize, mScale, fontSize);
} }
break; break;
} }
@@ -1087,7 +1082,6 @@ class TSpanView extends TextView {
mid.preRotate((float) r); mid.preRotate((float) r);
Path glyph; Path glyph;
if (hasLigature) { if (hasLigature) {
glyph = new Path(); glyph = new Path();
@@ -1232,10 +1226,8 @@ class TSpanView extends TextView {
initBounds(); initBounds();
if ( if ((mRegion == null || !mRegion.contains(x, y))
(mRegion == null || !mRegion.contains(x, y)) && && (mStrokeRegion == null || !mStrokeRegion.contains(x, y))) {
(mStrokeRegion == null || !mStrokeRegion.contains(x, y))
) {
return -1; return -1;
} }

View File

@@ -2,17 +2,16 @@ package com.horcrux.svg;
// TODO implement https://www.w3.org/TR/SVG2/text.html#TextLayoutAlgorithm // TODO implement https://www.w3.org/TR/SVG2/text.html#TextLayoutAlgorithm
import static com.horcrux.svg.TextProperties.Direction;
import static com.horcrux.svg.TextProperties.TextAnchor;
import static com.horcrux.svg.TextProperties.TextPathSide;
import android.graphics.Path; import android.graphics.Path;
import android.graphics.PathMeasure; import android.graphics.PathMeasure;
import android.graphics.PointF; import android.graphics.PointF;
import android.view.View; import android.view.View;
import java.util.ArrayList; import java.util.ArrayList;
import static com.horcrux.svg.TextProperties.Direction;
import static com.horcrux.svg.TextProperties.TextAnchor;
import static com.horcrux.svg.TextProperties.TextPathSide;
@SuppressWarnings("ALL") @SuppressWarnings("ALL")
class TextLayoutAlgorithm { class TextLayoutAlgorithm {
class CharacterInformation { class CharacterInformation {
@@ -49,14 +48,14 @@ class TextLayoutAlgorithm {
ArrayList<TextView> subtree, ArrayList<TextView> subtree,
StringBuilder line, StringBuilder line,
View node, View node,
TextPathView textPath TextPathView textPath) {
) {
if (node instanceof TSpanView) { if (node instanceof TSpanView) {
final TSpanView tSpanView = (TSpanView) node; final TSpanView tSpanView = (TSpanView) node;
String content = tSpanView.mContent; String content = tSpanView.mContent;
if (content == null) { if (content == null) {
for (int i = 0; i < tSpanView.getChildCount(); i++) { for (int i = 0; i < tSpanView.getChildCount(); i++) {
getSubTreeTypographicCharacterPositions(inTextPath, subtree, line, tSpanView.getChildAt(i), textPath); getSubTreeTypographicCharacterPositions(
inTextPath, subtree, line, tSpanView.getChildAt(i), textPath);
} }
} else { } else {
for (int i = 0; i < content.length(); i++) { for (int i = 0; i < content.length(); i++) {
@@ -68,7 +67,8 @@ class TextLayoutAlgorithm {
} else { } else {
textPath = node instanceof TextPathView ? (TextPathView) node : textPath; textPath = node instanceof TextPathView ? (TextPathView) node : textPath;
for (int i = 0; i < textPath.getChildCount(); i++) { for (int i = 0; i < textPath.getChildCount(); i++) {
getSubTreeTypographicCharacterPositions(inTextPath, subtree, line, textPath.getChildAt(i), textPath); getSubTreeTypographicCharacterPositions(
inTextPath, subtree, line, textPath.getChildAt(i), textPath);
} }
} }
} }
@@ -265,8 +265,7 @@ class TextLayoutAlgorithm {
String[] resolve_x, String[] resolve_x,
String[] resolve_y, String[] resolve_y,
String[] resolve_dx, String[] resolve_dx,
String[] resolve_dy String[] resolve_dy) {
) {
this.result = result; this.result = result;
this.resolve_x = resolve_x; this.resolve_x = resolve_x;
this.resolve_y = resolve_y; this.resolve_y = resolve_y;
@@ -499,13 +498,8 @@ class TextLayoutAlgorithm {
} }
} }
CharacterPositioningResolver resolver = new CharacterPositioningResolver( CharacterPositioningResolver resolver =
result, new CharacterPositioningResolver(result, resolve_x, resolve_y, resolve_dx, resolve_dy);
resolve_x,
resolve_y,
resolve_dx,
resolve_dy
);
/* /*
Adjust positions: dx, dy Adjust positions: dx, dy
@@ -581,10 +575,7 @@ class TextLayoutAlgorithm {
*/ */
final Class<? extends TextView> nodeClass = node.getClass(); final Class<? extends TextView> nodeClass = node.getClass();
final boolean validTextLength = node.mTextLength != null; final boolean validTextLength = node.mTextLength != null;
if ( if ((nodeClass == TSpanView.class) && validTextLength) {
(nodeClass == TSpanView.class)
&& validTextLength
) {
/* /*
Let a = +∞ and b = −∞. Let a = +∞ and b = −∞.
*/ */
@@ -738,7 +729,8 @@ class TextLayoutAlgorithm {
character then shift = shift character then shift = shift
+ δ. + δ.
*/ */
if (!result[k].middle && (!result[k].resolved || result[k].firstCharacterInResolvedDescendant)) { if (!result[k].middle
&& (!result[k].resolved || result[k].firstCharacterInResolvedDescendant)) {
shift += perCharacterAdjustment; shift += perCharacterAdjustment;
} }
} }
@@ -906,7 +898,8 @@ class TextLayoutAlgorithm {
(middle, ltr) or (middle, rtl) (middle, ltr) or (middle, rtl)
Set shift = shift (a + b) / 2. Set shift = shift (a + b) / 2.
*/ */
if ((k > 0 && result[k].anchoredChunk && prevA != Double.POSITIVE_INFINITY) || k == count - 1) { if ((k > 0 && result[k].anchoredChunk && prevA != Double.POSITIVE_INFINITY)
|| k == count - 1) {
TextAnchor anchor = TextAnchor.start; TextAnchor anchor = TextAnchor.start;
Direction direction = Direction.ltr; Direction direction = Direction.ltr;
@@ -1012,9 +1005,8 @@ class TextLayoutAlgorithm {
TODO reverse path. TODO reverse path.
*/ */
Path path = textPath; Path path = textPath;
if (textPathView.getSide() == TextPathSide.right) { if (textPathView.getSide() == TextPathSide.right) {}
}
/* /*
Let length be the length Let length be the length
of path. of path.
@@ -1237,7 +1229,6 @@ class TextLayoutAlgorithm {
result[index].y = result[index - 1].y; result[index].y = result[index - 1].y;
result[index].rotate = result[index - 1].rotate; result[index].rotate = result[index - 1].rotate;
} }
} }
/* /*
If the character at index i is not within a If the character at index i is not within a

View File

@@ -6,22 +6,19 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import static com.horcrux.svg.TextProperties.*;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Path; import android.graphics.Path;
import com.facebook.react.bridge.Dynamic; import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactProp;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import static com.horcrux.svg.TextProperties.*;
@SuppressLint("ViewConstructor") @SuppressLint("ViewConstructor")
class TextPathView extends TextView { class TextPathView extends TextView {

View File

@@ -2,7 +2,6 @@ package com.horcrux.svg;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
class TextProperties { class TextProperties {
@@ -85,13 +84,15 @@ class TextProperties {
enum FontVariantLigatures { enum FontVariantLigatures {
normal, normal,
@SuppressWarnings("unused")none @SuppressWarnings("unused")
none
} }
enum FontStyle { enum FontStyle {
normal, normal,
italic, italic,
@SuppressWarnings("unused")oblique @SuppressWarnings("unused")
oblique
} }
enum FontWeight { enum FontWeight {
@@ -112,6 +113,7 @@ class TextProperties {
Lighter("lighter"); Lighter("lighter");
private final String weight; private final String weight;
FontWeight(String weight) { FontWeight(String weight) {
this.weight = weight; this.weight = weight;
} }
@@ -125,6 +127,7 @@ class TextProperties {
} }
private static final Map<String, FontWeight> weightToEnum = new HashMap<>(); private static final Map<String, FontWeight> weightToEnum = new HashMap<>();
static { static {
for (final FontWeight en : FontWeight.values()) { for (final FontWeight en : FontWeight.values()) {
weightToEnum.put(en.weight, en); weightToEnum.put(en.weight, en);
@@ -138,15 +141,13 @@ class TextProperties {
} }
} }
enum TextAnchor enum TextAnchor {
{
start, start,
middle, middle,
end end
} }
enum TextDecoration enum TextDecoration {
{
None("none"), None("none"),
Underline("underline"), Underline("underline"),
Overline("overline"), Overline("overline"),
@@ -154,6 +155,7 @@ class TextProperties {
Blink("blink"); Blink("blink");
private final String decoration; private final String decoration;
TextDecoration(String decoration) { TextDecoration(String decoration) {
this.decoration = decoration; this.decoration = decoration;
} }
@@ -166,6 +168,7 @@ class TextProperties {
} }
private static final Map<String, TextDecoration> decorationToEnum = new HashMap<>(); private static final Map<String, TextDecoration> decorationToEnum = new HashMap<>();
static { static {
for (final TextDecoration en : TextDecoration.values()) { for (final TextDecoration en : TextDecoration.values()) {
decorationToEnum.put(en.decoration, en); decorationToEnum.put(en.decoration, en);
@@ -179,15 +182,15 @@ class TextProperties {
} }
} }
enum TextLengthAdjust enum TextLengthAdjust {
{
spacing, spacing,
spacingAndGlyphs spacingAndGlyphs
} }
enum TextPathMethod { enum TextPathMethod {
align, align,
@SuppressWarnings("unused")stretch @SuppressWarnings("unused")
stretch
} }
/* /*
@@ -198,16 +201,19 @@ class TextProperties {
*/ */
enum TextPathMidLine { enum TextPathMidLine {
sharp, sharp,
@SuppressWarnings("unused")smooth @SuppressWarnings("unused")
smooth
} }
enum TextPathSide { enum TextPathSide {
@SuppressWarnings("unused")left, @SuppressWarnings("unused")
left,
right right
} }
enum TextPathSpacing { enum TextPathSpacing {
@SuppressWarnings("unused")auto, @SuppressWarnings("unused")
auto,
exact exact
} }
} }

View File

@@ -6,9 +6,11 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import static com.horcrux.svg.TextProperties.AlignmentBaseline;
import static com.horcrux.svg.TextProperties.TextLengthAdjust;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
@@ -16,19 +18,13 @@ import android.graphics.Path;
import android.graphics.Region; import android.graphics.Region;
import android.view.View; import android.view.View;
import android.view.ViewParent; import android.view.ViewParent;
import com.facebook.react.bridge.Dynamic; import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactProp;
import java.util.ArrayList; import java.util.ArrayList;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import static com.horcrux.svg.TextProperties.AlignmentBaseline;
import static com.horcrux.svg.TextProperties.TextLengthAdjust;
@SuppressLint("ViewConstructor") @SuppressLint("ViewConstructor")
class TextView extends GroupView { class TextView extends GroupView {
SVGLength mInlineSize = null; SVGLength mInlineSize = null;
@@ -172,7 +168,6 @@ class TextView extends GroupView {
invalidate(); invalidate();
} }
@ReactProp(name = "y") @ReactProp(name = "y")
public void setPositionY(Dynamic positionY) { public void setPositionY(Dynamic positionY) {
mPositionY = SVGLength.arrayFrom(positionY); mPositionY = SVGLength.arrayFrom(positionY);
@@ -261,7 +256,8 @@ class TextView extends GroupView {
@Override @Override
void pushGlyphContext() { void pushGlyphContext() {
boolean isTextNode = !(this instanceof TextPathView) && !(this instanceof TSpanView); boolean isTextNode = !(this instanceof TextPathView) && !(this instanceof TSpanView);
getTextRootGlyphContext().pushContext(isTextNode, this, mFont, mPositionX, mPositionY, mDeltaX, mDeltaY, mRotate); getTextRootGlyphContext()
.pushContext(isTextNode, this, mFont, mPositionX, mPositionY, mDeltaX, mDeltaY, mRotate);
} }
TextView getTextAnchorRoot() { TextView getTextAnchorRoot() {
@@ -270,7 +266,9 @@ class TextView extends GroupView {
TextView node = this; TextView node = this;
ViewParent parent = this.getParent(); ViewParent parent = this.getParent();
for (int i = font.size() - 1; i >= 0; i--) { for (int i = font.size() - 1; i >= 0; i--) {
if (!(parent instanceof TextView) || font.get(i).textAnchor == TextProperties.TextAnchor.start || node.mPositionX != null) { if (!(parent instanceof TextView)
|| font.get(i).textAnchor == TextProperties.TextAnchor.start
|| node.mPositionX != null) {
return node; return node;
} }
node = (TextView) parent; node = (TextView) parent;

View File

@@ -6,7 +6,6 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
@@ -14,7 +13,6 @@ import android.graphics.Canvas;
import android.graphics.Matrix; import android.graphics.Matrix;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Path; import android.graphics.Path;
import com.facebook.common.logging.FLog; import com.facebook.common.logging.FLog;
import com.facebook.react.bridge.Dynamic; import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
@@ -88,8 +86,12 @@ class UseView extends RenderableView {
VirtualView template = getSvgView().getDefinedTemplate(mHref); VirtualView template = getSvgView().getDefinedTemplate(mHref);
if (template == null) { if (template == null) {
FLog.w(ReactConstants.TAG, "`Use` element expected a pre-defined svg template as `href` prop, " + FLog.w(
"template named: " + mHref + " is not defined."); ReactConstants.TAG,
"`Use` element expected a pre-defined svg template as `href` prop, "
+ "template named: "
+ mHref
+ " is not defined.");
return; return;
} }
@@ -104,7 +106,8 @@ class UseView extends RenderableView {
if (template instanceof SymbolView) { if (template instanceof SymbolView) {
SymbolView symbol = (SymbolView) template; SymbolView symbol = (SymbolView) template;
symbol.drawSymbol(canvas, paint, opacity, (float) relativeOnWidth(mW), (float) relativeOnHeight(mH)); symbol.drawSymbol(
canvas, paint, opacity, (float) relativeOnWidth(mW), (float) relativeOnHeight(mH));
} else { } else {
template.draw(canvas, paint, opacity * mOpacity); template.draw(canvas, paint, opacity * mOpacity);
} }
@@ -129,8 +132,12 @@ class UseView extends RenderableView {
VirtualView template = getSvgView().getDefinedTemplate(mHref); VirtualView template = getSvgView().getDefinedTemplate(mHref);
if (template == null) { if (template == null) {
FLog.w(ReactConstants.TAG, "`Use` element expected a pre-defined svg template as `href` prop, " + FLog.w(
"template named: " + mHref + " is not defined."); ReactConstants.TAG,
"`Use` element expected a pre-defined svg template as `href` prop, "
+ "template named: "
+ mHref
+ " is not defined.");
return -1; return -1;
} }
@@ -146,8 +153,12 @@ class UseView extends RenderableView {
Path getPath(Canvas canvas, Paint paint) { Path getPath(Canvas canvas, Paint paint) {
VirtualView template = getSvgView().getDefinedTemplate(mHref); VirtualView template = getSvgView().getDefinedTemplate(mHref);
if (template == null) { if (template == null) {
FLog.w(ReactConstants.TAG, "`Use` element expected a pre-defined svg template as `href` prop, " + FLog.w(
"template named: " + mHref + " is not defined."); ReactConstants.TAG,
"`Use` element expected a pre-defined svg template as `href` prop, "
+ "template named: "
+ mHref
+ " is not defined.");
return null; return null;
} }
Path path = template.getPath(canvas, paint); Path path = template.getPath(canvas, paint);

View File

@@ -6,7 +6,6 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
package com.horcrux.svg; package com.horcrux.svg;
import android.graphics.Matrix; import android.graphics.Matrix;
@@ -21,7 +20,8 @@ class ViewBox {
static Matrix getTransform(RectF vbRect, RectF eRect, String align, int meetOrSlice) { static Matrix getTransform(RectF vbRect, RectF eRect, String align, int meetOrSlice) {
// based on https://svgwg.org/svg2-draft/coords.html#ComputingAViewportsTransform // based on https://svgwg.org/svg2-draft/coords.html#ComputingAViewportsTransform
// Let vb-x, vb-y, vb-width, vb-height be the min-x, min-y, width and height values of the viewBox attribute respectively. // Let vb-x, vb-y, vb-width, vb-height be the min-x, min-y, width and height values of the
// viewBox attribute respectively.
double vbX = vbRect.left; double vbX = vbRect.left;
double vbY = vbRect.top; double vbY = vbRect.top;
double vbWidth = vbRect.width(); double vbWidth = vbRect.width();
@@ -33,7 +33,6 @@ class ViewBox {
double eWidth = eRect.width(); double eWidth = eRect.width();
double eHeight = eRect.height(); double eHeight = eRect.height();
// Initialize scale-x to e-width/vb-width. // Initialize scale-x to e-width/vb-width.
double scaleX = eWidth / vbWidth; double scaleX = eWidth / vbWidth;
@@ -62,8 +61,10 @@ class ViewBox {
translateY -= (eHeight - vbHeight * scale) / 2; translateY -= (eHeight - vbHeight * scale) / 2;
} }
} else { } else {
// If align is not 'none' and meetOrSlice is 'meet', set the larger of scale-x and scale-y to the smaller. // If align is not 'none' and meetOrSlice is 'meet', set the larger of scale-x and scale-y to
// Otherwise, if align is not 'none' and meetOrSlice is 'slice', set the smaller of scale-x and scale-y to the larger. // the smaller.
// Otherwise, if align is not 'none' and meetOrSlice is 'slice', set the smaller of scale-x
// and scale-y to the larger.
if (!align.equals("none") && meetOrSlice == MOS_MEET) { if (!align.equals("none") && meetOrSlice == MOS_MEET) {
scaleX = scaleY = Math.min(scaleX, scaleY); scaleX = scaleY = Math.min(scaleX, scaleY);
@@ -90,7 +91,6 @@ class ViewBox {
if (align.contains("YMax")) { if (align.contains("YMax")) {
translateY += (eHeight - vbHeight * scaleY); translateY += (eHeight - vbHeight * scaleY);
} }
} }
// The transform applied to content contained by the element is given by // The transform applied to content contained by the element is given by

View File

@@ -1,5 +1,7 @@
package com.horcrux.svg; package com.horcrux.svg;
import static com.horcrux.svg.FontData.DEFAULT_FONT_SIZE;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Matrix; import android.graphics.Matrix;
@@ -9,7 +11,6 @@ import android.graphics.RectF;
import android.graphics.Region; import android.graphics.Region;
import android.view.View; import android.view.View;
import android.view.ViewParent; import android.view.ViewParent;
import com.facebook.common.logging.FLog; import com.facebook.common.logging.FLog;
import com.facebook.react.bridge.Dynamic; import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
@@ -23,15 +24,11 @@ import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.events.EventDispatcher; import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.views.view.ReactViewGroup; import com.facebook.react.views.view.ReactViewGroup;
import java.util.ArrayList; import java.util.ArrayList;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import static com.horcrux.svg.FontData.DEFAULT_FONT_SIZE;
@SuppressLint("ViewConstructor") @SuppressLint("ViewConstructor")
abstract public class VirtualView extends ReactViewGroup { public abstract class VirtualView extends ReactViewGroup {
final ReactContext mContext; final ReactContext mContext;
VirtualView(ReactContext reactContext) { VirtualView(ReactContext reactContext) {
@@ -47,7 +44,8 @@ abstract public class VirtualView extends ReactViewGroup {
*/ */
private static final double M_SQRT1_2l = 0.707106781186547524400844362104849039; private static final double M_SQRT1_2l = 0.707106781186547524400844362104849039;
private static final float[] sRawMatrix = new float[]{ private static final float[] sRawMatrix =
new float[] {
1, 0, 0, 1, 0, 0,
0, 1, 0, 0, 1, 0,
0, 0, 1 0, 0, 1
@@ -189,7 +187,6 @@ abstract public class VirtualView extends ReactViewGroup {
} }
} }
private double getFontSizeFromContext() { private double getFontSizeFromContext() {
if (fontSize != -1) { if (fontSize != -1) {
return fontSize; return fontSize;
@@ -209,6 +206,7 @@ abstract public class VirtualView extends ReactViewGroup {
} }
abstract void draw(Canvas canvas, Paint paint, float opacity); abstract void draw(Canvas canvas, Paint paint, float opacity);
void render(Canvas canvas, Paint paint, float opacity) { void render(Canvas canvas, Paint paint, float opacity) {
draw(canvas, paint, opacity); draw(canvas, paint, opacity);
} }
@@ -216,7 +214,7 @@ abstract public class VirtualView extends ReactViewGroup {
/** /**
* Sets up the transform matrix on the canvas before an element is drawn. * 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 * <p>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 * layer (which allocates an offscreen bitmap) and having it composited afterwards. Instead, the
* drawing code should apply opacity recursively. * drawing code should apply opacity recursively.
* *
@@ -233,8 +231,8 @@ abstract public class VirtualView extends ReactViewGroup {
} }
/** /**
* Restore the canvas after an element was drawn. This is always called in mirror with * Restore the canvas after an element was drawn. This is always called in mirror with {@link
* {@link #saveAndSetupCanvas}. * #saveAndSetupCanvas}.
* *
* @param canvas the canvas to restore * @param canvas the canvas to restore
*/ */
@@ -339,17 +337,21 @@ abstract public class VirtualView extends ReactViewGroup {
invalidate(); invalidate();
} }
@Nullable Path getClipPath() { @Nullable
Path getClipPath() {
return mCachedClipPath; return mCachedClipPath;
} }
@Nullable Path getClipPath(Canvas canvas, Paint paint) { @Nullable
Path getClipPath(Canvas canvas, Paint paint) {
if (mClipPath != null) { if (mClipPath != null) {
ClipPathView mClipNode = (ClipPathView) getSvgView().getDefinedClipPath(mClipPath); ClipPathView mClipNode = (ClipPathView) getSvgView().getDefinedClipPath(mClipPath);
if (mClipNode != null) { if (mClipNode != null) {
Path clipPath = mClipRule == CLIP_RULE_EVENODD ? mClipNode.getPath(canvas, paint) : Path clipPath =
mClipNode.getPath(canvas, paint, Region.Op.UNION); mClipRule == CLIP_RULE_EVENODD
? mClipNode.getPath(canvas, paint)
: mClipNode.getPath(canvas, paint, Region.Op.UNION);
clipPath.transform(mClipNode.mMatrix); clipPath.transform(mClipNode.mMatrix);
clipPath.transform(mClipNode.mTransform); clipPath.transform(mClipNode.mTransform);
switch (mClipRule) { switch (mClipRule) {
@@ -400,7 +402,9 @@ abstract public class VirtualView extends ReactViewGroup {
} else if (parent instanceof VirtualView) { } else if (parent instanceof VirtualView) {
svgView = ((VirtualView) parent).getSvgView(); svgView = ((VirtualView) parent).getSvgView();
} else { } else {
FLog.e(ReactConstants.TAG, "RNSVG: " + getClass().getName() + " should be descendant of a SvgView."); FLog.e(
ReactConstants.TAG,
"RNSVG: " + getClass().getName() + " should be descendant of a SvgView.");
} }
return svgView; return svgView;
@@ -437,8 +441,7 @@ abstract public class VirtualView extends ReactViewGroup {
} }
/** /**
* Converts SVGLength into px / user units * Converts SVGLength into px / user units in the current user coordinate system
* in the current user coordinate system
* *
* @param length length string * @param length length string
* @return value in the current user coordinate system * @return value in the current user coordinate system
@@ -520,24 +523,25 @@ abstract public class VirtualView extends ReactViewGroup {
} }
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = mClientRect != null ? int width =
(int) Math.ceil(mClientRect.width()) mClientRect != null
? (int) Math.ceil(mClientRect.width())
: getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec); : getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
int height = mClientRect != null ? int height =
(int) Math.ceil(mClientRect.height()) mClientRect != null
? (int) Math.ceil(mClientRect.height())
: getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec); : getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height); setMeasuredDimension(width, height);
} }
/** /**
* Called from layout when this view should * Called from layout when this view should assign a size and position to each of its children.
* assign a size and position to each of its children. *
* <p>Derived classes with children should override this method and call layout on each of their
* children.
* *
* Derived classes with children should override
* this method and call layout on each of
* their children.
* @param changed This is a new size or position for this view * @param changed This is a new size or position for this view
* @param pleft Left position, relative to parent * @param pleft Left position, relative to parent
* @param ptop Top position, relative to parent * @param ptop Top position, relative to parent
@@ -588,20 +592,12 @@ abstract public class VirtualView extends ReactViewGroup {
if (!mOnLayout) { if (!mOnLayout) {
return; return;
} }
EventDispatcher eventDispatcher = mContext EventDispatcher eventDispatcher =
.getNativeModule(UIManagerModule.class) mContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
.getEventDispatcher(); eventDispatcher.dispatchEvent(OnLayoutEvent.obtain(this.getId(), left, top, width, height));
eventDispatcher.dispatchEvent(OnLayoutEvent.obtain(
this.getId(),
left,
top,
width,
height
));
} }
RectF getClientRect() { RectF getClientRect() {
return mClientRect; return mClientRect;
} }
} }

View File

@@ -1,9 +1,7 @@
package com.horcrux.svg; package com.horcrux.svg;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
import com.facebook.react.views.view.ReactViewGroup; import com.facebook.react.views.view.ReactViewGroup;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public abstract class FabricEnabledViewGroup extends ReactViewGroup { public abstract class FabricEnabledViewGroup extends ReactViewGroup {

View File

@@ -18,7 +18,6 @@
- (void)paint:(CGContextRef)context opacity:(CGFloat)opacity painter:(RNSVGPainter *)painter bounds:(CGRect)bounds - (void)paint:(CGContextRef)context opacity:(CGFloat)opacity painter:(RNSVGPainter *)painter bounds:(CGRect)bounds
{ {
} }
- (BOOL)applyFillColor:(CGContextRef)context opacity:(CGFloat)opacity - (BOOL)applyFillColor:(CGContextRef)context opacity:(CGFloat)opacity

View File

@@ -7,14 +7,13 @@
*/ */
#import "RNSVGContextBrush.h" #import "RNSVGContextBrush.h"
#import "RNSVGRenderable.h"
#import "RNSVGNode.h" #import "RNSVGNode.h"
#import "RNSVGRenderable.h"
#import "RCTConvert+RNSVG.h"
#import <React/RCTLog.h> #import <React/RCTLog.h>
#import "RCTConvert+RNSVG.h"
@implementation RNSVGContextBrush @implementation RNSVGContextBrush {
{
BOOL _isStroke; BOOL _isStroke;
} }
@@ -59,8 +58,6 @@
return fillColor; return fillColor;
} }
- (BOOL)applyStrokeColor:(CGContextRef)context opacity:(CGFloat)opacity - (BOOL)applyStrokeColor:(CGContextRef)context opacity:(CGFloat)opacity
{ {
RNSVGRenderable *element = RNSVGRenderable.contextElement; RNSVGRenderable *element = RNSVGRenderable.contextElement;

View File

@@ -8,8 +8,8 @@
#import "RCTConvert+RNSVG.h" #import "RCTConvert+RNSVG.h"
#import "RNSVGBrushType.h" #import "RNSVGBrushType.h"
#import "RNSVGUnits.h"
#import "RNSVGLength.h" #import "RNSVGLength.h"
#import "RNSVGUnits.h"
@class RNSVGPattern; @class RNSVGPattern;

View File

@@ -10,8 +10,7 @@
#import "RNSVGPattern.h" #import "RNSVGPattern.h"
#import "RNSVGViewBox.h" #import "RNSVGViewBox.h"
@implementation RNSVGPainter @implementation RNSVGPainter {
{
NSArray<RNSVGLength *> *_points; NSArray<RNSVGLength *> *_points;
NSArray<NSNumber *> *_colors; NSArray<NSNumber *> *_colors;
RNSVGBrushType _type; RNSVGBrushType _type;
@@ -122,8 +121,7 @@ void PatternFunction(void* info, CGContextRef context)
CGFloat vbHeight = _pattern.vbHeight; CGFloat vbHeight = _pattern.vbHeight;
if (vbWidth > 0 && vbHeight > 0) { if (vbWidth > 0 && vbHeight > 0) {
CGRect vbRect = CGRectMake(minX, minY, vbWidth, vbHeight); CGRect vbRect = CGRectMake(minX, minY, vbWidth, vbHeight);
CGAffineTransform _viewBoxTransform = [RNSVGViewBox CGAffineTransform _viewBoxTransform = [RNSVGViewBox getTransform:vbRect
getTransform:vbRect
eRect:rect eRect:rect
align:_pattern.align align:_pattern.align
meetOrSlice:_pattern.meetOrSlice]; meetOrSlice:_pattern.meetOrSlice];
@@ -141,10 +139,8 @@ void PatternFunction(void* info, CGContextRef context)
- (CGFloat)getVal:(RNSVGLength *)length relative:(CGFloat)relative - (CGFloat)getVal:(RNSVGLength *)length relative:(CGFloat)relative
{ {
RNSVGLengthUnitType unit = [length unit]; RNSVGLengthUnitType unit = [length unit];
CGFloat val = [RNSVGPropHelper fromRelative:length CGFloat val = [RNSVGPropHelper fromRelative:length relative:relative];
relative:relative]; return _useObjectBoundingBox && unit == SVG_LENGTHTYPE_NUMBER ? val * relative : val;
return _useObjectBoundingBox &&
unit == SVG_LENGTHTYPE_NUMBER ? val * relative : val;
} }
- (void)paintPattern:(CGContextRef)context bounds:(CGRect)bounds - (void)paintPattern:(CGContextRef)context bounds:(CGRect)bounds
@@ -175,7 +171,8 @@ void PatternFunction(void* info, CGContextRef context)
CGContextSetFillColorSpace(context, patternSpace); CGContextSetFillColorSpace(context, patternSpace);
CGColorSpaceRelease(patternSpace); CGColorSpaceRelease(patternSpace);
CGPatternRef pattern = CGPatternCreate((__bridge void * _Nullable)(self), CGPatternRef pattern = CGPatternCreate(
(__bridge void *_Nullable)(self),
newBounds, newBounds,
viewbox, viewbox,
size.width, size.width,
@@ -252,4 +249,3 @@ void PatternFunction(void* info, CGContextRef context)
} }
@end @end

View File

@@ -7,9 +7,9 @@
*/ */
#import "RNSVGPainterBrush.h" #import "RNSVGPainterBrush.h"
#import "RNSVGPainter.h"
#import "RCTConvert+RNSVG.h"
#import <React/RCTLog.h> #import <React/RCTLog.h>
#import "RCTConvert+RNSVG.h"
#import "RNSVGPainter.h"
@implementation RNSVGPainterBrush @implementation RNSVGPainterBrush
@@ -17,8 +17,7 @@
{ {
if ((self = [super initWithArray:array])) { if ((self = [super initWithArray:array])) {
if (array.count != 2) { if (array.count != 2) {
RCTLogError(@"-[%@ %@] expects 2 elements, received %@", RCTLogError(@"-[%@ %@] expects 2 elements, received %@", self.class, NSStringFromSelector(_cmd), array);
self.class, NSStringFromSelector(_cmd), array);
return nil; return nil;
} }

View File

@@ -9,11 +9,10 @@
#import "RNSVGSolidColorBrush.h" #import "RNSVGSolidColorBrush.h"
#import "RNSVGUIKit.h" #import "RNSVGUIKit.h"
#import "RCTConvert+RNSVG.h"
#import <React/RCTLog.h> #import <React/RCTLog.h>
#import "RCTConvert+RNSVG.h"
@implementation RNSVGSolidColorBrush @implementation RNSVGSolidColorBrush {
{
RNSVGColor *_color; RNSVGColor *_color;
} }
@@ -41,7 +40,6 @@
return self; return self;
} }
- (void)dealloc - (void)dealloc
{ {
_color = nil; _color = nil;

View File

@@ -10,9 +10,9 @@
#ifdef RN_FABRIC_ENABLED #ifdef RN_FABRIC_ENABLED
#import <react/renderer/components/rnsvg/ComponentDescriptors.h> #import <react/renderer/components/rnsvg/ComponentDescriptors.h>
#import "RCTFabricComponentsPlugins.h"
#import "RCTConversions.h"
#import <react/renderer/components/view/conversions.h> #import <react/renderer/components/view/conversions.h>
#import "RCTConversions.h"
#import "RCTFabricComponentsPlugins.h"
#import "RNSVGFabricConversions.h" #import "RNSVGFabricConversions.h"
#endif // RN_FABRIC_ENABLED #endif // RN_FABRIC_ENABLED
@@ -55,7 +55,6 @@ using namespace facebook::react;
[self.svgView defineClipPath:self clipPathName:self.name]; [self.svgView defineClipPath:self clipPathName:self.name];
} }
- (BOOL)isSimpleClipPath - (BOOL)isSimpleClipPath
{ {
NSArray<RNSVGView *> *children = self.subviews; NSArray<RNSVGView *> *children = self.subviews;

View File

@@ -9,9 +9,9 @@
#ifdef RN_FABRIC_ENABLED #ifdef RN_FABRIC_ENABLED
#import <react/renderer/components/rnsvg/ComponentDescriptors.h> #import <react/renderer/components/rnsvg/ComponentDescriptors.h>
#import "RCTFabricComponentsPlugins.h"
#import "RCTConversions.h"
#import <react/renderer/components/view/conversions.h> #import <react/renderer/components/view/conversions.h>
#import "RCTConversions.h"
#import "RCTFabricComponentsPlugins.h"
#import "RNSVGFabricConversions.h" #import "RNSVGFabricConversions.h"
#endif // RN_FABRIC_ENABLED #endif // RN_FABRIC_ENABLED

View File

@@ -12,9 +12,9 @@
#ifdef RN_FABRIC_ENABLED #ifdef RN_FABRIC_ENABLED
#import <react/renderer/components/rnsvg/ComponentDescriptors.h> #import <react/renderer/components/rnsvg/ComponentDescriptors.h>
#import "RCTFabricComponentsPlugins.h"
#import "RCTConversions.h"
#import <react/renderer/components/view/conversions.h> #import <react/renderer/components/view/conversions.h>
#import "RCTConversions.h"
#import "RCTFabricComponentsPlugins.h"
#import "RNSVGFabricConversions.h" #import "RNSVGFabricConversions.h"
#endif // RN_FABRIC_ENABLED #endif // RN_FABRIC_ENABLED
@@ -43,8 +43,12 @@ using namespace facebook::react;
{ {
const auto &newProps = *std::static_pointer_cast<const RNSVGForeignObjectProps>(props); const auto &newProps = *std::static_pointer_cast<const RNSVGForeignObjectProps>(props);
self.x = RCTNSStringFromStringNilIfEmpty(newProps.x) ? [RNSVGLength lengthWithString:RCTNSStringFromString(newProps.x)] : nil; self.x = RCTNSStringFromStringNilIfEmpty(newProps.x)
self.y = RCTNSStringFromStringNilIfEmpty(newProps.y) ? [RNSVGLength lengthWithString:RCTNSStringFromString(newProps.y)] : nil; ? [RNSVGLength lengthWithString:RCTNSStringFromString(newProps.x)]
: nil;
self.y = RCTNSStringFromStringNilIfEmpty(newProps.y)
? [RNSVGLength lengthWithString:RCTNSStringFromString(newProps.y)]
: nil;
if (RCTNSStringFromStringNilIfEmpty(newProps.foreignObjectheight)) { if (RCTNSStringFromStringNilIfEmpty(newProps.foreignObjectheight)) {
self.foreignObjectheight = [RNSVGLength lengthWithString:RCTNSStringFromString(newProps.foreignObjectheight)]; self.foreignObjectheight = [RNSVGLength lengthWithString:RCTNSStringFromString(newProps.foreignObjectheight)];
} }
@@ -85,11 +89,7 @@ using namespace facebook::react;
[self clip:context]; [self clip:context];
CGContextTranslateCTM(context, [self relativeOnWidth:self.x], [self relativeOnHeight:self.y]); CGContextTranslateCTM(context, [self relativeOnWidth:self.x], [self relativeOnHeight:self.y]);
CGRect clip = CGRectMake( CGRect clip = CGRectMake(
0, 0, 0, [self relativeOnWidth:self.foreignObjectwidth], [self relativeOnHeight:self.foreignObjectheight]);
0,
[self relativeOnWidth:self.foreignObjectwidth],
[self relativeOnHeight:self.foreignObjectheight]
);
CGContextClipToRect(context, clip); CGContextClipToRect(context, clip);
[super renderLayerTo:context rect:rect]; [super renderLayerTo:context rect:rect];
} }

View File

@@ -10,11 +10,11 @@
#import "RNSVGUIKit.h" #import "RNSVGUIKit.h"
#import "RNSVGContainer.h"
#import "RNSVGCGFCRule.h" #import "RNSVGCGFCRule.h"
#import "RNSVGSvgView.h" #import "RNSVGContainer.h"
#import "RNSVGPath.h"
#import "RNSVGGlyphContext.h" #import "RNSVGGlyphContext.h"
#import "RNSVGPath.h"
#import "RNSVGSvgView.h"
@interface RNSVGGroup : RNSVGPath <RNSVGContainer> @interface RNSVGGroup : RNSVGPath <RNSVGContainer>

View File

@@ -10,17 +10,15 @@
#import "RNSVGClipPath.h" #import "RNSVGClipPath.h"
#import "RNSVGMask.h" #import "RNSVGMask.h"
#ifdef RN_FABRIC_ENABLED #ifdef RN_FABRIC_ENABLED
#import <react/renderer/components/rnsvg/ComponentDescriptors.h> #import <react/renderer/components/rnsvg/ComponentDescriptors.h>
#import "RCTFabricComponentsPlugins.h"
#import "RCTConversions.h"
#import <react/renderer/components/view/conversions.h> #import <react/renderer/components/view/conversions.h>
#import "RCTConversions.h"
#import "RCTFabricComponentsPlugins.h"
#import "RNSVGFabricConversions.h" #import "RNSVGFabricConversions.h"
#endif // RN_FABRIC_ENABLED #endif // RN_FABRIC_ENABLED
@implementation RNSVGGroup @implementation RNSVGGroup {
{
RNSVGGlyphContext *_glyphContext; RNSVGGlyphContext *_glyphContext;
} }
@@ -156,8 +154,7 @@ using namespace facebook::react;
CGFloat width = CGRectGetWidth(clipBounds); CGFloat width = CGRectGetWidth(clipBounds);
CGFloat height = CGRectGetHeight(clipBounds); CGFloat height = CGRectGetHeight(clipBounds);
_glyphContext = [[RNSVGGlyphContext alloc] initWithWidth:width _glyphContext = [[RNSVGGlyphContext alloc] initWithWidth:width height:height];
height:height];
} }
- (RNSVGGlyphContext *)getGlyphContext - (RNSVGGlyphContext *)getGlyphContext
@@ -228,7 +225,8 @@ using namespace facebook::react;
} }
if (!event) { if (!event) {
NSPredicate *const anyActive = [NSPredicate predicateWithFormat:@"self isKindOfClass: %@ AND active == TRUE", [RNSVGNode class]]; NSPredicate *const anyActive =
[NSPredicate predicateWithFormat:@"self isKindOfClass: %@ AND active == TRUE", [RNSVGNode class]];
NSArray *const filtered = [self.subviews filteredArrayUsingPredicate:anyActive]; NSArray *const filtered = [self.subviews filteredArrayUsingPredicate:anyActive];
if ([filtered count] != 0) { if ([filtered count] != 0) {
return [filtered.lastObject hitTest:transformed withEvent:event]; return [filtered.lastObject hitTest:transformed withEvent:event];

View File

@@ -9,9 +9,9 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import <React/RCTBridge.h> #import <React/RCTBridge.h>
#import "RNSVGLength.h"
#import "RNSVGRenderable.h" #import "RNSVGRenderable.h"
#import "RNSVGVBMOS.h" #import "RNSVGVBMOS.h"
#import "RNSVGLength.h"
#import <React/RCTImageSource.h> #import <React/RCTImageSource.h>

View File

@@ -15,25 +15,25 @@
#else #else
#import <React/RCTImageURLLoader.h>
#import <React/RCTImageShadowView.h>
#import <React/RCTImageView.h>
#import <React/RCTImageLoaderProtocol.h> #import <React/RCTImageLoaderProtocol.h>
#import <React/RCTImageShadowView.h>
#import <React/RCTImageURLLoader.h>
#import <React/RCTImageView.h>
#endif // RN_FABRIC_ENABLED #endif // RN_FABRIC_ENABLED
#import <React/RCTLog.h> #import <React/RCTLog.h>
#import "RNSVGViewBox.h"
#import "RCTBridge.h" #import "RCTBridge.h"
#import "RNSVGViewBox.h"
#ifdef RN_FABRIC_ENABLED #ifdef RN_FABRIC_ENABLED
#import <react/renderer/components/rnsvg/ComponentDescriptors.h> #import <react/renderer/components/rnsvg/ComponentDescriptors.h>
#import "RCTFabricComponentsPlugins.h"
#import "RCTConversions.h"
#import <react/renderer/components/view/conversions.h> #import <react/renderer/components/view/conversions.h>
#import "RNSVGFabricConversions.h" #import "RCTConversions.h"
#import "RCTFabricComponentsPlugins.h"
#import "RCTImagePrimitivesConversions.h" #import "RCTImagePrimitivesConversions.h"
#import "RCTImageSource.h" #import "RCTImageSource.h"
#import "RNSVGFabricConversions.h"
// Some RN private method hacking below similar to how it is done in RNScreens: // Some RN private method hacking below similar to how it is done in RNScreens:
// https://github.com/software-mansion/react-native-screens/blob/90e548739f35b5ded2524a9d6410033fc233f586/ios/RNSScreenStackHeaderConfig.mm#L30 // https://github.com/software-mansion/react-native-screens/blob/90e548739f35b5ded2524a9d6410033fc233f586/ios/RNSScreenStackHeaderConfig.mm#L30
@@ -43,8 +43,7 @@
#endif // RN_FABRIC_ENABLED #endif // RN_FABRIC_ENABLED
@implementation RNSVGImage @implementation RNSVGImage {
{
CGImageRef _image; CGImageRef _image;
CGSize _imageSize; CGSize _imageSize;
RCTImageLoaderCancellationBlock _reloadImageCancellationBlock; RCTImageLoaderCancellationBlock _reloadImageCancellationBlock;
@@ -143,7 +142,9 @@ using namespace facebook::react;
_reloadImageCancellationBlock = nil; _reloadImageCancellationBlock = nil;
} }
_reloadImageCancellationBlock = [[self.bridge moduleForName:@"ImageLoader"] loadImageWithURLRequest:[RCTConvert NSURLRequest:src] callback:^(NSError *error, UIImage *image) { _reloadImageCancellationBlock = [[self.bridge moduleForName:@"ImageLoader"]
loadImageWithURLRequest:[RCTConvert NSURLRequest:src]
callback:^(NSError *error, UIImage *image) {
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
self->_image = CGImageRetain(image.CGImage); self->_image = CGImageRetain(image.CGImage);
self->_imageSize = CGSizeMake(CGImageGetWidth(self->_image), CGImageGetHeight(self->_image)); self->_imageSize = CGSizeMake(CGImageGetWidth(self->_image), CGImageGetHeight(self->_image));
@@ -260,7 +261,10 @@ using namespace facebook::react;
// apply viewBox transform on Image render. // apply viewBox transform on Image render.
CGRect imageBounds = CGRectMake(0, 0, _imageSize.width, _imageSize.height); CGRect imageBounds = CGRectMake(0, 0, _imageSize.width, _imageSize.height);
CGAffineTransform viewbox = [RNSVGViewBox getTransform:imageBounds eRect:hitArea align:self.align meetOrSlice:self.meetOrSlice]; CGAffineTransform viewbox = [RNSVGViewBox getTransform:imageBounds
eRect:hitArea
align:self.align
meetOrSlice:self.meetOrSlice];
[self clip:context]; [self clip:context];
CGContextClipToRect(context, hitArea); CGContextClipToRect(context, hitArea);

View File

@@ -6,8 +6,8 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#import "RNSVGNode.h"
#import "RNSVGLength.h" #import "RNSVGLength.h"
#import "RNSVGNode.h"
@interface RNSVGLinearGradient : RNSVGNode @interface RNSVGLinearGradient : RNSVGNode

View File

@@ -6,14 +6,14 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#import "RNSVGLinearGradient.h" #import "RNSVGLinearGradient.h"
#import "RNSVGPainter.h"
#import "RNSVGBrushType.h" #import "RNSVGBrushType.h"
#import "RNSVGPainter.h"
#ifdef RN_FABRIC_ENABLED #ifdef RN_FABRIC_ENABLED
#import <react/renderer/components/rnsvg/ComponentDescriptors.h> #import <react/renderer/components/rnsvg/ComponentDescriptors.h>
#import "RCTFabricComponentsPlugins.h"
#import "RCTConversions.h"
#import <react/renderer/components/view/conversions.h> #import <react/renderer/components/view/conversions.h>
#import "RCTConversions.h"
#import "RCTFabricComponentsPlugins.h"
#import "RNSVGFabricConversions.h" #import "RNSVGFabricConversions.h"
#endif // RN_FABRIC_ENABLED #endif // RN_FABRIC_ENABLED
@@ -55,7 +55,13 @@ using namespace facebook::react;
} }
self.gradientUnits = newProps.gradientUnits == 0 ? kRNSVGUnitsObjectBoundingBox : kRNSVGUnitsUserSpaceOnUse; self.gradientUnits = newProps.gradientUnits == 0 ? kRNSVGUnitsObjectBoundingBox : kRNSVGUnitsUserSpaceOnUse;
if (newProps.gradientTransform.size() == 6) { if (newProps.gradientTransform.size() == 6) {
self.gradientTransform = CGAffineTransformMake(newProps.gradientTransform.at(0), newProps.gradientTransform.at(1), newProps.gradientTransform.at(2), newProps.gradientTransform.at(3), newProps.gradientTransform.at(4), newProps.gradientTransform.at(5)); self.gradientTransform = CGAffineTransformMake(
newProps.gradientTransform.at(0),
newProps.gradientTransform.at(1),
newProps.gradientTransform.at(2),
newProps.gradientTransform.at(3),
newProps.gradientTransform.at(4),
newProps.gradientTransform.at(5));
} }
setCommonNodeProps(newProps, self); setCommonNodeProps(newProps, self);

View File

@@ -19,6 +19,9 @@
@property (nonatomic, strong) NSString *align; @property (nonatomic, strong) NSString *align;
@property (nonatomic, assign) RNSVGVBMOS meetOrSlice; @property (nonatomic, assign) RNSVGVBMOS meetOrSlice;
- (void)renderMarker:(CGContextRef)context rect:(CGRect)rect position:(RNSVGMarkerPosition*)position strokeWidth:(CGFloat)strokeWidth; - (void)renderMarker:(CGContextRef)context
rect:(CGRect)rect
position:(RNSVGMarkerPosition *)position
strokeWidth:(CGFloat)strokeWidth;
@end @end

View File

@@ -6,16 +6,16 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#import "RNSVGMarker.h" #import "RNSVGMarker.h"
#import "RNSVGPainter.h"
#import "RNSVGBrushType.h" #import "RNSVGBrushType.h"
#import "RNSVGNode.h" #import "RNSVGNode.h"
#import "RNSVGPainter.h"
#import "RNSVGViewBox.h" #import "RNSVGViewBox.h"
#ifdef RN_FABRIC_ENABLED #ifdef RN_FABRIC_ENABLED
#import <react/renderer/components/rnsvg/ComponentDescriptors.h> #import <react/renderer/components/rnsvg/ComponentDescriptors.h>
#import "RCTFabricComponentsPlugins.h"
#import "RCTConversions.h"
#import <react/renderer/components/view/conversions.h> #import <react/renderer/components/view/conversions.h>
#import "RCTConversions.h"
#import "RCTFabricComponentsPlugins.h"
#import "RNSVGFabricConversions.h" #import "RNSVGFabricConversions.h"
#endif // RN_FABRIC_ENABLED #endif // RN_FABRIC_ENABLED
@@ -219,11 +219,15 @@ using namespace facebook::react;
static CGFloat RNSVG_degToRad = (CGFloat)M_PI / 180; static CGFloat RNSVG_degToRad = (CGFloat)M_PI / 180;
double deg2rad(CGFloat deg) { double deg2rad(CGFloat deg)
{
return deg * RNSVG_degToRad; return deg * RNSVG_degToRad;
} }
- (void)renderMarker:(CGContextRef)context rect:(CGRect)rect position:(RNSVGMarkerPosition*)position strokeWidth:(CGFloat)strokeWidth - (void)renderMarker:(CGContextRef)context
rect:(CGRect)rect
position:(RNSVGMarkerPosition *)position
strokeWidth:(CGFloat)strokeWidth
{ {
CGContextSaveGState(context); CGContextSaveGState(context);
@@ -244,7 +248,8 @@ double deg2rad(CGFloat deg) {
CGFloat height = [self relativeOnHeight:self.markerHeight]; CGFloat height = [self relativeOnHeight:self.markerHeight];
CGRect eRect = CGRectMake(0, 0, width, height); CGRect eRect = CGRectMake(0, 0, width, height);
if (self.align) { if (self.align) {
CGAffineTransform viewBoxTransform = [RNSVGViewBox getTransform:CGRectMake(self.minX, self.minY, self.vbWidth, self.vbHeight) CGAffineTransform viewBoxTransform =
[RNSVGViewBox getTransform:CGRectMake(self.minX, self.minY, self.vbWidth, self.vbHeight)
eRect:eRect eRect:eRect
align:self.align align:self.align
meetOrSlice:self.meetOrSlice]; meetOrSlice:self.meetOrSlice];
@@ -265,7 +270,6 @@ double deg2rad(CGFloat deg) {
@end @end
#ifdef RN_FABRIC_ENABLED #ifdef RN_FABRIC_ENABLED
Class<RCTComponentViewProtocol> RNSVGMarkerCls(void) Class<RCTComponentViewProtocol> RNSVGMarkerCls(void)
{ {

View File

@@ -6,16 +6,15 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#import "RNSVGMask.h" #import "RNSVGMask.h"
#import "RNSVGPainter.h"
#import "RNSVGBrushType.h" #import "RNSVGBrushType.h"
#import "RNSVGNode.h" #import "RNSVGNode.h"
#import "RNSVGPainter.h"
#ifdef RN_FABRIC_ENABLED #ifdef RN_FABRIC_ENABLED
#import <react/renderer/components/rnsvg/ComponentDescriptors.h> #import <react/renderer/components/rnsvg/ComponentDescriptors.h>
#import "RCTFabricComponentsPlugins.h"
#import "RCTConversions.h"
#import <react/renderer/components/view/conversions.h> #import <react/renderer/components/view/conversions.h>
#import "RCTConversions.h"
#import "RCTFabricComponentsPlugins.h"
#import "RNSVGFabricConversions.h" #import "RNSVGFabricConversions.h"
#endif // RN_FABRIC_ENABLED #endif // RN_FABRIC_ENABLED
@@ -61,7 +60,13 @@ using namespace facebook::react;
self.maskUnits = newProps.maskUnits == 0 ? kRNSVGUnitsObjectBoundingBox : kRNSVGUnitsUserSpaceOnUse; self.maskUnits = newProps.maskUnits == 0 ? kRNSVGUnitsObjectBoundingBox : kRNSVGUnitsUserSpaceOnUse;
self.maskContentUnits = newProps.maskUnits == 0 ? kRNSVGUnitsObjectBoundingBox : kRNSVGUnitsUserSpaceOnUse; self.maskContentUnits = newProps.maskUnits == 0 ? kRNSVGUnitsObjectBoundingBox : kRNSVGUnitsUserSpaceOnUse;
if (newProps.maskTransform.size() == 6) { if (newProps.maskTransform.size() == 6) {
self.maskTransform = CGAffineTransformMake(newProps.maskTransform.at(0), newProps.maskTransform.at(1), newProps.maskTransform.at(2), newProps.maskTransform.at(3), newProps.maskTransform.at(4), newProps.maskTransform.at(5)); self.maskTransform = CGAffineTransformMake(
newProps.maskTransform.at(0),
newProps.maskTransform.at(1),
newProps.maskTransform.at(2),
newProps.maskTransform.at(3),
newProps.maskTransform.at(4),
newProps.maskTransform.at(5));
} }
setCommonGroupProps(newProps, self); setCommonGroupProps(newProps, self);

View File

@@ -10,14 +10,13 @@
#ifdef RN_FABRIC_ENABLED #ifdef RN_FABRIC_ENABLED
#import <react/renderer/components/rnsvg/ComponentDescriptors.h> #import <react/renderer/components/rnsvg/ComponentDescriptors.h>
#import "RCTFabricComponentsPlugins.h"
#import "RCTConversions.h"
#import <react/renderer/components/view/conversions.h> #import <react/renderer/components/view/conversions.h>
#import "RCTConversions.h"
#import "RCTFabricComponentsPlugins.h"
#import "RNSVGFabricConversions.h" #import "RNSVGFabricConversions.h"
#endif // RN_FABRIC_ENABLED #endif // RN_FABRIC_ENABLED
@implementation RNSVGPath @implementation RNSVGPath {
{
CGPathRef _path; CGPathRef _path;
} }

View File

@@ -6,15 +6,15 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#import "RNSVGPattern.h" #import "RNSVGPattern.h"
#import "RNSVGPainter.h"
#import "RNSVGBrushType.h" #import "RNSVGBrushType.h"
#import "RNSVGNode.h" #import "RNSVGNode.h"
#import "RNSVGPainter.h"
#ifdef RN_FABRIC_ENABLED #ifdef RN_FABRIC_ENABLED
#import <react/renderer/components/rnsvg/ComponentDescriptors.h> #import <react/renderer/components/rnsvg/ComponentDescriptors.h>
#import "RCTFabricComponentsPlugins.h"
#import "RCTConversions.h"
#import <react/renderer/components/view/conversions.h> #import <react/renderer/components/view/conversions.h>
#import "RCTConversions.h"
#import "RCTFabricComponentsPlugins.h"
#import "RNSVGFabricConversions.h" #import "RNSVGFabricConversions.h"
#endif // RN_FABRIC_ENABLED #endif // RN_FABRIC_ENABLED
@@ -60,7 +60,13 @@ using namespace facebook::react;
self.patternUnits = newProps.patternUnits == 0 ? kRNSVGUnitsObjectBoundingBox : kRNSVGUnitsUserSpaceOnUse; self.patternUnits = newProps.patternUnits == 0 ? kRNSVGUnitsObjectBoundingBox : kRNSVGUnitsUserSpaceOnUse;
self.patternContentUnits = newProps.patternUnits == 0 ? kRNSVGUnitsObjectBoundingBox : kRNSVGUnitsUserSpaceOnUse; self.patternContentUnits = newProps.patternUnits == 0 ? kRNSVGUnitsObjectBoundingBox : kRNSVGUnitsUserSpaceOnUse;
if (newProps.patternTransform.size() == 6) { if (newProps.patternTransform.size() == 6) {
self.patternTransform = CGAffineTransformMake(newProps.patternTransform.at(0), newProps.patternTransform.at(1), newProps.patternTransform.at(2), newProps.patternTransform.at(3), newProps.patternTransform.at(4), newProps.patternTransform.at(5)); self.patternTransform = CGAffineTransformMake(
newProps.patternTransform.at(0),
newProps.patternTransform.at(1),
newProps.patternTransform.at(2),
newProps.patternTransform.at(3),
newProps.patternTransform.at(4),
newProps.patternTransform.at(5));
} }
self.minX = newProps.minX; self.minX = newProps.minX;
self.minY = newProps.minY; self.minY = newProps.minY;

View File

@@ -6,8 +6,8 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#import "RNSVGNode.h"
#import "RNSVGLength.h" #import "RNSVGLength.h"
#import "RNSVGNode.h"
@interface RNSVGRadialGradient : RNSVGNode @interface RNSVGRadialGradient : RNSVGNode

View File

@@ -9,9 +9,9 @@
#ifdef RN_FABRIC_ENABLED #ifdef RN_FABRIC_ENABLED
#import <react/renderer/components/rnsvg/ComponentDescriptors.h> #import <react/renderer/components/rnsvg/ComponentDescriptors.h>
#import "RCTFabricComponentsPlugins.h"
#import "RCTConversions.h"
#import <react/renderer/components/view/conversions.h> #import <react/renderer/components/view/conversions.h>
#import "RCTConversions.h"
#import "RCTFabricComponentsPlugins.h"
#import "RNSVGFabricConversions.h" #import "RNSVGFabricConversions.h"
#endif // RN_FABRIC_ENABLED #endif // RN_FABRIC_ENABLED
@@ -55,7 +55,13 @@ using namespace facebook::react;
} }
self.gradientUnits = newProps.gradientUnits == 0 ? kRNSVGUnitsObjectBoundingBox : kRNSVGUnitsUserSpaceOnUse; self.gradientUnits = newProps.gradientUnits == 0 ? kRNSVGUnitsObjectBoundingBox : kRNSVGUnitsUserSpaceOnUse;
if (newProps.gradientTransform.size() == 6) { if (newProps.gradientTransform.size() == 6) {
self.gradientTransform = CGAffineTransformMake(newProps.gradientTransform.at(0), newProps.gradientTransform.at(1), newProps.gradientTransform.at(2), newProps.gradientTransform.at(3), newProps.gradientTransform.at(4), newProps.gradientTransform.at(5)); self.gradientTransform = CGAffineTransformMake(
newProps.gradientTransform.at(0),
newProps.gradientTransform.at(1),
newProps.gradientTransform.at(2),
newProps.gradientTransform.at(3),
newProps.gradientTransform.at(4),
newProps.gradientTransform.at(5));
} }
setCommonNodeProps(newProps, self); setCommonNodeProps(newProps, self);

View File

@@ -8,8 +8,8 @@
#import "RNSVGUIKit.h" #import "RNSVGUIKit.h"
#import "RNSVGPainter.h"
#import "RNSVGContainer.h" #import "RNSVGContainer.h"
#import "RNSVGPainter.h"
#import "RNSVGVBMOS.h" #import "RNSVGVBMOS.h"
#ifdef RN_FABRIC_ENABLED #ifdef RN_FABRIC_ENABLED

View File

@@ -7,20 +7,19 @@
*/ */
#import "RNSVGSvgView.h" #import "RNSVGSvgView.h"
#import "RNSVGViewBox.h"
#import "RNSVGNode.h"
#import <React/RCTLog.h> #import <React/RCTLog.h>
#import "RNSVGNode.h"
#import "RNSVGViewBox.h"
#ifdef RN_FABRIC_ENABLED #ifdef RN_FABRIC_ENABLED
#import <react/renderer/components/rnsvg/ComponentDescriptors.h> #import <react/renderer/components/rnsvg/ComponentDescriptors.h>
#import "RCTFabricComponentsPlugins.h"
#import "RCTConversions.h"
#import <react/renderer/components/view/conversions.h> #import <react/renderer/components/view/conversions.h>
#import "RCTConversions.h"
#import "RCTFabricComponentsPlugins.h"
#import "RNSVGFabricConversions.h" #import "RNSVGFabricConversions.h"
#endif // RN_FABRIC_ENABLED #endif // RN_FABRIC_ENABLED
@implementation RNSVGSvgView @implementation RNSVGSvgView {
{
NSMutableDictionary<NSString *, RNSVGNode *> *_clipPaths; NSMutableDictionary<NSString *, RNSVGNode *> *_clipPaths;
NSMutableDictionary<NSString *, RNSVGNode *> *_templates; NSMutableDictionary<NSString *, RNSVGNode *> *_templates;
NSMutableDictionary<NSString *, RNSVGPainter *> *_painters; NSMutableDictionary<NSString *, RNSVGPainter *> *_painters;
@@ -81,7 +80,6 @@ using namespace facebook::react;
} }
} }
- (void)prepareForRecycle - (void)prepareForRecycle
{ {
[super prepareForRecycle]; [super prepareForRecycle];
@@ -251,16 +249,14 @@ using namespace facebook::react;
_meetOrSlice = meetOrSlice; _meetOrSlice = meetOrSlice;
} }
- (void)drawToContext:(CGContextRef)context withRect:(CGRect)rect { - (void)drawToContext:(CGContextRef)context withRect:(CGRect)rect
{
rendered = true; rendered = true;
self.initialCTM = CGContextGetCTM(context); self.initialCTM = CGContextGetCTM(context);
self.invInitialCTM = CGAffineTransformInvert(self.initialCTM); self.invInitialCTM = CGAffineTransformInvert(self.initialCTM);
if (self.align) { if (self.align) {
CGRect tRect = CGRectMake(self.minX, self.minY, self.vbWidth, self.vbHeight); CGRect tRect = CGRectMake(self.minX, self.minY, self.vbWidth, self.vbHeight);
_viewBoxTransform = [RNSVGViewBox getTransform:tRect _viewBoxTransform = [RNSVGViewBox getTransform:tRect eRect:rect align:self.align meetOrSlice:self.meetOrSlice];
eRect:rect
align:self.align
meetOrSlice:self.meetOrSlice];
_invviewBoxTransform = CGAffineTransformInvert(_viewBoxTransform); _invviewBoxTransform = CGAffineTransformInvert(_viewBoxTransform);
CGContextConcatCTM(context, _viewBoxTransform); CGContextConcatCTM(context, _viewBoxTransform);
} else { } else {
@@ -271,8 +267,7 @@ using namespace facebook::react;
for (RNSVGView *node in self.subviews) { for (RNSVGView *node in self.subviews) {
if ([node isKindOfClass:[RNSVGNode class]]) { if ([node isKindOfClass:[RNSVGNode class]]) {
RNSVGNode *svg = (RNSVGNode *)node; RNSVGNode *svg = (RNSVGNode *)node;
[svg renderTo:context [svg renderTo:context rect:rect];
rect:rect];
} else { } else {
[node drawRect:rect]; [node drawRect:rect];
} }
@@ -388,7 +383,6 @@ using namespace facebook::react;
return _templates ? [_templates objectForKey:templateName] : nil; return _templates ? [_templates objectForKey:templateName] : nil;
} }
- (void)definePainter:(RNSVGPainter *)painter painterName:(NSString *)painterName - (void)definePainter:(RNSVGPainter *)painter painterName:(NSString *)painterName
{ {
if (!_painters) { if (!_painters) {

View File

@@ -10,9 +10,9 @@
#ifdef RN_FABRIC_ENABLED #ifdef RN_FABRIC_ENABLED
#import <react/renderer/components/rnsvg/ComponentDescriptors.h> #import <react/renderer/components/rnsvg/ComponentDescriptors.h>
#import "RCTFabricComponentsPlugins.h"
#import "RCTConversions.h"
#import <react/renderer/components/view/conversions.h> #import <react/renderer/components/view/conversions.h>
#import "RCTConversions.h"
#import "RCTFabricComponentsPlugins.h"
#import "RNSVGFabricConversions.h" #import "RNSVGFabricConversions.h"
#endif // RN_FABRIC_ENABLED #endif // RN_FABRIC_ENABLED
@@ -134,8 +134,8 @@ using namespace facebook::react;
{ {
CGRect eRect = CGRectMake(0, 0, width, height); CGRect eRect = CGRectMake(0, 0, width, height);
if (self.align) { if (self.align) {
CGAffineTransform viewBoxTransform =
CGAffineTransform viewBoxTransform = [RNSVGViewBox getTransform:CGRectMake(self.minX, self.minY, self.vbWidth, self.vbHeight) [RNSVGViewBox getTransform:CGRectMake(self.minX, self.minY, self.vbWidth, self.vbHeight)
eRect:eRect eRect:eRect
align:self.align align:self.align
meetOrSlice:self.meetOrSlice]; meetOrSlice:self.meetOrSlice];

View File

@@ -6,8 +6,8 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#import "RNSVGRenderable.h"
#import "RNSVGLength.h" #import "RNSVGLength.h"
#import "RNSVGRenderable.h"
/** /**
* RNSVG defination are implemented as abstract UIViews for all elements inside Defs. * RNSVG defination are implemented as abstract UIViews for all elements inside Defs.

View File

@@ -6,14 +6,14 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#import "RNSVGUse.h" #import "RNSVGUse.h"
#import "RNSVGSymbol.h"
#import <React/RCTLog.h> #import <React/RCTLog.h>
#import "RNSVGSymbol.h"
#ifdef RN_FABRIC_ENABLED #ifdef RN_FABRIC_ENABLED
#import <react/renderer/components/rnsvg/ComponentDescriptors.h> #import <react/renderer/components/rnsvg/ComponentDescriptors.h>
#import "RCTFabricComponentsPlugins.h"
#import "RCTConversions.h"
#import <react/renderer/components/view/conversions.h> #import <react/renderer/components/view/conversions.h>
#import "RCTConversions.h"
#import "RCTFabricComponentsPlugins.h"
#import "RNSVGFabricConversions.h" #import "RNSVGFabricConversions.h"
#endif // RN_FABRIC_ENABLED #endif // RN_FABRIC_ENABLED
@@ -102,7 +102,6 @@ using namespace facebook::react;
_y = y; _y = y;
} }
- (void)setUsewidth:(RNSVGLength *)usewidth - (void)setUsewidth:(RNSVGLength *)usewidth
{ {
if ([usewidth isEqualTo:_usewidth]) { if ([usewidth isEqualTo:_usewidth]) {
@@ -137,7 +136,9 @@ using namespace facebook::react;
if ([definedTemplate class] == [RNSVGSymbol class]) { if ([definedTemplate class] == [RNSVGSymbol class]) {
RNSVGSymbol *symbol = (RNSVGSymbol *)definedTemplate; RNSVGSymbol *symbol = (RNSVGSymbol *)definedTemplate;
[symbol renderSymbolTo:context width:[self relativeOnWidth:self.usewidth] height:[self relativeOnHeight:self.useheight]]; [symbol renderSymbolTo:context
width:[self relativeOnWidth:self.usewidth]
height:[self relativeOnHeight:self.useheight]];
} else { } else {
[definedTemplate renderTo:context rect:rect]; [definedTemplate renderTo:context rect:rect];
} }
@@ -149,7 +150,9 @@ using namespace facebook::react;
[self endTransparencyLayer:context]; [self endTransparencyLayer:context];
} else if (self.href) { } else if (self.href) {
// TODO: calling yellow box here // TODO: calling yellow box here
RCTLogWarn(@"`Use` element expected a pre-defined svg template as `href` prop, template named: %@ is not defined.", self.href); RCTLogWarn(
@"`Use` element expected a pre-defined svg template as `href` prop, template named: %@ is not defined.",
self.href);
return; return;
} else { } else {
return; return;
@@ -174,7 +177,8 @@ using namespace facebook::react;
self.frame = bounds; self.frame = bounds;
} }
- (RNSVGPlatformView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { - (RNSVGPlatformView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix); CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix);
transformed = CGPointApplyAffineTransform(transformed, self.invTransform); transformed = CGPointApplyAffineTransform(transformed, self.invTransform);
RNSVGNode const *definedTemplate = [self.svgView getDefinedTemplate:self.href]; RNSVGNode const *definedTemplate = [self.svgView getDefinedTemplate:self.href];
@@ -193,7 +197,8 @@ using namespace facebook::react;
- (CGPathRef)getPath:(CGContextRef)context - (CGPathRef)getPath:(CGContextRef)context
{ {
CGAffineTransform transform = CGAffineTransformMakeTranslation([self relativeOnWidth:self.x], [self relativeOnHeight:self.y]); CGAffineTransform transform =
CGAffineTransformMakeTranslation([self relativeOnWidth:self.x], [self relativeOnHeight:self.y]);
RNSVGNode const *definedTemplate = [self.svgView getDefinedTemplate:self.href]; RNSVGNode const *definedTemplate = [self.svgView getDefinedTemplate:self.href];
if (!definedTemplate) { if (!definedTemplate) {
return nil; return nil;

View File

@@ -6,10 +6,11 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#import "RNSVGSvgView.h"
#import <React/UIView+React.h>
#import <React/RCTPointerEvents.h>
#import "RNSVGCGFCRule.h" #import "RNSVGCGFCRule.h"
#import "RNSVGSvgView.h"
#import <React/RCTPointerEvents.h>
#import <React/UIView+React.h>
#ifdef RN_FABRIC_ENABLED #ifdef RN_FABRIC_ENABLED
#import <React/RCTViewComponentView.h> #import <React/RCTViewComponentView.h>
@@ -73,7 +74,6 @@ extern CGFloat const RNSVG_DEFAULT_FONT_SIZE;
@property (nonatomic, assign) CGRect markerBounds; @property (nonatomic, assign) CGRect markerBounds;
@property (nonatomic, copy) RCTDirectEventBlock onLayout; @property (nonatomic, copy) RCTDirectEventBlock onLayout;
/** /**
* RNSVGSvgView which ownes current RNSVGNode * RNSVGSvgView which ownes current RNSVGNode
*/ */

View File

@@ -7,18 +7,17 @@
*/ */
#import "RNSVGNode.h" #import "RNSVGNode.h"
#import "RNSVGContainer.h"
#import "RNSVGClipPath.h" #import "RNSVGClipPath.h"
#import "RNSVGGroup.h" #import "RNSVGContainer.h"
#import "RNSVGGlyphContext.h" #import "RNSVGGlyphContext.h"
#import "RNSVGGroup.h"
@interface RNSVGNode () @interface RNSVGNode ()
@property (nonatomic, readwrite, weak) RNSVGSvgView *svgView; @property (nonatomic, readwrite, weak) RNSVGSvgView *svgView;
@property (nonatomic, readwrite, weak) RNSVGGroup *textRoot; @property (nonatomic, readwrite, weak) RNSVGGroup *textRoot;
@end @end
@implementation RNSVGNode @implementation RNSVGNode {
{
RNSVGGlyphContext *glyphContext; RNSVGGlyphContext *glyphContext;
BOOL _transparent; BOOL _transparent;
RNSVGClipPath *_clipNode; RNSVGClipPath *_clipNode;
@@ -233,7 +232,8 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
} }
} }
- (void)setClientRect:(CGRect)clientRect { - (void)setClientRect:(CGRect)clientRect
{
if (CGRectEqualToRect(_clientRect, clientRect)) { if (CGRectEqualToRect(_clientRect, clientRect)) {
return; return;
} }
@@ -247,7 +247,6 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
@"height" : @(_clientRect.size.height), @"height" : @(_clientRect.size.height),
} }
}); });
} }
} }
@@ -376,7 +375,6 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
// hitTest delagate // hitTest delagate
- (RNSVGPlatformView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event - (RNSVGPlatformView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{ {
// abstract // abstract
return nil; return nil;
} }
@@ -465,7 +463,8 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
return [self fromRelative:length]; return [self fromRelative:length];
} }
- (CGFloat)fromRelative:(RNSVGLength*)length { - (CGFloat)fromRelative:(RNSVGLength *)length
{
CGFloat unit; CGFloat unit;
switch (length.unit) { switch (length.unit) {
case SVG_LENGTHTYPE_EMS: case SVG_LENGTHTYPE_EMS:
@@ -512,7 +511,8 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
return CGRectGetHeight([self getContextBounds]); return CGRectGetHeight([self getContextBounds]);
} }
- (CGFloat)getContextDiagonal { - (CGFloat)getContextDiagonal
{
CGRect bounds = [self getContextBounds]; CGRect bounds = [self getContextBounds];
CGFloat width = CGRectGetWidth(bounds); CGFloat width = CGRectGetWidth(bounds);
CGFloat height = CGRectGetHeight(bounds); CGFloat height = CGRectGetHeight(bounds);
@@ -522,7 +522,8 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
return r; return r;
} }
- (CGFloat) getCanvasWidth { - (CGFloat)getCanvasWidth
{
if (canvasWidth != -1) { if (canvasWidth != -1) {
return canvasWidth; return canvasWidth;
} }
@@ -536,7 +537,8 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
return canvasWidth; return canvasWidth;
} }
- (CGFloat) getCanvasHeight { - (CGFloat)getCanvasHeight
{
if (canvasHeight != -1) { if (canvasHeight != -1) {
return canvasHeight; return canvasHeight;
} }
@@ -550,7 +552,8 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
return canvasHeight; return canvasHeight;
} }
- (CGFloat) getCanvasDiagonal { - (CGFloat)getCanvasDiagonal
{
if (canvasDiagonal != -1) { if (canvasDiagonal != -1) {
return canvasDiagonal; return canvasDiagonal;
} }
@@ -636,7 +639,6 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
_svgView = nil; _svgView = nil;
_textRoot = nil; _textRoot = nil;
glyphContext = nil; glyphContext = nil;
_transparent = NO; _transparent = NO;
_clipNode = nil; _clipNode = nil;

View File

@@ -12,8 +12,8 @@
#import "RNSVGBrush.h" #import "RNSVGBrush.h"
#import "RNSVGCGFCRule.h" #import "RNSVGCGFCRule.h"
#import "RNSVGNode.h"
#import "RNSVGLength.h" #import "RNSVGLength.h"
#import "RNSVGNode.h"
#import "RNSVGVectorEffect.h" #import "RNSVGVectorEffect.h"
@interface RNSVGRenderable : RNSVGNode @interface RNSVGRenderable : RNSVGNode

View File

@@ -6,18 +6,17 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#import <React/RCTPointerEvents.h>
#import "RNSVGRenderable.h" #import "RNSVGRenderable.h"
#import "RNSVGClipPath.h" #import <React/RCTPointerEvents.h>
#import "RNSVGMask.h"
#import "RNSVGViewBox.h"
#import "RNSVGVectorEffect.h"
#import "RNSVGBezierElement.h" #import "RNSVGBezierElement.h"
#import "RNSVGClipPath.h"
#import "RNSVGMarker.h" #import "RNSVGMarker.h"
#import "RNSVGMarkerPosition.h" #import "RNSVGMarkerPosition.h"
#import "RNSVGMask.h"
#import "RNSVGVectorEffect.h"
#import "RNSVGViewBox.h"
@implementation RNSVGRenderable @implementation RNSVGRenderable {
{
NSMutableDictionary *_originProperties; NSMutableDictionary *_originProperties;
NSArray<NSString *> *_lastMergedList; NSArray<NSString *> *_lastMergedList;
NSArray<NSString *> *_attributeList; NSArray<NSString *> *_attributeList;
@@ -27,8 +26,14 @@
} }
static RNSVGRenderable *_contextElement; static RNSVGRenderable *_contextElement;
+ (RNSVGRenderable *)contextElement { return _contextElement; } + (RNSVGRenderable *)contextElement
+ (void)setContextElement:(RNSVGRenderable *)contextElement { _contextElement = contextElement; } {
return _contextElement;
}
+ (void)setContextElement:(RNSVGRenderable *)contextElement
{
_contextElement = contextElement;
}
- (id)init - (id)init
{ {
@@ -217,7 +222,8 @@ static RNSVGRenderable * _contextElement;
} }
#endif // RN_FABRIC_ENABLED #endif // RN_FABRIC_ENABLED
UInt32 saturate(CGFloat value) { UInt32 saturate(CGFloat value)
{
return value <= 0 ? 0 : value >= 255 ? 255 : (UInt32)value; return value <= 0 ? 0 : value >= 255 ? 255 : (UInt32)value;
} }
@@ -258,18 +264,21 @@ UInt32 saturate(CGFloat value) {
NSUInteger bytesPerRow = bytesPerPixel * scaledWidth; NSUInteger bytesPerRow = bytesPerPixel * scaledWidth;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
UInt32 *pixels = (UInt32 *)calloc(npixels, sizeof(UInt32)); UInt32 *pixels = (UInt32 *)calloc(npixels, sizeof(UInt32));
CGContextRef bcontext = CGBitmapContextCreate(pixels, scaledWidth, scaledHeight, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); CGContextRef bcontext = CGBitmapContextCreate(
pixels,
scaledWidth,
scaledHeight,
bitsPerComponent,
bytesPerRow,
colorSpace,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGContextScaleCTM(bcontext, iscale, iscale); CGContextScaleCTM(bcontext, iscale, iscale);
// Clip to mask bounds and render the mask // Clip to mask bounds and render the mask
CGFloat x = [self relativeOn:[_maskNode x] CGFloat x = [self relativeOn:[_maskNode x] relative:width];
relative:width]; CGFloat y = [self relativeOn:[_maskNode y] relative:height];
CGFloat y = [self relativeOn:[_maskNode y] CGFloat w = [self relativeOn:[_maskNode maskwidth] relative:width];
relative:height]; CGFloat h = [self relativeOn:[_maskNode maskheight] relative:height];
CGFloat w = [self relativeOn:[_maskNode maskwidth]
relative:width];
CGFloat h = [self relativeOn:[_maskNode maskheight]
relative:height];
CGRect maskBounds = CGRectMake(x, y, w, h); CGRect maskBounds = CGRectMake(x, y, w, h);
CGContextClipToRect(bcontext, maskBounds); CGContextClipToRect(bcontext, maskBounds);
[_maskNode renderLayerTo:bcontext rect:rect]; [_maskNode renderLayerTo:bcontext rect:rect];
@@ -334,7 +343,8 @@ UInt32 saturate(CGFloat value) {
[self renderMarkers:context path:self.path rect:&rect]; [self renderMarkers:context path:self.path rect:&rect];
} }
- (void)prepareStrokeDash:(NSUInteger)count strokeDasharray:(NSArray<RNSVGLength *> *)strokeDasharray { - (void)prepareStrokeDash:(NSUInteger)count strokeDasharray:(NSArray<RNSVGLength *> *)strokeDasharray
{
if (strokeDasharray != _sourceStrokeDashArray) { if (strokeDasharray != _sourceStrokeDashArray) {
CGFloat *dash = _strokeDashArrayData; CGFloat *dash = _strokeDashArrayData;
_strokeDashArrayData = (CGFloat *)realloc(dash, sizeof(CGFloat) * count); _strokeDashArrayData = (CGFloat *)realloc(dash, sizeof(CGFloat) * count);
@@ -349,7 +359,8 @@ UInt32 saturate(CGFloat value) {
} }
} }
- (void)renderMarkers:(CGContextRef)context path:(CGPathRef)path rect:(const CGRect *)rect { - (void)renderMarkers:(CGContextRef)context path:(CGPathRef)path rect:(const CGRect *)rect
{
RNSVGMarker *markerStart = (RNSVGMarker *)[self.svgView getDefinedMarker:self.markerStart]; RNSVGMarker *markerStart = (RNSVGMarker *)[self.svgView getDefinedMarker:self.markerStart];
RNSVGMarker *markerMid = (RNSVGMarker *)[self.svgView getDefinedMarker:self.markerMid]; RNSVGMarker *markerMid = (RNSVGMarker *)[self.svgView getDefinedMarker:self.markerMid];
RNSVGMarker *markerEnd = (RNSVGMarker *)[self.svgView getDefinedMarker:self.markerEnd]; RNSVGMarker *markerEnd = (RNSVGMarker *)[self.svgView getDefinedMarker:self.markerEnd];
@@ -467,8 +478,7 @@ UInt32 saturate(CGFloat value) {
[self.fill paint:context [self.fill paint:context
opacity:self.fillOpacity opacity:self.fillOpacity
painter:[self.svgView getDefinedPainter:self.fill.brushRef] painter:[self.svgView getDefinedPainter:self.fill.brushRef]
bounds:pathBounds bounds:pathBounds];
];
CGContextRestoreGState(context); CGContextRestoreGState(context);
if (!self.stroke) { if (!self.stroke) {
@@ -524,8 +534,7 @@ UInt32 saturate(CGFloat value) {
[self.stroke paint:context [self.stroke paint:context
opacity:self.strokeOpacity opacity:self.strokeOpacity
painter:[self.svgView getDefinedPainter:self.stroke.brushRef] painter:[self.svgView getDefinedPainter:self.stroke.brushRef]
bounds:pathBounds bounds:pathBounds];
];
return; return;
} }
} }
@@ -547,9 +556,11 @@ UInt32 saturate(CGFloat value) {
if (self.stroke && self.strokeWidth) { if (self.stroke && self.strokeWidth) {
// Add stroke to hitArea // Add stroke to hitArea
CGFloat width = [self relativeOnOther:self.strokeWidth]; CGFloat width = [self relativeOnOther:self.strokeWidth];
self.strokePath = CGPathRetain((CGPathRef)CFAutorelease(CGPathCreateCopyByStrokingPath(path, nil, width, self.strokeLinecap, self.strokeLinejoin, self.strokeMiterlimit))); self.strokePath = CGPathRetain((CGPathRef)CFAutorelease(CGPathCreateCopyByStrokingPath(
path, nil, width, self.strokeLinecap, self.strokeLinejoin, self.strokeMiterlimit)));
// TODO add dashing // TODO add dashing
// CGPathCreateCopyByDashingPath(CGPathRef _Nullable path, const CGAffineTransform * _Nullable transform, CGFloat phase, const CGFloat * _Nullable lengths, size_t count) // CGPathCreateCopyByDashingPath(CGPathRef _Nullable path, const CGAffineTransform * _Nullable transform, CGFloat
// phase, const CGFloat * _Nullable lengths, size_t count)
} }
} }
@@ -580,8 +591,7 @@ UInt32 saturate(CGFloat value) {
CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix); CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix);
transformed = CGPointApplyAffineTransform(transformed, self.invTransform); transformed = CGPointApplyAffineTransform(transformed, self.invTransform);
if (!CGRectContainsPoint(self.pathBounds, transformed) && if (!CGRectContainsPoint(self.pathBounds, transformed) && !CGRectContainsPoint(self.markerBounds, transformed)) {
!CGRectContainsPoint(self.markerBounds, transformed)) {
return nil; return nil;
} }

View File

@@ -1,5 +1,5 @@
// Most (if not all) of this file could probably go away once react-native-macos's version of RCTUIKit.h makes its way upstream. // Most (if not all) of this file could probably go away once react-native-macos's version of RCTUIKit.h makes its way
// https://github.com/microsoft/react-native-macos/issues/242 // upstream. https://github.com/microsoft/react-native-macos/issues/242
#if !TARGET_OS_OSX #if !TARGET_OS_OSX
@@ -12,9 +12,9 @@
#else // TARGET_OS_OSX [ #else // TARGET_OS_OSX [
// Due to name mangling, calling c-style functions from .mm files will fail, therefore we need to wrap them with extern "C" // Due to name mangling, calling c-style functions from .mm files will fail, therefore we need to wrap them with extern
// so they are handled correctly. We also need to have imports positioned in a correct way, // "C" so they are handled correctly. We also need to have imports positioned in a correct way, so that this extern "C"
// so that this extern "C" wrapper is used before the functions from RCTUIKit are used. // wrapper is used before the functions from RCTUIKit are used.
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@@ -37,7 +37,8 @@ extern "C" {
@end @end
// TODO: These could probably be a part of react-native-macos // TODO: These could probably be a part of react-native-macos
// See https://github.com/microsoft/react-native-macos/issues/658 and https://github.com/microsoft/react-native-macos/issues/659 // See https://github.com/microsoft/react-native-macos/issues/658 and
// https://github.com/microsoft/react-native-macos/issues/659
@interface NSImage (RNSVGMacOSExtensions) @interface NSImage (RNSVGMacOSExtensions)
@property (readonly) CGImageRef CGImage; @property (readonly) CGImageRef CGImage;
@end @end

View File

@@ -1,7 +1,6 @@
#import "RNSVGUIKit.h" #import "RNSVGUIKit.h"
@implementation RNSVGView @implementation RNSVGView {
{
NSColor *_tintColor; NSColor *_tintColor;
} }
@@ -46,7 +45,6 @@
@end @end
@implementation NSImage (RNSVGMacOSExtensions) @implementation NSImage (RNSVGMacOSExtensions)
- (CGImageRef)CGImage - (CGImageRef)CGImage
@@ -56,7 +54,6 @@
@end @end
@implementation NSValue (RNSVGMacOSExtensions) @implementation NSValue (RNSVGMacOSExtensions)
+ (NSValue *)valueWithCGAffineTransform:(CGAffineTransform)transform + (NSValue *)valueWithCGAffineTransform:(CGAffineTransform)transform

View File

@@ -17,4 +17,3 @@
@property (nonatomic, strong) RNSVGLength *r; @property (nonatomic, strong) RNSVGLength *r;
@end @end

View File

@@ -11,9 +11,9 @@
#ifdef RN_FABRIC_ENABLED #ifdef RN_FABRIC_ENABLED
#import <react/renderer/components/rnsvg/ComponentDescriptors.h> #import <react/renderer/components/rnsvg/ComponentDescriptors.h>
#import "RCTFabricComponentsPlugins.h"
#import "RCTConversions.h"
#import <react/renderer/components/view/conversions.h> #import <react/renderer/components/view/conversions.h>
#import "RCTConversions.h"
#import "RCTFabricComponentsPlugins.h"
#import "RNSVGFabricConversions.h" #import "RNSVGFabricConversions.h"
#endif // RN_FABRIC_ENABLED #endif // RN_FABRIC_ENABLED

View File

@@ -11,9 +11,9 @@
#ifdef RN_FABRIC_ENABLED #ifdef RN_FABRIC_ENABLED
#import <react/renderer/components/rnsvg/ComponentDescriptors.h> #import <react/renderer/components/rnsvg/ComponentDescriptors.h>
#import "RCTFabricComponentsPlugins.h"
#import "RCTConversions.h"
#import <react/renderer/components/view/conversions.h> #import <react/renderer/components/view/conversions.h>
#import "RCTConversions.h"
#import "RCTFabricComponentsPlugins.h"
#import "RNSVGFabricConversions.h" #import "RNSVGFabricConversions.h"
#endif // RN_FABRIC_ENABLED #endif // RN_FABRIC_ENABLED

View File

@@ -11,9 +11,9 @@
#ifdef RN_FABRIC_ENABLED #ifdef RN_FABRIC_ENABLED
#import <react/renderer/components/rnsvg/ComponentDescriptors.h> #import <react/renderer/components/rnsvg/ComponentDescriptors.h>
#import "RCTFabricComponentsPlugins.h"
#import "RCTConversions.h"
#import <react/renderer/components/view/conversions.h> #import <react/renderer/components/view/conversions.h>
#import "RCTConversions.h"
#import "RCTFabricComponentsPlugins.h"
#import "RNSVGFabricConversions.h" #import "RNSVGFabricConversions.h"
#endif // RN_FABRIC_ENABLED #endif // RN_FABRIC_ENABLED

View File

@@ -11,9 +11,9 @@
#ifdef RN_FABRIC_ENABLED #ifdef RN_FABRIC_ENABLED
#import <react/renderer/components/rnsvg/ComponentDescriptors.h> #import <react/renderer/components/rnsvg/ComponentDescriptors.h>
#import "RCTFabricComponentsPlugins.h"
#import "RCTConversions.h"
#import <react/renderer/components/view/conversions.h> #import <react/renderer/components/view/conversions.h>
#import "RCTConversions.h"
#import "RCTFabricComponentsPlugins.h"
#import "RNSVGFabricConversions.h" #import "RNSVGFabricConversions.h"
#endif // RN_FABRIC_ENABLED #endif // RN_FABRIC_ENABLED

View File

@@ -2,8 +2,8 @@
#import "RNSVGUIKit.h" #import "RNSVGUIKit.h"
#import "RNSVGTextProperties.h"
#import "RNSVGPropHelper.h" #import "RNSVGPropHelper.h"
#import "RNSVGTextProperties.h"
@interface RNSVGFontData : NSObject { @interface RNSVGFontData : NSObject {
@public @public
@@ -26,11 +26,9 @@
+ (instancetype)Defaults; + (instancetype)Defaults;
+ (CGFloat)toAbsoluteWithNSString:(NSString *)string + (CGFloat)toAbsoluteWithNSString:(NSString *)string fontSize:(CGFloat)fontSize;
fontSize:(CGFloat)fontSize;
+ (instancetype)initWithNSDictionary:(NSDictionary *)font + (instancetype)initWithNSDictionary:(NSDictionary *)font parent:(RNSVGFontData *)parent;
parent:(RNSVGFontData *)parent;
@end @end

View File

@@ -1,7 +1,7 @@
#import "RNSVGFontData.h" #import "RNSVGFontData.h"
#import "RNSVGNode.h"
#import "RNSVGPropHelper.h" #import "RNSVGPropHelper.h"
#import "RNSVGTextProperties.h" #import "RNSVGTextProperties.h"
#import "RNSVGNode.h"
#define RNSVG_DEFAULT_KERNING 0.0 #define RNSVG_DEFAULT_KERNING 0.0
#define RNSVG_DEFAULT_WORD_SPACING 0.0 #define RNSVG_DEFAULT_WORD_SPACING 0.0
@@ -23,7 +23,8 @@ RNSVGFontData *RNSVGFontData_Defaults;
@implementation RNSVGFontData @implementation RNSVGFontData
+ (instancetype)Defaults { + (instancetype)Defaults
{
if (!RNSVGFontData_Defaults) { if (!RNSVGFontData_Defaults) {
RNSVGFontData *self = [RNSVGFontData alloc]; RNSVGFontData *self = [RNSVGFontData alloc];
self->fontData = nil; self->fontData = nil;
@@ -45,23 +46,24 @@ RNSVGFontData *RNSVGFontData_Defaults;
return RNSVGFontData_Defaults; return RNSVGFontData_Defaults;
} }
+ (CGFloat)toAbsoluteWithNSString:(NSString *)string + (CGFloat)toAbsoluteWithNSString:(NSString *)string fontSize:(CGFloat)fontSize
fontSize:(CGFloat)fontSize { {
return [RNSVGPropHelper fromRelativeWithNSString:string return [RNSVGPropHelper fromRelativeWithNSString:string relative:0 fontSize:fontSize];
relative:0
fontSize:fontSize];
} }
- (void)setInheritedWeight:(RNSVGFontData*) parent { - (void)setInheritedWeight:(RNSVGFontData *)parent
{
absoluteFontWeight = parent->absoluteFontWeight; absoluteFontWeight = parent->absoluteFontWeight;
fontWeight = parent->fontWeight; fontWeight = parent->fontWeight;
} }
RNSVGFontWeight nearestFontWeight(int absoluteFontWeight) { RNSVGFontWeight nearestFontWeight(int absoluteFontWeight)
{
return RNSVGFontWeights[(int)round(absoluteFontWeight / 100.0)]; return RNSVGFontWeights[(int)round(absoluteFontWeight / 100.0)];
} }
- (void)handleNumericWeight:(RNSVGFontData*)parent weight:(double)weight { - (void)handleNumericWeight:(RNSVGFontData *)parent weight:(double)weight
{
long roundWeight = round(weight); long roundWeight = round(weight);
if (roundWeight >= 1 && roundWeight <= 1000) { if (roundWeight >= 1 && roundWeight <= 1000) {
absoluteFontWeight = (int)roundWeight; absoluteFontWeight = (int)roundWeight;
@@ -72,7 +74,8 @@ RNSVGFontWeight nearestFontWeight(int absoluteFontWeight) {
} }
// https://drafts.csswg.org/css-fonts-4/#relative-weights // https://drafts.csswg.org/css-fonts-4/#relative-weights
int AbsoluteFontWeight(RNSVGFontWeight fontWeight, RNSVGFontData* parent) { int AbsoluteFontWeight(RNSVGFontWeight fontWeight, RNSVGFontData *parent)
{
if (fontWeight == RNSVGFontWeightBolder) { if (fontWeight == RNSVGFontWeightBolder) {
return bolder(parent->absoluteFontWeight); return bolder(parent->absoluteFontWeight);
} else if (fontWeight == RNSVGFontWeightLighter) { } else if (fontWeight == RNSVGFontWeightLighter) {
@@ -82,7 +85,8 @@ int AbsoluteFontWeight(RNSVGFontWeight fontWeight, RNSVGFontData* parent) {
} }
} }
int bolder(int inherited) { int bolder(int inherited)
{
if (inherited < 350) { if (inherited < 350) {
return 400; return 400;
} else if (inherited < 550) { } else if (inherited < 550) {
@@ -94,7 +98,8 @@ int bolder(int inherited) {
} }
} }
int lighter(int inherited) { int lighter(int inherited)
{
if (inherited < 100) { if (inherited < 100) {
return inherited; return inherited;
} else if (inherited < 550) { } else if (inherited < 550) {
@@ -106,8 +111,8 @@ int lighter(int inherited) {
} }
} }
+ (instancetype)initWithNSDictionary:(NSDictionary *)font + (instancetype)initWithNSDictionary:(NSDictionary *)font parent:(RNSVGFontData *)parent
parent:(RNSVGFontData *)parent { {
RNSVGFontData *data = [RNSVGFontData alloc]; RNSVGFontData *data = [RNSVGFontData alloc];
CGFloat parentFontSize = parent->fontSize; CGFloat parentFontSize = parent->fontSize;
if ([font objectForKey:FONT_SIZE]) { if ([font objectForKey:FONT_SIZE]) {
@@ -120,8 +125,7 @@ int lighter(int inherited) {
relative:parentFontSize relative:parentFontSize
fontSize:parentFontSize]; fontSize:parentFontSize];
} }
} } else {
else {
data->fontSize = parentFontSize; data->fontSize = parentFontSize;
} }
@@ -165,10 +169,7 @@ int lighter(int inherited) {
NSNumber *kern = kerning; NSNumber *kern = kerning;
data->kerning = (CGFloat)[kern doubleValue]; data->kerning = (CGFloat)[kern doubleValue];
} else { } else {
data->kerning = kerning ? data->kerning = kerning ? [RNSVGFontData toAbsoluteWithNSString:kerning fontSize:fontSize] : parent->kerning;
[RNSVGFontData toAbsoluteWithNSString:kerning
fontSize:fontSize]
: parent->kerning;
} }
id wordSpacing = [font objectForKey:WORD_SPACING]; id wordSpacing = [font objectForKey:WORD_SPACING];
@@ -176,10 +177,8 @@ int lighter(int inherited) {
NSNumber *ws = wordSpacing; NSNumber *ws = wordSpacing;
data->wordSpacing = (CGFloat)[ws doubleValue]; data->wordSpacing = (CGFloat)[ws doubleValue];
} else { } else {
data->wordSpacing = wordSpacing ? data->wordSpacing =
[RNSVGFontData toAbsoluteWithNSString:wordSpacing wordSpacing ? [RNSVGFontData toAbsoluteWithNSString:wordSpacing fontSize:fontSize] : parent->wordSpacing;
fontSize:fontSize]
: parent->wordSpacing;
} }
id letterSpacing = [font objectForKey:LETTER_SPACING]; id letterSpacing = [font objectForKey:LETTER_SPACING];
@@ -187,14 +186,11 @@ int lighter(int inherited) {
NSNumber *ls = letterSpacing; NSNumber *ls = letterSpacing;
data->wordSpacing = (CGFloat)[ls doubleValue]; data->wordSpacing = (CGFloat)[ls doubleValue];
} else { } else {
data->letterSpacing = letterSpacing ? data->letterSpacing =
[RNSVGFontData toAbsoluteWithNSString:letterSpacing letterSpacing ? [RNSVGFontData toAbsoluteWithNSString:letterSpacing fontSize:fontSize] : parent->letterSpacing;
fontSize:fontSize]
: parent->letterSpacing;
} }
return data; return data;
} }
@end @end

View File

@@ -1,5 +1,5 @@
#import <React/UIView+React.h>
#import <CoreText/CoreText.h> #import <CoreText/CoreText.h>
#import <React/UIView+React.h>
#import "RNSVGFontData.h" #import "RNSVGFontData.h"
@class RNSVGText; @class RNSVGText;
@@ -10,8 +10,7 @@
- (CTFontRef)getGlyphFont; - (CTFontRef)getGlyphFont;
- (instancetype)initWithWidth:(CGFloat)width - (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height;
height:(CGFloat)height;
- (RNSVGFontData *)getFont; - (RNSVGFontData *)getFont;
@@ -41,8 +40,7 @@
deltaY:(NSArray<RNSVGLength *> *)deltaY deltaY:(NSArray<RNSVGLength *> *)deltaY
rotate:(NSArray<RNSVGLength *> *)rotate; rotate:(NSArray<RNSVGLength *> *)rotate;
- (void)pushContext:(RNSVGGroup*)node - (void)pushContext:(RNSVGGroup *)node font:(NSDictionary *)font;
font:(NSDictionary *)font;
- (NSArray *)getFontContext; - (NSArray *)getFontContext;

View File

@@ -1,8 +1,8 @@
#import "RNSVGGlyphContext.h" #import "RNSVGGlyphContext.h"
#import <React/RCTFont.h> #import <React/RCTFont.h>
#import "RNSVGFontData.h"
#import "RNSVGNode.h" #import "RNSVGNode.h"
#import "RNSVGPropHelper.h" #import "RNSVGPropHelper.h"
#import "RNSVGFontData.h"
#import "RNSVGText.h" #import "RNSVGText.h"
// https://www.w3.org/TR/SVG/text.html#TSpanElement // https://www.w3.org/TR/SVG/text.html#TSpanElement
@@ -101,13 +101,13 @@
deltaY:(NSArray<RNSVGLength *> *)deltaY deltaY:(NSArray<RNSVGLength *> *)deltaY
rotate:(NSArray<RNSVGLength *> *)rotate; rotate:(NSArray<RNSVGLength *> *)rotate;
- (void)pushContext:(RNSVGGroup*)node - (void)pushContext:(RNSVGGroup *)node font:(NSDictionary *)font;
font:(NSDictionary *)font;
@end @end
@implementation RNSVGGlyphContext @implementation RNSVGGlyphContext
- (NSArray*)getFontContext { - (NSArray *)getFontContext
{
return mFontContext_; return mFontContext_;
} }
@@ -160,8 +160,7 @@
if (axisMinValue && CFGetTypeID(axisMinValue) == CFNumberGetTypeID()) { if (axisMinValue && CFGetTypeID(axisMinValue) == CFNumberGetTypeID()) {
CFNumberRef axisMinValueNumber = (CFNumberRef)axisMinValue; CFNumberRef axisMinValueNumber = (CFNumberRef)axisMinValue;
double axisMinValueDouble; double axisMinValueDouble;
if (CFNumberGetValue(axisMinValueNumber, kCFNumberDoubleType, &axisMinValueDouble)) if (CFNumberGetValue(axisMinValueNumber, kCFNumberDoubleType, &axisMinValueDouble)) {
{
weight = fmax(axisMinValueDouble, weight); weight = fmax(axisMinValueDouble, weight);
} }
} }
@@ -170,8 +169,7 @@
if (axisMaxValue && CFGetTypeID(axisMaxValue) == CFNumberGetTypeID()) { if (axisMaxValue && CFGetTypeID(axisMaxValue) == CFNumberGetTypeID()) {
CFNumberRef axisMaxValueNumber = (CFNumberRef)axisMaxValue; CFNumberRef axisMaxValueNumber = (CFNumberRef)axisMaxValue;
double axisMaxValueDouble; double axisMaxValueDouble;
if (CFNumberGetValue(axisMaxValueNumber, kCFNumberDoubleType, &axisMaxValueDouble)) if (CFNumberGetValue(axisMaxValueNumber, kCFNumberDoubleType, &axisMaxValueDouble)) {
{
weight = fmin(axisMaxValueDouble, weight); weight = fmin(axisMaxValueDouble, weight);
} }
} }
@@ -206,8 +204,8 @@
[self->mRsIndices_ addObject:[NSNumber numberWithLong:self->mRsIndex_]]; [self->mRsIndices_ addObject:[NSNumber numberWithLong:self->mRsIndex_]];
} }
- (instancetype)initWithWidth:(CGFloat)width - (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height
height:(CGFloat)height { {
self = [super init]; self = [super init];
self->mFontContext_ = [[NSMutableArray alloc] init]; self->mFontContext_ = [[NSMutableArray alloc] init];
self->mXsContext_ = [[NSMutableArray alloc] init]; self->mXsContext_ = [[NSMutableArray alloc] init];
@@ -263,7 +261,8 @@
return self; return self;
} }
- (RNSVGFontData *)getFont { - (RNSVGFontData *)getFont
{
return topFont_; return topFont_;
} }
@@ -293,15 +292,14 @@
[self->mFontContext_ addObject:parent]; [self->mFontContext_ addObject:parent];
return; return;
} }
RNSVGFontData *data = [RNSVGFontData initWithNSDictionary:font RNSVGFontData *data = [RNSVGFontData initWithNSDictionary:font parent:parent];
parent:parent];
self->mFontSize_ = data->fontSize; self->mFontSize_ = data->fontSize;
[self->mFontContext_ addObject:data]; [self->mFontContext_ addObject:data];
self->topFont_ = data; self->topFont_ = data;
} }
- (void)pushContext:(RNSVGGroup*)node - (void)pushContext:(RNSVGGroup *)node font:(NSDictionary *)font
font:(NSDictionary*)font { {
[self pushNode:node andFont:font]; [self pushNode:node andFont:font];
[self pushIndices]; [self pushIndices];
} }
@@ -312,7 +310,8 @@
y:(NSArray<RNSVGLength *> *)y y:(NSArray<RNSVGLength *> *)y
deltaX:(NSArray<RNSVGLength *> *)deltaX deltaX:(NSArray<RNSVGLength *> *)deltaX
deltaY:(NSArray<RNSVGLength *> *)deltaY deltaY:(NSArray<RNSVGLength *> *)deltaY
rotate:(NSArray<RNSVGLength*>*)rotate { rotate:(NSArray<RNSVGLength *> *)rotate
{
[self pushNode:(RNSVGGroup *)node andFont:font]; [self pushNode:(RNSVGGroup *)node andFont:font];
if (x != nil && [x count] != 0) { if (x != nil && [x count] != 0) {
mXsIndex_++; mXsIndex_++;
@@ -352,7 +351,8 @@
[self pushIndices]; [self pushIndices];
} }
- (void)popContext { - (void)popContext
{
[mFontContext_ removeLastObject]; [mFontContext_ removeLastObject];
[mXsIndices_ removeLastObject]; [mXsIndices_ removeLastObject];
[mYsIndices_ removeLastObject]; [mYsIndices_ removeLastObject];
@@ -442,68 +442,66 @@
* Except for any additional information provided in this specification, * Except for any additional information provided in this specification,
* the normative definition of the property is in CSS2 ([CSS2], section 15.2.4). * the normative definition of the property is in CSS2 ([CSS2], section 15.2.4).
*/ */
- (CGFloat)getFontSize { - (CGFloat)getFontSize
{
return mFontSize_; return mFontSize_;
} }
- (CGFloat)nextXWithDouble:(CGFloat)advance { - (CGFloat)nextXWithDouble:(CGFloat)advance
{
[RNSVGGlyphContext incrementIndices:mXIndices_ topIndex:mXsIndex_]; [RNSVGGlyphContext incrementIndices:mXIndices_ topIndex:mXsIndex_];
long nextIndex = mXIndex_ + 1; long nextIndex = mXIndex_ + 1;
if (nextIndex < [mXs_ count]) { if (nextIndex < [mXs_ count]) {
mDX_ = 0; mDX_ = 0;
mXIndex_ = nextIndex; mXIndex_ = nextIndex;
RNSVGLength *length = [mXs_ objectAtIndex:nextIndex]; RNSVGLength *length = [mXs_ objectAtIndex:nextIndex];
mX_ = [RNSVGPropHelper fromRelative:length mX_ = [RNSVGPropHelper fromRelative:length relative:mWidth_ fontSize:mFontSize_];
relative:mWidth_
fontSize:mFontSize_];
} }
mX_ += advance; mX_ += advance;
return mX_; return mX_;
} }
- (CGFloat)nextY { - (CGFloat)nextY
{
[RNSVGGlyphContext incrementIndices:mYIndices_ topIndex:mYsIndex_]; [RNSVGGlyphContext incrementIndices:mYIndices_ topIndex:mYsIndex_];
long nextIndex = mYIndex_ + 1; long nextIndex = mYIndex_ + 1;
if (nextIndex < [mYs_ count]) { if (nextIndex < [mYs_ count]) {
mDY_ = 0; mDY_ = 0;
mYIndex_ = nextIndex; mYIndex_ = nextIndex;
RNSVGLength *length = [mYs_ objectAtIndex:nextIndex]; RNSVGLength *length = [mYs_ objectAtIndex:nextIndex];
mY_ = [RNSVGPropHelper fromRelative:length mY_ = [RNSVGPropHelper fromRelative:length relative:mHeight_ fontSize:mFontSize_];
relative:mHeight_
fontSize:mFontSize_];
} }
return mY_; return mY_;
} }
- (CGFloat)nextDeltaX { - (CGFloat)nextDeltaX
{
[RNSVGGlyphContext incrementIndices:mDXIndices_ topIndex:mDXsIndex_]; [RNSVGGlyphContext incrementIndices:mDXIndices_ topIndex:mDXsIndex_];
long nextIndex = mDXIndex_ + 1; long nextIndex = mDXIndex_ + 1;
if (nextIndex < [mDXs_ count]) { if (nextIndex < [mDXs_ count]) {
mDXIndex_ = nextIndex; mDXIndex_ = nextIndex;
RNSVGLength *length = [mDXs_ objectAtIndex:nextIndex]; RNSVGLength *length = [mDXs_ objectAtIndex:nextIndex];
CGFloat val = [RNSVGPropHelper fromRelative:length CGFloat val = [RNSVGPropHelper fromRelative:length relative:mWidth_ fontSize:mFontSize_];
relative:mWidth_
fontSize:mFontSize_];
mDX_ += val; mDX_ += val;
} }
return mDX_; return mDX_;
} }
- (CGFloat)nextDeltaY { - (CGFloat)nextDeltaY
{
[RNSVGGlyphContext incrementIndices:mDYIndices_ topIndex:mDYsIndex_]; [RNSVGGlyphContext incrementIndices:mDYIndices_ topIndex:mDYsIndex_];
long nextIndex = mDYIndex_ + 1; long nextIndex = mDYIndex_ + 1;
if (nextIndex < [mDYs_ count]) { if (nextIndex < [mDYs_ count]) {
mDYIndex_ = nextIndex; mDYIndex_ = nextIndex;
RNSVGLength *length = [mDYs_ objectAtIndex:nextIndex]; RNSVGLength *length = [mDYs_ objectAtIndex:nextIndex];
CGFloat val = [RNSVGPropHelper fromRelative:length CGFloat val = [RNSVGPropHelper fromRelative:length relative:mHeight_ fontSize:mFontSize_];
relative:mHeight_
fontSize:mFontSize_];
mDY_ += val; mDY_ += val;
} }
return mDY_; return mDY_;
} }
- (CGFloat)nextRotation { - (CGFloat)nextRotation
{
[RNSVGGlyphContext incrementIndices:mRIndices_ topIndex:mRsIndex_]; [RNSVGGlyphContext incrementIndices:mRIndices_ topIndex:mRsIndex_];
long nextIndex = mRIndex_ + 1; long nextIndex = mRIndex_ + 1;
long count = [mRs_ count]; long count = [mRs_ count];
@@ -515,11 +513,13 @@
return [mRs_[mRIndex_] value]; return [mRs_[mRIndex_] value];
} }
- (CGFloat)getWidth { - (CGFloat)getWidth
{
return mWidth_; return mWidth_;
} }
- (CGFloat)getHeight { - (CGFloat)getHeight
{
return mHeight_; return mHeight_;
} }
@end @end

View File

@@ -7,16 +7,11 @@
@interface RNSVGPropHelper : NSObject @interface RNSVGPropHelper : NSObject
+ (CGFloat) fromRelativeWithNSString:(NSString *)length + (CGFloat)fromRelativeWithNSString:(NSString *)length relative:(CGFloat)relative fontSize:(CGFloat)fontSize;
relative:(CGFloat)relative
fontSize:(CGFloat)fontSize;
+ (CGFloat) fromRelative:(RNSVGLength*)length + (CGFloat)fromRelative:(RNSVGLength *)length relative:(CGFloat)relative fontSize:(CGFloat)fontSize;
relative:(CGFloat)relative
fontSize:(CGFloat)fontSize;
+ (CGFloat)fromRelative:(RNSVGLength*)length + (CGFloat)fromRelative:(RNSVGLength *)length relative:(CGFloat)relative;
relative:(CGFloat)relative;
@end @end
#endif #endif

View File

@@ -1,26 +1,22 @@
#include "RNSVGPropHelper.h" #include "RNSVGPropHelper.h"
@implementation RNSVGPropHelper @implementation RNSVGPropHelper
+ (CGFloat)fromRelativeWithNSString:(NSString *)length + (CGFloat)fromRelativeWithNSString:(NSString *)length relative:(CGFloat)relative fontSize:(CGFloat)fontSize
relative:(CGFloat)relative {
fontSize:(CGFloat)fontSize {
length = [length stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; length = [length stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSUInteger stringLength = [length length]; NSUInteger stringLength = [length length];
NSInteger percentIndex = stringLength - 1; NSInteger percentIndex = stringLength - 1;
if (stringLength == 0) { if (stringLength == 0) {
return 0; return 0;
} } else if ([length characterAtIndex:percentIndex] == '%') {
else if ([length characterAtIndex:percentIndex] == '%') {
return (CGFloat)[[length substringWithRange:NSMakeRange(0, percentIndex)] doubleValue] / 100 * relative; return (CGFloat)[[length substringWithRange:NSMakeRange(0, percentIndex)] doubleValue] / 100 * relative;
} } else {
else {
NSInteger twoLetterUnitIndex = stringLength - 2; NSInteger twoLetterUnitIndex = stringLength - 2;
if (twoLetterUnitIndex > 0) { if (twoLetterUnitIndex > 0) {
NSString *lastTwo = [length substringFromIndex:twoLetterUnitIndex]; NSString *lastTwo = [length substringFromIndex:twoLetterUnitIndex];
NSUInteger end = twoLetterUnitIndex; NSUInteger end = twoLetterUnitIndex;
CGFloat unit = 1; CGFloat unit = 1;
if ([lastTwo isEqualToString:@"px"]) { if ([lastTwo isEqualToString:@"px"]) {
} else if ([lastTwo isEqualToString:@"em"]) { } else if ([lastTwo isEqualToString:@"em"]) {
unit = fontSize; unit = fontSize;
} else if ([lastTwo isEqualToString:@"ex"]) { } else if ([lastTwo isEqualToString:@"ex"]) {
@@ -46,9 +42,8 @@
} }
} }
+ (CGFloat)fromRelative:(RNSVGLength*)length + (CGFloat)fromRelative:(RNSVGLength *)length relative:(CGFloat)relative fontSize:(CGFloat)fontSize
relative:(CGFloat)relative {
fontSize:(CGFloat)fontSize {
RNSVGLengthUnitType unitType = length.unit; RNSVGLengthUnitType unitType = length.unit;
CGFloat value = length.value; CGFloat value = length.value;
CGFloat unit = 1; CGFloat unit = 1;
@@ -91,8 +86,8 @@
return value * unit; return value * unit;
} }
+ (CGFloat)fromRelative:(RNSVGLength*)length + (CGFloat)fromRelative:(RNSVGLength *)length relative:(CGFloat)relative
relative:(CGFloat)relative { {
RNSVGLengthUnitType unitType = length.unit; RNSVGLengthUnitType unitType = length.unit;
CGFloat value = length.value; CGFloat value = length.value;
CGFloat unit = 1; CGFloat unit = 1;

View File

@@ -6,8 +6,8 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#import <Foundation/Foundation.h>
#import <CoreText/CoreText.h> #import <CoreText/CoreText.h>
#import <Foundation/Foundation.h>
#import "RNSVGUIKit.h" #import "RNSVGUIKit.h"

View File

@@ -6,27 +6,26 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#import "RNSVGTSpan.h" #import "RNSVGTSpan.h"
#import "RNSVGUIKit.h" #import "RNSVGFontData.h"
#import "RNSVGPathMeasure.h"
#import "RNSVGText.h" #import "RNSVGText.h"
#import "RNSVGTextPath.h" #import "RNSVGTextPath.h"
#import "RNSVGTextProperties.h" #import "RNSVGTextProperties.h"
#import "RNSVGTopAlignedLabel.h" #import "RNSVGTopAlignedLabel.h"
#import "RNSVGPathMeasure.h" #import "RNSVGUIKit.h"
#import "RNSVGFontData.h"
static NSCharacterSet *RNSVGTSpan_separators = nil; static NSCharacterSet *RNSVGTSpan_separators = nil;
static CGFloat RNSVGTSpan_radToDeg = 180 / (CGFloat)M_PI; static CGFloat RNSVGTSpan_radToDeg = 180 / (CGFloat)M_PI;
#ifdef RN_FABRIC_ENABLED #ifdef RN_FABRIC_ENABLED
#import <react/renderer/components/rnsvg/ComponentDescriptors.h> #import <react/renderer/components/rnsvg/ComponentDescriptors.h>
#import "RCTFabricComponentsPlugins.h"
#import "RCTConversions.h"
#import <react/renderer/components/view/conversions.h> #import <react/renderer/components/view/conversions.h>
#import "RCTConversions.h"
#import "RCTFabricComponentsPlugins.h"
#import "RNSVGFabricConversions.h" #import "RNSVGFabricConversions.h"
#endif // RN_FABRIC_ENABLED #endif // RN_FABRIC_ENABLED
@implementation RNSVGTSpan @implementation RNSVGTSpan {
{
CGFloat startOffset; CGFloat startOffset;
RNSVGTextPath *textPath; RNSVGTextPath *textPath;
NSMutableArray *emoji; NSMutableArray *emoji;
@@ -108,7 +107,6 @@ using namespace facebook::react;
emojiTransform = [NSMutableArray arrayWithCapacity:0]; emojiTransform = [NSMutableArray arrayWithCapacity:0];
measure = [[RNSVGPathMeasure alloc] init]; measure = [[RNSVGPathMeasure alloc] init];
RNSVGTSpan_separators = [NSCharacterSet whitespaceCharacterSet]; RNSVGTSpan_separators = [NSCharacterSet whitespaceCharacterSet];
} }
#endif // RN_FABRIC_ENABLED #endif // RN_FABRIC_ENABLED
@@ -190,7 +188,8 @@ using namespace facebook::react;
} }
} }
- (NSMutableDictionary *)getAttributes:(RNSVGFontData *)fontdata { - (NSMutableDictionary *)getAttributes:(RNSVGFontData *)fontdata
{
NSMutableDictionary *attrs = [[NSMutableDictionary alloc] init]; NSMutableDictionary *attrs = [[NSMutableDictionary alloc] init];
if (fontRef != nil) { if (fontRef != nil) {
@@ -206,11 +205,9 @@ using namespace facebook::react;
float kern = (float)(letterSpacing + kerning); float kern = (float)(letterSpacing + kerning);
NSNumber *kernAttr = [NSNumber numberWithFloat:kern]; NSNumber *kernAttr = [NSNumber numberWithFloat:kern];
#if DTCORETEXT_SUPPORT_NS_ATTRIBUTES #if DTCORETEXT_SUPPORT_NS_ATTRIBUTES
if (___useiOS6Attributes) if (___useiOS6Attributes) {
{
[attrs setObject:kernAttr forKey:NSKernAttributeName]; [attrs setObject:kernAttr forKey:NSKernAttributeName];
} } else
else
#endif // DTCORETEXT_SUPPORT_NS_ATTRIBUTES #endif // DTCORETEXT_SUPPORT_NS_ATTRIBUTES
{ {
[attrs setObject:kernAttr forKey:(id)kCTKernAttributeName]; [attrs setObject:kernAttr forKey:(id)kCTKernAttributeName];
@@ -220,7 +217,8 @@ using namespace facebook::react;
} }
RNSVGTopAlignedLabel *label; RNSVGTopAlignedLabel *label;
- (void)drawWrappedText:(CGContextRef)context gc:(RNSVGGlyphContext *)gc rect:(CGRect)rect color:(CGColorRef)color { - (void)drawWrappedText:(CGContextRef)context gc:(RNSVGGlyphContext *)gc rect:(CGRect)rect color:(CGColorRef)color
{
[self pushGlyphContext]; [self pushGlyphContext];
if (fontRef != nil) { if (fontRef != nil) {
CFRelease(fontRef); CFRelease(fontRef);
@@ -269,12 +267,9 @@ RNSVGTopAlignedLabel *label;
CGFloat fontSize = [gc getFontSize]; CGFloat fontSize = [gc getFontSize];
CGFloat height = CGRectGetHeight(rect); CGFloat height = CGRectGetHeight(rect);
CGFloat width = [RNSVGPropHelper fromRelative:self.inlineSize CGFloat width = [RNSVGPropHelper fromRelative:self.inlineSize relative:[gc getWidth] fontSize:fontSize];
relative:[gc getWidth]
fontSize:fontSize];
CGRect constrain = CGRectMake(0, 0, width, height); CGRect constrain = CGRectMake(0, 0, width, height);
CGRect s = [self.content CGRect s = [self.content boundingRectWithSize:constrain.size
boundingRectWithSize:constrain.size
options:NSStringDrawingUsesLineFragmentOrigin options:NSStringDrawingUsesLineFragmentOrigin
attributes:attrs attributes:attrs
context:nil]; context:nil];
@@ -518,11 +513,9 @@ RNSVGTopAlignedLabel *label;
NSNumber *noAutoKern = [NSNumber numberWithFloat:0.0f]; NSNumber *noAutoKern = [NSNumber numberWithFloat:0.0f];
#if DTCORETEXT_SUPPORT_NS_ATTRIBUTES #if DTCORETEXT_SUPPORT_NS_ATTRIBUTES
if (___useiOS6Attributes) if (___useiOS6Attributes) {
{
[attrs setObject:noAutoKern forKey:NSKernAttributeName]; [attrs setObject:noAutoKern forKey:NSKernAttributeName];
} } else
else
#endif // DTCORETEXT_SUPPORT_NS_ATTRIBUTES #endif // DTCORETEXT_SUPPORT_NS_ATTRIBUTES
{ {
[attrs setObject:noAutoKern forKey:(id)kCTKernAttributeName]; [attrs setObject:noAutoKern forKey:(id)kCTKernAttributeName];
@@ -726,12 +719,9 @@ RNSVGTopAlignedLabel *label;
RNSVGLength *mTextLength = [self textLength]; RNSVGLength *mTextLength = [self textLength];
enum RNSVGTextLengthAdjust mLengthAdjust = RNSVGTextLengthAdjustFromString([self lengthAdjust]); enum RNSVGTextLengthAdjust mLengthAdjust = RNSVGTextLengthAdjustFromString([self lengthAdjust]);
if (mTextLength != nil) { if (mTextLength != nil) {
CGFloat author = [RNSVGPropHelper fromRelative:mTextLength CGFloat author = [RNSVGPropHelper fromRelative:mTextLength relative:[gc getWidth] fontSize:fontSize];
relative:[gc getWidth]
fontSize:fontSize];
if (author < 0) { if (author < 0) {
NSException *e = [NSException NSException *e = [NSException exceptionWithName:@"NegativeTextLength"
exceptionWithName:@"NegativeTextLength"
reason:@"Negative textLength value" reason:@"Negative textLength value"
userInfo:nil]; userInfo:nil];
@throw e; @throw e;
@@ -829,8 +819,8 @@ RNSVGTopAlignedLabel *label;
break; break;
case RNSVGAlignmentBaselineMiddle: case RNSVGAlignmentBaselineMiddle:
// Align the vertical midpoint of the box with the baseline of the parent box plus half the x-height of the parent. TODO // Align the vertical midpoint of the box with the baseline of the parent box plus half the x-height of the
// middle = x height / 2 // parent. TODO middle = x height / 2
baselineShift = xHeight / 2; baselineShift = xHeight / 2;
break; break;
@@ -1055,7 +1045,8 @@ RNSVGTopAlignedLabel *label;
transform = CGAffineTransformConcat(CGAffineTransformMakeTranslation(px, py), transform); transform = CGAffineTransformConcat(CGAffineTransformMakeTranslation(px, py), transform);
transform = CGAffineTransformConcat(CGAffineTransformMakeRotation(angle + r), transform); transform = CGAffineTransformConcat(CGAffineTransformMakeRotation(angle + r), transform);
transform = CGAffineTransformScale(transform, scaledDirection, side); transform = CGAffineTransformScale(transform, scaledDirection, side);
transform = CGAffineTransformConcat(CGAffineTransformMakeTranslation(-halfWay, y + dy + baselineShift), transform); transform =
CGAffineTransformConcat(CGAffineTransformMakeTranslation(-halfWay, y + dy + baselineShift), transform);
} else { } else {
transform = CGAffineTransformMakeTranslation(startPoint, y + dy + baselineShift); transform = CGAffineTransformMakeTranslation(startPoint, y + dy + baselineShift);
transform = CGAffineTransformConcat(CGAffineTransformMakeRotation(r), transform); transform = CGAffineTransformConcat(CGAffineTransformMakeRotation(r), transform);
@@ -1079,8 +1070,7 @@ RNSVGTopAlignedLabel *label;
label.backgroundColor = RNSVGColor.clearColor; label.backgroundColor = RNSVGColor.clearColor;
UIFont *customFont = [UIFont systemFontOfSize:fontSize]; UIFont *customFont = [UIFont systemFontOfSize:fontSize];
CGSize measuredSize = [currChars sizeWithAttributes: CGSize measuredSize = [currChars sizeWithAttributes:@{NSFontAttributeName : customFont}];
@{NSFontAttributeName:customFont}];
label.font = customFont; label.font = customFont;
CGFloat width = ceil(measuredSize.width); CGFloat width = ceil(measuredSize.width);
CGFloat height = ceil(measuredSize.height); CGFloat height = ceil(measuredSize.height);

View File

@@ -7,22 +7,21 @@
*/ */
#import "RNSVGText.h" #import "RNSVGText.h"
#import "RNSVGTextPath.h"
#import <React/RCTFont.h>
#import <CoreText/CoreText.h> #import <CoreText/CoreText.h>
#import <React/RCTFont.h>
#import "RNSVGGlyphContext.h" #import "RNSVGGlyphContext.h"
#import "RNSVGTextPath.h"
#import "RNSVGTextProperties.h" #import "RNSVGTextProperties.h"
#ifdef RN_FABRIC_ENABLED #ifdef RN_FABRIC_ENABLED
#import <react/renderer/components/rnsvg/ComponentDescriptors.h> #import <react/renderer/components/rnsvg/ComponentDescriptors.h>
#import "RCTFabricComponentsPlugins.h"
#import "RCTConversions.h"
#import <react/renderer/components/view/conversions.h> #import <react/renderer/components/view/conversions.h>
#import "RCTConversions.h"
#import "RCTFabricComponentsPlugins.h"
#import "RNSVGFabricConversions.h" #import "RNSVGFabricConversions.h"
#endif // RN_FABRIC_ENABLED #endif // RN_FABRIC_ENABLED
@implementation RNSVGText @implementation RNSVGText {
{
RNSVGGlyphContext *_glyphContext; RNSVGGlyphContext *_glyphContext;
NSString *_alignmentBaseline; NSString *_alignmentBaseline;
NSString *_baselineShift; NSString *_baselineShift;
@@ -219,8 +218,7 @@ using namespace facebook::react;
{ {
CGRect bounds = CGContextGetClipBoundingBox(context); CGRect bounds = CGContextGetClipBoundingBox(context);
CGSize size = bounds.size; CGSize size = bounds.size;
_glyphContext = [[RNSVGGlyphContext alloc] initWithWidth:size.width _glyphContext = [[RNSVGGlyphContext alloc] initWithWidth:size.width height:size.height];
height:size.height];
} }
- (CGPathRef)getGroupPath:(CGContextRef)context - (CGPathRef)getGroupPath:(CGContextRef)context
@@ -352,8 +350,7 @@ using namespace facebook::react;
RNSVGPlatformView *parent = [self superview]; RNSVGPlatformView *parent = [self superview];
for (NSInteger i = [font count] - 1; i >= 0; i--) { for (NSInteger i = [font count] - 1; i >= 0; i--) {
RNSVGFontData *fontData = [font objectAtIndex:i]; RNSVGFontData *fontData = [font objectAtIndex:i];
if (![parent isKindOfClass:[RNSVGText class]] || if (![parent isKindOfClass:[RNSVGText class]] || fontData->textAnchor == RNSVGTextAnchorStart ||
fontData->textAnchor == RNSVGTextAnchorStart ||
node.positionX != nil) { node.positionX != nil) {
return node; return node;
} }

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