Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android applies rounding to rect when stretching with preserveAspectRatio="none" #1057

Closed
EyMaddis opened this issue Jul 23, 2019 · 10 comments
Closed

Comments

@EyMaddis
Copy link

EyMaddis commented Jul 23, 2019

Bug

When using preserveAspectRatio="none" I can use pixel dimensions which are potentially only 1 pixel in size, but setting a width={somethingLarger} should stretch the image if viewBox is defined.
On iOS and the web it does, but not on android.

Here is an expo that shows the bug:
https://snack.expo.io/@eymaddis/react-native-svg-android-rounding-error

This is what happens on iOS and web:

Jul-23-2019 12-23-19

Android:
ezgif-1-15f9dcf7bbd9

Likely related to #1033.

In this recording I used a device with a pixel density of 2, which is likely why it rounds on 0.5. I assume that using a device with a higher pixel density will result in more visible steps.

Environment info

React native info output:

info 
  React Native Environment Info:
    System:
      OS: macOS 10.14.5
      CPU: (8) x64 Intel(R) Core(TM) i7-6920HQ CPU @ 2.90GHz
      Memory: 1.14 GB / 16.00 GB
      Shell: 3.2.57 - /bin/bash
    Binaries:
      Node: 10.16.0 - /usr/local/bin/node
      Yarn: 1.16.0 - /usr/local/bin/yarn
      npm: 6.9.0 - /usr/local/bin/npm
      Watchman: 4.9.0 - /usr/local/bin/watchman
    SDKs:
      iOS SDK:
        Platforms: iOS 12.2, macOS 10.14, tvOS 12.2, watchOS 5.2
      Android SDK:
        API Levels: 19, 23, 24, 25, 26, 27, 28
        Build Tools: 23.0.1, 25.0.1, 25.0.2, 25.0.3, 26.0.1, 26.0.3, 27.0.3, 28.0.2, 28.0.3
        System Images: android-19 | Google APIs Intel x86 Atom, android-27 | Google APIs Intel x86 Atom, android-27 | Google Play Intel x86 Atom, android-28 | Android TV Intel x86 Atom, android-28 | Google APIs Intel x86 Atom, android-Q | Google APIs Intel x86 Atom
    IDEs:
      Android Studio: 3.0 AI-171.4443003
      Xcode: 10.2.1/10E1001 - /usr/bin/xcodebuild
    npmPackages:
      react: 16.8.3 => 16.8.3 
      react-native: 0.59.4 => 0.59.4 

Library version: 9.5.3

Steps To Reproduce

See expo above.

  1. Generate SVG with width and height of 1
  2. set preserveAspectRatio="none"
  3. Set Width/height property on <Svg /> in order to stretch the image.
    ...

Describe what you expected to happen:
Image should be rendered such that it fills the width/height, without rounding.

Reproducible sample code

See https://snack.expo.io/@eymaddis/react-native-svg-android-rounding-error

import { Text, View, StyleSheet, Dimensions } from 'react-native';
import Constants from 'expo-constants';
import Svg, { Rect } from 'react-native-svg';

export default class App extends React.Component {
  state = {
    stretchTo: 0
  }
  update() {
    this.setState(function({ stretchTo }) {
      console.warn('stretchTo',stretchTo)
      return {
        stretchTo: parseFloat(((stretchTo + 0.1) % 1).toFixed(1)) // avoid float rounding errors like 0,999999...4
      }
    })
    //requestAnimationFrame(this.update)
  }

  componentDidMount() {
    setInterval(this.update.bind(this), 1000)
  }

  
  render() {
    const { stretchTo } = this.state
    const barHeight = 5
    return (
      <View style={styles.container}>
      <Line stretchTo={stretchTo} />
      <Line stretchTo={0} />
      <Line stretchTo={0.25} />
      <Line stretchTo={0.5} />
      <Line stretchTo={0.75} />
      <Line stretchTo={1} />
      </View>
    );
  }
}

function Line({ stretchTo }) {
  const barHeight = 5
  const { width, height } = Dimensions.get('window') 
    
      
  return <>
  <Text>Width: {stretchTo}</Text>
  <Svg 
        width={width}
        height={barHeight}

        preserveAspectRatio="none"
        viewBox={`0 0 1 ${barHeight}`}
       >
        <Rect 
          x={0}
          y={0}
          width={stretchTo}
          height={barHeight}
          fill="red"
        />
       </Svg>
  </>
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    //alignItems: 'center',
    paddingTop: Constants.statusBarHeight + 100,
    backgroundColor: '#ecf0f1',
  },
});
@EyMaddis EyMaddis changed the title Android applies rounding to rect Android applies rounding to rect when stretching with preserveAspectRatio="none" Jul 23, 2019
@msand
Copy link
Collaborator

msand commented Jul 24, 2019

Can you try with the latest commit in the develop branch?

@EyMaddis
Copy link
Author

@msand No change, I tried commit 7b8ad33462db616e340c3968a35980ea6b502967

@msand
Copy link
Collaborator

msand commented Jul 24, 2019

Can you try 08e82c5 instead?

@msand
Copy link
Collaborator

msand commented Jul 24, 2019

At least seems to work fine for me, did you rebuild the native code?

@msand
Copy link
Collaborator

msand commented Jul 24, 2019

Btw you'll need to eject from Expo, if you're using that, to build native dependencies.

@EyMaddis
Copy link
Author

EyMaddis commented Jul 25, 2019

Oh, I forgot to rebuild native...

Unfortunately it does not compile, I tried both commits and cleaned the project before.

> Task :react-native-svg:compileDebugJavaWithJavac FAILED
....node_modules/react-native-svg/android/src/main/java/com/horcrux/svg/TSpanView.java:1033: error: method getTypeface in class ReactFontManager cannot be applied to given types;
                typeface = ReactFontManager.getInstance().getTypeface(fontFamily, fontStyle, weight, assetManager);
                                                         ^
  required: String,int,AssetManager
  found: String,int,int,AssetManager
  reason: actual and formal argument lists differ in length
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
1 error

I use React Native 0.59, seems like this is not compatible.

@msand
Copy link
Collaborator

msand commented Jul 25, 2019

Oh, I see. That's from having added support for variable fonts and font weight variation axes. I'll try and find some backwards compatible way to get it done. If you want a quick fick, you can remove the weight argument from the getTypeface call and rebuild.

@EyMaddis
Copy link
Author

I have a fix in my code, I just set the width to be really big and scale down the image instead of scaling a small one up.

@msand
Copy link
Collaborator

msand commented Jul 25, 2019

I think the latest commit in develop should work fine in 0.59 and earlier, could you try with that?

@EyMaddis
Copy link
Author

I had to clean and rebuild the project and a little trouble with android studio, but in the end it did work out! :)
Thanks for your quick and effective responds!
👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants