Skip to content

Commit

Permalink
final fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
intergalacticspacehighway committed Jan 5, 2025
1 parent d7a560c commit 85268b0
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type LinearGradientDirection =

// null color indicate that the transition hint syntax is used. e.g. red, 20%, blue
type ColorStopColor = ProcessedColorValue | null;
// percentage or pixel value
type ColorStopPosition = number | string | null;

type ParsedGradientValue = {
Expand Down Expand Up @@ -360,80 +361,3 @@ function getPositionFromCSSValue(position: string) {
return position;
}
}

// https://drafts.csswg.org/css-images-4/#color-stop-fixup
// function getFixedColorStops(
// colorStops: $ReadOnlyArray<{
// color: ColorStopColor,
// position: ColorStopPosition,
// }>,
// ): Array<{
// color: ColorStopColor,
// position: ColorStopPosition,
// }> {
// let fixedColorStops: Array<{
// color: ColorStopColor,
// position: ColorStopPosition,
// }> = [];
// let hasNullPositions = false;
// let maxPositionSoFar = colorStops[0].position ?? 0;
// for (let i = 0; i < colorStops.length; i++) {
// const colorStop = colorStops[i];
// let newPosition = colorStop.position;
// if (newPosition === null) {
// // Step 1:
// // If the first color stop does not have a position,
// // set its position to 0%. If the last color stop does not have a position,
// // set its position to 100%.
// if (i === 0) {
// newPosition = 0;
// } else if (i === colorStops.length - 1) {
// newPosition = 1;
// }
// }
// Step 2:
// If a color stop or transition hint has a position
// that is less than the specified position of any color stop or transition hint
// before it in the list, set its position to be equal to the
// largest specified position of any color stop or transition hint before it.
// if (newPosition !== null) {
// newPosition = Math.max(newPosition, maxPositionSoFar);
// fixedColorStops[i] = {
// color: colorStop.color,
// position: newPosition,
// };
// maxPositionSoFar = newPosition;
// } else {
// hasNullPositions = true;
// }
// }

// Step 3:
// If any color stop still does not have a position,
// then, for each run of adjacent color stops without positions,
// set their positions so that they are evenly spaced between the preceding and
// following color stops with positions.
// if (hasNullPositions) {
// let lastDefinedIndex = 0;
// for (let i = 1; i < fixedColorStops.length; i++) {
// if (fixedColorStops[i] !== undefined) {
// const unpositionedStops = i - lastDefinedIndex - 1;
// if (unpositionedStops > 0) {
// const startPosition = fixedColorStops[lastDefinedIndex].position;
// const endPosition = fixedColorStops[i].position;
// const increment =
// (endPosition - startPosition) / (unpositionedStops + 1);
// for (let j = 1; j <= unpositionedStops; j++) {
// fixedColorStops[lastDefinedIndex + j] = {
// color: colorStops[lastDefinedIndex + j].color,
// position: startPosition + increment * j,
// };
// }
// }
// lastDefinedIndex = i;
// }
// }
// }

// return fixedColorStops;
// }
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ internal class Gradient(gradient: ReadableMap?, context: Context) {
}

public fun getShader(bounds: Rect): Shader? {
linearGradient
return when (type) {
GradientType.LINEAR_GRADIENT ->
linearGradient.getShader(bounds.width().toFloat(), bounds.height().toFloat())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.ReadableType
import com.facebook.react.uimanager.FloatUtil
import com.facebook.react.uimanager.PixelUtil
import kotlin.math.atan
import kotlin.math.ln
import kotlin.math.sqrt
Expand Down Expand Up @@ -120,10 +121,8 @@ internal class LinearGradient(
stops.add(ColorStop(color, position))
}
stops;

}


public fun getShader(width: Float, height: Float): Shader {
val angle =
when (direction) {
Expand All @@ -135,7 +134,7 @@ internal class LinearGradient(
val dx = endPoint[0] - startPoint[0];
val dy = endPoint[1] - startPoint[1];
val gradientLineLength = sqrt(dx * dx + dy * dy)
val processedColorStops = getFixedColorStops(colorStops, context, gradientLineLength)
val processedColorStops = getFixedColorStops(colorStops, gradientLineLength)
val finalStops = processColorTransitionHints(processedColorStops);
val colors = IntArray(finalStops.size)
val positions = FloatArray(finalStops.size)
Expand Down Expand Up @@ -220,7 +219,6 @@ internal class LinearGradient(

private fun getFixedColorStops(
colorStops: ArrayList<ColorStop>,
context: Context,
gradientLineLength: Float
): List<ColorStop> {
val fixedColorStops = ArrayList<ColorStop>(colorStops.size)
Expand All @@ -232,14 +230,21 @@ internal class LinearGradient(
var newPosition = resolveColorStopPosition(colorStop.position, gradientLineLength)

if (newPosition.unit == UnitType.Undefined) {
// Step 1: Set position for first and last stops if undefined
// Step 1:
// If the first color stop does not have a position,
// set its position to 0%. If the last color stop does not have a position,
// set its position to 100%.
when (i) {
0 -> newPosition = ValueUnit(0f, UnitType.Point)
colorStops.size - 1 -> newPosition = ValueUnit(1f, UnitType.Point)
}
}

// Step 2: Ensure positions are monotonically increasing
// Step 2:
// If a color stop or transition hint has a position
// that is less than the specified position of any color stop or transition hint
// before it in the list, set its position to be equal to the
// largest specified position of any color stop or transition hint before it.
if (newPosition.unit != UnitType.Undefined) {
newPosition = ValueUnit(
maxOf(newPosition.value, maxPositionSoFar),
Expand All @@ -253,7 +258,11 @@ internal class LinearGradient(
}
}

// Step 3: Distribute undefined positions evenly
// Step 3:
// If any color stop still does not have a position,
// then, for each run of adjacent color stops without positions,
// set their positions so that they are evenly spaced between the preceding and
// following color stops with positions.
if (hasNullPositions) {
var lastDefinedIndex = 0
for (i in 1 until fixedColorStops.size) {
Expand Down Expand Up @@ -397,7 +406,7 @@ internal class LinearGradient(

private fun resolveColorStopPosition(position: ValueUnit, gradientLineLength: Float): ValueUnit {
return when (position.unit) {
UnitType.Point -> ValueUnit(position.value / gradientLineLength, UnitType.Point)
UnitType.Point -> ValueUnit(PixelUtil.toPixelFromDIP(position.value) / gradientLineLength, UnitType.Point)
UnitType.Percent -> ValueUnit(position.value / 100, UnitType.Point)
UnitType.Undefined -> position
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ import {Platform, PlatformColor, StyleSheet, View} from 'react-native';
type Props = $ReadOnly<{
style: ViewStyleProp,
testID?: string,
children?: React.Node,
}>;

function GradientBox(props: Props): React.Node {
return (
<View style={[styles.box, props.style]} testID={props.testID}>
<RNTesterText style={styles.text}>Linear Gradient</RNTesterText>
{props.children}
</View>
);
}
Expand Down Expand Up @@ -56,8 +57,9 @@ exports.examples = [
style={{
experimental_backgroundImage: 'linear-gradient(#e66465, #9198e5);',
}}
testID="linear-gradient-basic"
/>
testID="linear-gradient-basic">
<RNTesterText style={styles.text}>Linear Gradient</RNTesterText>
</GradientBox>
);
},
},
Expand Down Expand Up @@ -237,4 +239,26 @@ exports.examples = [
);
},
},
{
title: 'with px and % combination',
render(): React.Node {
return (
<GradientBox
style={{
experimental_backgroundImage: `linear-gradient(
to right,
#f15a24 0%,
#f15a24 50px,
#fbb03b 50px,
35%,
#29abe2 65%,
180px,
#2e3192 100%
);`,
}}
testID="linear-gradient-transition-hint"
/>
);
},
},
];

0 comments on commit 85268b0

Please sign in to comment.