649 Commits

Author SHA1 Message Date
Jakub Grzywacz
de8a7632f6 fix: properly handle touch events outside the Svg (#2611)
# Summary

Fixes #2585 

Improve the `onPress` events by ignoring touches outside the `Svg` view.
This is implemented as follows:
* on Android by clipping the Android's element dimensions to (0, 0,
canvas width, canvas height)
* on Apple by improving `hitTest` to exclude touches outside the bounds
of (0, 0, bounds width, bounds height)


https://github.com/user-attachments/assets/59417493-d849-47df-84e8-d5b0a6045b00
2025-01-15 11:49:55 +01:00
Ignacy Łątka
3bf4298ae0 feat: make svgView getter public (#2583)
<!-- Thanks for submitting a pull request! We appreciate you spending
the time to work on these changes. Please follow the template so that
the reviewers can easily understand what the code changes affect -->

# Summary

This PR reverts #2555, as `RenderableView.hitTest()` can be replaced by
`SvgView.reactTagForTouch()`, which is already `public`.

This PR also changes the `package-private` `getSvgView()` method of
`VirtualView` to `public`.
This change has been made to handle hit detection of transformed
`VirtualView`s, as `RenderableView`'s `hitTest()` doesn't take
transformations into account, while `SvgView`'s `reactTagForTouch()`
does.

Making `getSvgView()` public is necessary for integrating RNSVG support
into RNGH. More details
[here](https://github.com/software-mansion/react-native-gesture-handler/pull/3242/).

## Test Plan

Run the example from the RNGH - RNSVG [integration
PR](https://github.com/software-mansion/react-native-gesture-handler/pull/3242/).

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| Android |          |
2025-01-15 11:27:35 +01:00
Jakub Grzywacz
73bdb03f4c fix: CMake flags (#2603)
# Summary

Fix typo in CMakeLists.txt flags and use `ReactAndroid_VERSION_MINOR`
instead of `REACT_NATIVE_MINOR_VERSION`

## Test Plan

Example apps should build without warnings/errors on 0.73+ as well as on
0.77.0-rc.6
2025-01-08 10:30:37 +01:00
Jakub Grzywacz
1e1f140b15 chore: update generated specs for the old architecture to work on 0.77 (#2586)
# Summary

Similarly to
https://github.com/software-mansion/react-native-gesture-handler/pull/3301
we need to regenerate specs

## Test Plan

CI should be green
2025-01-07 15:09:41 +01:00
Jakub Grzywacz
6377be5f20 fix: remove package from AndroidManifest.xml (#2600)
# Summary

Fixes #2599 

Starting with `v15.8.0`, we support `react-native@0.73+`, which
eliminates the need to worry about AGP versions below 7. Consequently,
the `package` attribute in `AndroidManifest.xml` can be safely removed,
along with the corresponding check in `build.gradle`.

## Test Plan

Build the app on all supported versions

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| Android |          |
2025-01-07 14:43:58 +01:00
Jakub Grzywacz
6042b89b6b feat: use yoga::StyleLength instead of yoga::value on 77+ (#2582)
# Summary

With react-native@0.77 `yoga::value` is no longer available and we
should use `yoga::StyleLength`.

## Test Plan

App should build again on 0.77.rc-3
2024-12-19 14:34:55 +01:00
Jakub Grzywacz
d3d61a5fc1 feat: custom shadow nodes (#2568)
# Summary

Implement custom shadow nodes for nearly all `Svg` components. While
it's a foundation for numerous upcoming changes, it currently addresses
and resolves #2544.

## Test Plan

There shouldn't be any noticeable changes, and everything should
function as before, except that `onLayout` will now be triggered only
once and with the correct dimensions.

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |          |
| MacOS   |          |
| Android |          |

---------

Co-authored-by: Jakub Piasecki <jakubpiasecki67@gmail.com>
2024-12-12 11:48:46 +01:00
Abed El Rahman Al Tawil
d1e91144a7 refactor: use old style switch statement in FeCompositeView.java (#2562)
Use old-style switch statement in `FeCompositeView.java`.
2024-12-06 16:34:49 +01:00
Ignacy Łątka
01db444f51 feat: make RenderableView.hitTest public to create a cross-library interface (#2555)
<!-- Thanks for submitting a pull request! We appreciate you spending
the time to work on these changes. Please follow the template so that
the reviewers can easily understand what the code changes affect -->

# Summary

Adding an `RNGH <-> RNSVG` interface requires usage of
`RenderableView.hitTest` to work.
([link](https://github.com/software-mansion/react-native-gesture-handler/pull/3242))
Currently, `RenderableView.hitTest` is `package-private`, meaning it
cannot be accessed by other packages.
This change does not change any functionality of the library, it only
exposes existing functions to other libraries.

I only made public those `hitTest` implementation which are strictly
necessary for this interface, this is why multiple, if not most
`hitTest` implementations remain `package-private` despite the changes
made in the PR.

## Test Plan

- open the example app, see how the app builds successfully

### What's required for testing (prerequisites)?

- `RNSVG`'s `paper-example` app

### What are the steps to reproduce (after prerequisites)?

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |          |
| MacOS   |          |
| Android |          |
| Web     |          |

## Checklist

<!-- Check completed item, when applicable, via: [X] -->

- [X] I have tested this on a device and a simulator
- [ ] I added documentation in `README.md`
- [ ] ~~I updated the typed files (typescript)~~
- [ ] I added a test for the API in the `__tests__` folder
2024-11-28 17:05:43 +01:00
Jakub Grzywacz
2dcc8324b6 refactor: replace deprecated processTransform (#2554)
# Summary

Replace deprecated `TransformHelper.processTransform` with a new
function that also gets `transformOrigin`.

## Test Plan

Transforms should function properly, and this error should not occur
during the build process:
```
> Task :react-native-svg:compileDebugJavaWithJavac
/react-native-svg/apps/paper-example/node_modules/react-native-svg/android/src/main/java/com/horcrux/svg/RenderableViewManager.java:390: warning: [removal] processTransform(ReadableArray,double[]) in TransformHelper has been deprecated and marked for removal
    TransformHelper.processTransform(transforms, sTransformDecompositionArray);
                   ^
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 warning
```

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| Android |          |
2024-11-28 15:29:45 +01:00
Jakub Grzywacz
c617dec1c5 fix: animated transform last frame (#2553)
# Summary

When using the Animated API for animations, it sends the last frame as
JavaScript-parsed (matrix) updates in addition to native (transform)
updates. ~~As a result, we need to ignore one of them.~~ I believe
there's no need to differentiate between native and JavaScript
updates—we can simply save both to the same value (mMatrix). By doing
so, we can avoid duplicating the transforms.

| Before | After |
|--------|--------|
| <video
src="https://github.com/user-attachments/assets/868cc778-4b88-4473-85b5-9665b4b241aa">
| <video
src="https://github.com/user-attachments/assets/c6d17b7b-7c9a-47c3-8286-2d9b5720f261">
|




## Test Plan

```jsx
import React, {useEffect} from 'react';
import {Animated, useAnimatedValue, View} from 'react-native';
import {Rect, Svg} from 'react-native-svg';

const AnimatedRect = Animated.createAnimatedComponent(Rect);
function AnimatedJumpIssue() {
  const animatedValue = useAnimatedValue(100);
  return (
    <>
      <View style={{borderColor: 'black', borderWidth: 1}}>
        <Svg height="100" width="400">
          <AnimatedRect
            x="0"
            y="0"
            width="100"
            height="100"
            fill="black"
            transform={[{translateX: animatedValue}]}
          />
        </Svg>
      </View>
      <Button
        title="Press me"
        onPress={() => {
          Animated.timing(animatedValue, {
            toValue: 200,
            duration: 3000,
            useNativeDriver: true,
          }).start();
        }}
      />
    </>
  );
}
```

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| Android |          |
| iOS |          |
| macOS |          |
2024-11-28 12:44:55 +01:00
Jakub Grzywacz
74b77a672e fix: react-native@0.73 sourceSet to maintain support (#2543)
# Summary

#2541 is not compatible with `react-native@0.73`. This PR introduces
sourceSet to maintain support for that version.

## Test Plan

Build app with `react-native@0.73.x`

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| Android |          |
2024-11-19 13:54:39 +01:00
Pieter De Baets
81e4692885 feat: update SvgPackage to supported stable API's (#2541)
Address some deprecated API's in SVGPackage

# Summary

This improves compatibility with future React Native releases, which
will remove TurboReactPackage and the ReactModuleInfo constructor used.

## Test Plan

CI
2024-11-19 10:02:49 +01:00
Jakub Grzywacz
0c30339c55 refactor: use old style switch statement (#2538)
# Summary

Use old-style switch statement.
Closes #2537
2024-11-18 10:43:17 +01:00
Jakub Grzywacz
2a58016ec1 feat: get currentColor from caller instead of parent (#2521)
# Summary

Fixes #2520
When an element uses `currentColor`, it should look for color in its
caller, not in its parent.
Example: 
```svg
<Svg width="100" height="100" viewBox="0 0 100 100" color="red">
  <Defs color="blue">
    <G color="green">
      <Rect id="a" x="0" y="0" width="50" height="50" fill="currentColor"/>
    </G>
  </Defs>
  <G color="pink">
    <Use href="#a"/>												<!-- #1 -->
  </G>
  <Use href="#a" transform="translate(25 25)"/>						<!-- #2 -->
  <G color="green">
    <Use href="#a" transform="translate(50 50)"/>					<!-- #3 -->
  </G>
</Svg>
```

* `#1` should be **pink**
* `#2` should be **red**
* `#3` should be **green**


![image](https://github.com/user-attachments/assets/b7ba2ec6-ea05-4bcb-9f40-0cf024e5c749)

## Test Plan

Example app -> test -> Test2520

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |          |
| MacOS   |          |
| Android |          |
2024-10-31 16:00:36 +01:00
Jakub Grzywacz
fd9397c1f9 fix: FeComposite in2 on Android (#2516)
# Summary

While working on
https://github.com/software-mansion/react-native-svg/pull/2514 I've
noticed a bug in `FeComposite` on Android that `in2` was ignored

## Test Plan

Run Example app -> filters -> FeComposite on Android

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| Android |          |
2024-10-28 15:01:19 +01:00
Jakub Grzywacz
eb4889c000 fix: negative dx/dy in feOffset (#2515)
# Summary

While working on #2514 I've noticed that negative dx/dy were treated as
positive.

## Test Plan

Add FeOffset filter with negative dx/dy to an element. It should move
closer to upper left corner.

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| Android |          |
2024-10-28 14:55:22 +01:00
Jakub Grzywacz
36ca5c4584 fix: client rect on use element (#2513)
# Summary

Use elements had incorrect `clientRect` based on templates' rect, which
was incorrect. With this change, it ensures client rect is based on path
transformed by CTM.

## Test Plan

Example app -> Filters -> FeComposite

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| Android |          |
2024-10-28 13:45:52 +01:00
Jakub Grzywacz
4637dee1e4 feat: FeComposite filter (#2433)
# Summary

<img width="324" alt="image"
src="https://github.com/user-attachments/assets/0a9b4a56-d093-49f7-aacd-c198ee00f256">

## Test Plan

Examples app -> Filters -> FeComposite

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |          |
| macOS   |    *      |
| Android |          |
| Web     |          |

_*_ macOS isn't working as:
* `CGBitmapContextCreateImage` always returns null
* FeFlood isn't aligned properly (will be fixed in the following PR)
2024-10-25 11:18:07 +02:00
Jakub Grzywacz
16baf27a50 fix: crop rect invalid bounds crash (#2494)
# Summary

Do not crash on `getCropRect` call when renderableBounds is null

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| Android |          |
2024-10-17 11:34:37 +02:00
Jakub Grzywacz
93df20ca3f remove: deprecated sourceSets (#2493)
# Summary

Remove deprecated sourceSet and drop support for `react-native@0.72` to
simplify codebase.
2024-10-17 11:11:24 +02:00
Jakub Grzywacz
096fdc22a5 feat: FeBlend (#2489)
# Summary

Continuation of #2362 implementing `FeBlend` filter
https://www.w3.org/TR/SVG11/filters.html#feBlendElement

## Test Plan

Example app → Filters → `FeBlend`

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |          |
| macOS   |     _*_      |
| Android |          |
| Web     |          |
2024-10-16 11:45:44 +02:00
Jakub Grzywacz
cb30bd66d5 fix: filter subregion depend on primitive units not filter units (#2490)
# Summary

This fix addresses a minor bug/typo that was recently introduced, where
the filter subregion was incorrectly relying on filterUnits instead of
primitiveUnits.
2024-10-16 11:36:13 +02:00
Jakub Grzywacz
ba54b15799 feat: FeFlood (#2487)
# Summary

Continuation of #2362 implementing `FeFlood` filter
https://www.w3.org/TR/SVG11/filters.html#feFloodElement

## Test Plan

Example app → Filters → `FeFlood`

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |          |
| macOS   |     _*_      |
| Android |          |
| Web     |          |

_* `canvasWidth/canvasHeight` is incorrect on macOS, so there might be
some problems_
2024-10-15 09:35:13 +02:00
Jakub Grzywacz
8fed77476b feat: properly implement filter region unit USER_SPACE_ON_USE (#2486)
# Summary

After deep dive into the specification, I found out that the default
filter subregion is not equal to `0% 0% 100% 100%`, rather the size of
the parent filter region.

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |          |
| MacOS   |          |
| Android |          |
2024-10-14 15:35:16 +02:00
Jakub Grzywacz
3aae632d1f feat: implement filter region lengths directly on RNSVGFilterRegion (#2485)
# Summary

[apple] Use filter region directly instead of creating new one on every
rerender.
[android] rename some variables and add temporary fix for null lengths
2024-10-14 14:47:44 +02:00
Jakub Grzywacz
690cddd2f7 feat: improve animating colors (#2471)
# Summary

Currently on Fabric, you cannot animate color properties like `fill` or
`stroke` using Animated with `useNativeDriver: true` or Reanimated.
That's because we have custom structure that needs to be parsed on `JS`
and looks like:

```ts
type ColorStruct = Readonly<{
  type?: WithDefault<Int32, -1>;
  payload?: ColorValue;
  brushRef?: string;
}>;
```

However, special values like `currentColor` / `context-fill` /
`context-stroke` / `/^url\(#(.+)\)$/` can not be animated anyway.
Instead, we should allow passing `ColorValue` directly and detect on the
native side if its ColorValue or ColorStruct.

## Test Plan

Example app -> TestX

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |          |
| MacOS   |          |
| Android |          |

## Checklist

- [x] I have tested this on a device and a simulator
- [ ] I added documentation in `README.md`
2024-10-04 14:20:54 +02:00
Jakub Grzywacz
9d9958264b feat: properly implement currentColor (#2466)
# Summary

Motivated by issue #2455, I decided to implement the `currentColor`
property in line with the specs
(https://www.w3.org/TR/SVG11/color.html#ColorProperty). This involves
adding the `color` property to all renderable nodes.

## Test Plan

Example app -> `Test2455`

<img width="344" alt="image"
src="https://github.com/user-attachments/assets/ccaf5a79-4097-49f8-8948-0158d9d9274c">

```svg
<Svg color="red" width="60" height="60" viewBox="0 0 24 24" fill="none">
  <Path d="M22.7927 11.1242C21.359 18.5187 12.0003 22.7782 12.0003 22.7782C12.0003 22.7782 2.64153 18.5187 1.20661 11.1242C0.326598 6.58719 2.24925 2.02329 7.13701 2.00007C10.7781 1.98296 12.0003 5.65211 12.0003 5.65211C12.0003 5.65211 13.2226 1.98173 16.8624 2.00007C21.7612 2.02329 23.6727 6.58841 22.7927 11.1242Z" fill="currentColor"/>
  <G color="green" fill="purple">
    <G>
      <Rect x="16" y="16" width="8" height="8" fill="currentColor"/>
      <G color="pink">
        <Rect x="0" y="16" width="8" height="8" color="gold" fill="currentColor"/>
        <Circle cx="12" cy="20" r="4" fill="currentColor"/>
      </G>
    </G>
  </G>
</Svg>
```
## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |          |
| MacOS   |          |
| Android |          |
2024-09-30 15:50:37 +02:00
Jakub Grzywacz
cd47aece7e style: format and rename variables (#2469)
# Summary

Formatting and rename variable committed in #2415
2024-09-30 14:25:04 +02:00
Jakub Grzywacz
cc961774e7 fix: do not crash when borderRadius is set on Android (#2415)
# Summary

Fixes #2462
Currently, on Android, when `borderRadius` style is applied to a `Svg`
component an error occurs, stating `Cannot cast Double to Float`

This PR updates the codegen types, changing them from Double to Dynamic,
aligning with the implementation with the ViewProps.

## Test

### Tested on

- [x] react-native@0.76.0-rc.1
- [x] react-native@0.75.1
- [x] react-native@0.74.2
- [x] react-native@0.73.9

### Test case
```jsx
<Svg
  width="60"
  height="60"
  viewBox="0 0 24 24"
  style={{
    borderRadius: 16.2,
    borderTopLeftRadius: 16.2,
    borderBottomRightRadius: 16.2,
    borderStartStartRadius: 16.2,
    borderStartEndRadius: 16.2,
    borderTopRightRadius: 16.2,
    borderBottomLeftRadius: 16.2,
    borderTopStartRadius: 16.2,
    borderTopEndRadius: 16.2,
    borderBottomStartRadius: 16.2,
    borderBottomEndRadius: 16.2,
    borderEndEndRadius: 16.2,
    borderEndStartRadius: 16.2,
  }}>
  <Rect x="0" y="0" width="24" height="24" fill="red" />
</Svg>
```

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| Android |          |
2024-09-30 13:02:40 +02:00
Jakub Grzywacz
712201a19e feat: implement maskUnits (#2457)
# Summary

Without the `maskUnits` attribute, masks may not render correctly, as
seen in issue #2449. This pull request adds support for `maskUnits` and
ensures proper cropping within the mask boundaries.

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |          |
| MacOS   |          |
| Android |          |
2024-09-23 14:03:15 +02:00
Jakub Grzywacz
9df974194f refactor: use node resolver to locate React Native package (#2461)
# Summary

Twin pull request to
https://github.com/software-mansion/react-native-reanimated/pull/6482
2024-09-19 12:18:59 +02:00
Jakub Grzywacz
9049089954 fix: masked element layer opacity when previous item has stroke opacity (#2456)
# Summary

On Android when element before masked element has strokeOpacity
different from 1, the paint is reused to draw an offscreen layer
resulting in wrong opacity. Partially fixes (only on Android) #2449

## Test Plan

Add `stroke` and `strokeOpacity` to element directly before masked
element.

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| Android |          |
2024-09-18 13:13:59 +02:00
Jakub Grzywacz
b65b3c2679 feat: support react-native@0.76 (#2445)
# Summary

This PR adds support for React Native 0.76 (currently: 0.76.0-rc.0).
2024-09-17 11:02:48 +02:00
Jakub Grzywacz
2b081e5878 fix: transform scale on android (#2452)
# Summary

Undo these changes
https://github.com/software-mansion/react-native-svg/pull/2403/files#diff-7f8adeb6e7faded1a7ef711b4fa9d2b12d29ff386217e838c4551866afdd8bef
that introduced a bug described here
https://github.com/software-mansion/react-native-svg/issues/2442#issuecomment-2354170651
2024-09-17 09:56:27 +02:00
Jakub Grzywacz
51a4e0289a fix: render G offscreen only when it's needed (opacity != 1) (#2450)
# Summary

Improve #2417 by applying offscreen canvas only when opacity attribute
is set

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| Android |          |
2024-09-16 15:21:02 +02:00
Jakub Grzywacz
d05f69e3d7 fix: Android group opacity prop (#2417)
# Summary

Currently, on Android, when the `opacity` prop is applied to `G` or
`Svg` elements, it is rendered incorrectly. Instead of rendering the
children "offscreen" and then applying the opacity to the entire result,
the child elements themselves are rendered with the specified opacity.

Fixes #2046

## Example

```tsx
import {View} from 'react-native';
import {G, Rect, Svg} from 'react-native-svg';

export default function App() {
  return (
    <View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
      <Svg width="150" height="150" viewBox="0 0 150 150">
        <G opacity="0.5">
          <Rect width="100" height="100" fill="red" />
          <Rect x="50" y="50" width="100" height="100" fill="green" />
        </G>
      </Svg>

      <Svg width="150" height="150" viewBox="0 0 150 150" opacity="0.5">
        <Rect width="100" height="100" fill="red" />
        <Rect x="50" y="50" width="100" height="100" fill="green" />
      </Svg>
    </View>
  );
}
```

| Before | After | Web reference | 
| --- | --- | --- |
| <img width="200" alt="Zrzut ekranu 2024-08-20 o 15 44 13"
src="https://github.com/user-attachments/assets/68c57f7d-0375-4703-8c3c-a358fe124daa">
| <img width="200" alt="Zrzut ekranu 2024-08-20 o 15 44 26"
src="https://github.com/user-attachments/assets/ae7e24b9-edae-4b44-8785-3fc95a39fdd4">
| <img width="190" alt="image"
src="https://github.com/user-attachments/assets/1aa0491f-2936-4845-b18c-1fa669c34118">
|


## Test Plan

Example above is available in `test-examples` app as `Test2417`

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| Android |         |
2024-09-12 13:42:55 +02:00
Jakub Grzywacz
85be1d0bac feat: implement filter region (#2441)
# Summary

Implement proper handling for filter region according to the specs:
*
[FilterEffectsRegion](https://www.w3.org/TR/SVG11/filters.html#FilterEffectsRegion)
*
[FilterPrimitiveSubRegion](https://www.w3.org/TR/SVG11/filters.html#FilterPrimitiveSubRegion)

enabling user to specify 
* `filterUnits`
* `primitiveUnits`
* `x`
* `y`
* `width`
* `height`

on `Filter` element and the last four on filter primitives.

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |          |
| MacOS   |         |
| Android |          |
| Web     |          |
2024-09-12 12:13:05 +02:00
Jakub Grzywacz
fbc66311a9 fix: add deprecated SvgViewManager to not break 0.72 (#2435)
# Summary

Fixes #2428
To not introduce the breaking change in minor version, it restores the
old `SvgViewManager.java` on RN <= 72 using sourceSets

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| Android |          |
2024-09-02 15:28:54 +02:00
Jakub Grzywacz
8d3a03e6be fix: reset paint settings before drawing final bitmap (#2439)
# Summary

Fixes #2436.
#2403 introduced shared `Paint` between the node render method and the
final bitmap. However, Paint properties are not cleared after drawing,
so we need to call the `.clear()` method and re-enable antialiasing.

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| Android |         |
2024-09-02 13:27:10 +02:00
Jakub Grzywacz
53ba6f2413 fix: android svg scale 0 (#2424)
# Summary

Fixes #2421, bug introduced in
https://github.com/software-mansion/react-native-svg/pull/2403/files#diff-7f8adeb6e7faded1a7ef711b4fa9d2b12d29ff386217e838c4551866afdd8befR286
this line. When bitmap size is less or equal to 0 we want to stop
rendering the SVG to avoid Android crash.

## Test Plan

Set `transform="scale(0)"` to `Svg` element.

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| Android |          |

## Checklist

- [x] I have tested this on a device and a simulator
2024-08-23 12:31:05 +02:00
Jakub Grzywacz
d11d892496 feat: rewrite Svg transform (#2403)
# Summary

Currently, when applying transforms depending on the type (RN style vs
SVG style) transforms behave differently giving wrong results.

Example component
```tsx
<Svg
  height="200"
  viewBox="0 0 200 200"
  width="200"
  // transform={[{scale: 2}]}
  // transform="scale(2)"
  // transform={[{rotate: '45deg'}]}
  // transform="rotate(45)"
  // transform={[{translateX: 100}, {translateY: 100}]}
  // transform="translate(100 100)"
>
  <Mask id="myMask">
    <Rect fill="white" height="100" width="100" x="0" y="0" />
    <Path d="M10,35 A20,20,0,0,1,50,35 A20,20,0,0,1,90,35 Q90,65,50,95 Q10,65,10,35 Z" />
  </Mask>
  <Rect fill="pink" height="200" width="300" x="0" y="0" />
  <Circle cx="50" cy="50" fill="purple" mask="url(#myMask)" r="50" />
  <Rect fill="green" x="50" y="100" width="100" height="100" />
</Svg>
```
| Attribute | Before | After |
| --- | --- | --- |
| `transform={[{scale: 2}]}` | <img width="250" alt="image"
src="https://github.com/user-attachments/assets/c04d7e11-e039-4d1a-b804-e993f3877b6a">
| <img width="250" alt="image"
src="https://github.com/user-attachments/assets/bb717ae4-7c8f-410a-942d-1bd6feab273c">
|
| `transform="scale(2)"` | <img width="250" alt="image"
src="https://github.com/user-attachments/assets/85717613-ede0-44a8-8524-c9af4b37c09d">
| <img width="250" alt="image"
src="https://github.com/user-attachments/assets/f4e23bc6-8cfb-4509-a2f5-45c4f642c197">
|
| `transform={[{rotate: '45deg'}]}` | <img width="250" alt="image"
src="https://github.com/user-attachments/assets/90131401-2c52-4e8a-81ab-6cd449625953">
| <img width="250" alt="image"
src="https://github.com/user-attachments/assets/bab46300-4794-4322-bd95-d6e7e7abd30e">
|
| `transform="rotate(45)"` | <img width="250" alt="image"
src="https://github.com/user-attachments/assets/6d308022-4844-451a-b767-1c3e94e7a295">
| <img width="250" alt="image"
src="https://github.com/user-attachments/assets/553bbad5-9e37-4a52-b4e0-fa0c7b6b558e">
|
| `transform={[{translateX: 100}, {translateY: 100}]}` | <img
width="250" alt="image"
src="https://github.com/user-attachments/assets/91508d75-2b0a-4be6-9280-2ace017d9271">
| <img width="250" alt="image"
src="https://github.com/user-attachments/assets/36fb5cad-1ccf-4c99-8ffd-70ea56ba589f">
|
| `transform="translate(100 100)"` | <img width="250" alt="image"
src="https://github.com/user-attachments/assets/28fa66f2-b2f2-4b86-bb41-47bd507d6018">
| <img width="250" alt="image"
src="https://github.com/user-attachments/assets/36fb5cad-1ccf-4c99-8ffd-70ea56ba589f">
|

## Test Plan

Test example app -> `Test2403`
2024-08-19 09:16:18 +02:00
Jakub Grzywacz
ca1c35caa9 feat: introduce hitSlop prop (#2407)
# Summary

Explain the **motivation** for making this change: here are some points
to help you:

* What issues does the pull request solve? Please tag them so that they
will get automatically closed once the PR is merged
* What is the feature? (if applicable)
* How did you implement the solution?
* What areas of the library does it impact?

## Test Plan

Demonstrate the code is solid. Example: The exact commands you ran and
their output, screenshots / videos if the pull request changes UI.

### What's required for testing (prerequisites)?

### What are the steps to reproduce (after prerequisites)?

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |         |
| MacOS   |          |
| Android |          |
| Web     |          |
2024-08-19 09:11:07 +02:00
Jakub Grzywacz
7acbee41f3 fix: FeMerge on paper (#2384)
# Summary

Use empty string (`""`) instead of `undefined` for previous filter
result in `FeMergeNode`
2024-07-31 15:13:50 +02:00
Jakub Grzywacz
b8b022c31e feat: add FeMerge and FeMergeNode filters (#2369)
# Summary

As mentioned in #2362
Introduce new filters:
* `FeMerge`
* `FeMergeNode`

## Example usage

```tsx
<Svg width="200" height="200">
  <Filter id="mergeWithOffset" width="180" height="180">
    <FeOffset dx="50" dy="50" result="test" />
    <FeOffset dx="100" dy="100" in="SourceGraphic" />
    <FeMerge>
      <FeMergeNode in="SourceGraphic" />
      <FeMergeNode in="test" />
      <FeMergeNode />
    </FeMerge>
  </Filter>
  <Rect
    x="0"
    y="0"
    width="100"
    height="100"
    stroke="black"
    fill="red"
    filter="url(#mergeWithOffset)"
  />
</Svg>
```

<img width="207" alt="image"
src="https://github.com/user-attachments/assets/9cb3ded6-f939-4b2b-8ece-df54e64fe898">

## Test Plan

`Example` app -> `Filters` -> `FeMerge`

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |         |
| Android |         |

## Checklist

- [x] I have tested this on a device and a simulator
- [x] I added documentation in `README.md`
- [x] I updated the typed files (typescript)
2024-07-31 13:23:53 +02:00
Tomasz Żelawski
129e8ed8b5 feat: Make CMake less verbose (#2377)
<!-- Thanks for submitting a pull request! We appreciate you spending
the time to work on these changes. Please follow the template so that
the reviewers can easily understand what the code changes affect -->

# Summary

Explain the **motivation** for making this change: here are some points
to help you:

* What issues does the pull request solve? Please tag them so that they
will get automatically closed once the PR is merged
* What is the feature? (if applicable)
* How did you implement the solution?
* What areas of the library does it impact?

## Test Plan

Demonstrate the code is solid. Example: The exact commands you ran and
their output, screenshots / videos if the pull request changes UI.

### What's required for testing (prerequisites)?

### What are the steps to reproduce (after prerequisites)?

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |         |
| Android |         |

## Checklist

<!-- Check completed item, when applicable, via: [X] -->

- [x] I have tested this on a device and a simulator
- [x] I added documentation in `README.md`
- [x] I updated the typed files (typescript)
- [x] I added a test for the API in the `__tests__` folder
2024-07-30 09:34:37 +02:00
Jakub Grzywacz
25099ff220 refactor: small changes to filters (#2368)
# Summary

This PR contains two small refactors of filters:
* extract common props on ViewManagers on Android
* remove unnecessary extract in `FeOffset` filter
2024-07-29 08:21:17 +02:00
Jakub Grzywacz
5807f2c1a6 feat: add FeOffset filter (#2361)
# Summary

Continuation of #2316
Introducing new filter `FeOffset`.

## Test Plan

Example app -> Filters -> FeOffset

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |         |
| Android |         |

## Checklist

- [x] I have tested this on a device and a simulator
- [x] I added documentation in `README.md`
- [x] I updated the typed files (typescript)
2024-07-25 12:32:15 +02:00
Jakub Grzywacz
44254df9fb feat: add FeGaussianBlur filter (#2352)
# Summary

Continuation of #2316 
Introducing new filter `FeGaussianBlur`.

### Implementation notes

On Android there is no easy way to fully implement Gaussian blur, as
there is no native api for this. While a basic implementation is
possible with `RenderScript`, it does not allow for blur in one axis and
greater than `25`

## Test Plan

Example app -> Filters -> FeGaussianBlur

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |         |
| Android |         |
2024-07-25 11:46:45 +02:00
Jakub Grzywacz
9a2cd3d855 fix: color shift in FeColorMatrix on android (#2365)
# Summary

While debugging #2364 I've noticed that color shift in `FeColorMatrix`
on Android is wrong.
On web, elements 5, 10, 15, 20 is a color shift represented by number
where 1 mean full color shift, while on Android it's 255 for full color
shift.

## Test

```tsx
<svg width="180" height="180" viewBox="0 0 180 180">
  <rect width="180" height="180" fill="red" filter="url(#filter)"/>
  <filter id="filter">
    <feColorMatrix type="matrix" values="0 0 0 0 1
                                         0 1 0 0 0
                                         0 0 1 0 0
                                         0 0 0 1 0"/>
  </filter>
</svg>
```
2024-07-24 16:27:06 +02:00