[go: nahoru, domu]

blob: ec8fdafefcfba8654a652511a7a2584d959e7784 [file] [log] [blame]
/*
* Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.ui.painting
import androidx.ui.engine.geometry.Offset
import androidx.ui.vectormath64.Matrix4
import androidx.ui.vectormath64.PI
// A shader (as used by [Paint.shader]) that renders a color gradient.
//
// There are several types of gradients, represented by the various constructors
// on this class.
class Gradient private constructor(private val shader: android.graphics.Shader) : Shader() {
companion object {
/**
* Creates a linear gradient from `from` to `to`.
*
* If `colorStops` is provided, `colorStops[i]` is a number from 0.0 to 1.0
* that specifies where `color[i]` begins in the gradient. If `colorStops` is
* not provided, then only two stops, at 0.0 and 1.0, are implied (and
* `color` must therefore only have two entries).
*
* The behavior before `from` and after `to` is described by the `tileMode`
* argument. For details, see the [TileMode] enum.
*
* ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/tile_mode_clamp_linear.png)
* ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/tile_mode_mirror_linear.png)
* ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/tile_mode_repeated_linear.png)
*
* If `from`, `to`, `colors`, or `tileMode` are null, or if `colors` or
* `colorStops` contain null values, this constructor will throw a
* [NoSuchMethodError].
*/
// Gradient.linear(
// TODO(Migration/njawad remove annotation after b/113119778 is fixed/deployed)
@SuppressWarnings("SyntheticAccessor")
fun linear(
from: Offset,
to: Offset,
colors: List<Color>,
colorStops: List<Float>? = null,
tileMode: TileMode = TileMode.clamp
): Gradient {
_validateColorStops(colors, colorStops)
val linearGradient = android.graphics.LinearGradient(
from.dx,
from.dy,
to.dx,
to.dy,
toIntArray(colors),
toFloatArray(colorStops),
toFrameworkTileMode(tileMode)
)
return Gradient(linearGradient)
}
/**
* Creates a radial gradient centered at `center` that ends at `radius`
* distance from the center.
*
* If `colorStops` is provided, `colorStops[i]` is a number from 0.0 to 1.0
* that specifies where `color[i]` begins in the gradient. If `colorStops` is
* not provided, then only two stops, at 0.0 and 1.0, are implied (and
* `color` must therefore only have two entries).
*
* The behavior before and after the radius is described by the `tileMode`
* argument. For details, see the [TileMode] enum.
*
* ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/tile_mode_clamp_radial.png)
* ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/tile_mode_mirror_radial.png)
* ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/tile_mode_repeated_radial.png)
*
* If `center`, `radius`, `colors`, or `tileMode` are null, or if `colors` or
* `colorStops` contain null values, this constructor will throw a
* [NoSuchMethodError].
*
* If `matrix4` is provided, the gradient fill will be transformed by the
* specified 4x4 matrix relative to the local coordinate system. `matrix4` must
* be a column-major matrix packed into a list of 16 values.
*
* If `focal` is provided and not equal to `center` and `focalRadius` is
* provided and not equal to 0.0, the generated shader will be a two point
* conical radial gradient, with `focal` being the center of the focal
* circle and `focalRadius` being the radius of that circle. If `focal` is
* provided and not equal to `center`, at least one of the two offsets must
* not be equal to [Offset.zero].
*/
// TODO(Migration/njawad change matrix4 parameter to Float64List to match Flutter implementation)
// TODO(Migration/njawad remove annotation after b/113119778 is fixed/deployed)
@SuppressWarnings("SyntheticAccessor")
fun radial(
center: Offset,
radius: Float,
color: List<Color>,
colorStops: List<Float>?,
tileMode: TileMode = TileMode.clamp,
matrix4: Matrix4,
focal: Offset?,
focalRadius: Float
): Gradient {
_validateColorStops(color, colorStops)
if (focal == null || (focal == center && focalRadius == 0.0f)) {
TODO("Migration/njawad: add focal support to RadialGradient in framework")
} else {
// TODO(Migration/njawad use matrix parameter in creation of RadialGradient)
val radial = android.graphics.RadialGradient(
center.dx,
center.dy,
radius,
toIntArray(color),
toFloatArray(colorStops),
toFrameworkTileMode(tileMode)
)
return Gradient(radial)
}
}
/**
* Creates a sweep gradient centered at `center` that starts at `startAngle`
* and ends at `endAngle`.
*
* `startAngle` and `endAngle` should be provided in radians, with zero
* radians being the horizontal line to the right of the `center` and with
* positive angles going clockwise around the `center`.
*
* If `colorStops` is provided, `colorStops[i]` is a number from 0.0 to 1.0
* that specifies where `color[i]` begins in the gradient. If `colorStops` is
* not provided, then only two stops, at 0.0 and 1.0, are implied (and
* `color` must therefore only have two entries).
*
* The behavior before `startAngle` and after `endAngle` is described by the
* `tileMode` argument. For details, see the [TileMode] enum.
*
* ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/tile_mode_clamp_sweep.png)
* ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/tile_mode_mirror_sweep.png)
* ![](https://flutter.github.io/assets-for-api-docs/assets/dart-ui/tile_mode_repeated_sweep.png)
*
* If `center`, `colors`, `tileMode`, `startAngle`, or `endAngle` are null,
* or if `colors` or `colorStops` contain null values, this constructor will
* throw a [NoSuchMethodError].
*
* If `matrix4` is provided, the gradient fill will be transformed by the
* specified 4x4 matrix relative to the local coordinate system. `matrix4` must
* be a column-major matrix packed into a list of 16 values.
*/
// TODO(Migration/njawad change matrix4 parameter to Float64List to match Flutter implementation)
// TODO(Migration/njawad remove annotation after b/113119778 is fixed/deployed)
@SuppressWarnings("SyntheticAccessor")
fun sweep(
center: Offset,
colors: List<Color>,
colorStops: List<Float>,
tileMode: TileMode = TileMode.clamp,
startAngle: Float,
endAngle: Float = PI * 2,
matrix4: Matrix4
): Gradient {
_validateColorStops(colors, colorStops)
// TODO(Migration/njawad framework SweepGradient does not support angle ranges/TileModes)
val sweep = android.graphics.SweepGradient(
center.dx, center.dy,
toIntArray(colors),
toFloatArray(colorStops)
)
return Gradient(sweep)
}
private fun toFrameworkTileMode(tileMode: TileMode): android.graphics.Shader.TileMode {
return when (tileMode) {
TileMode.clamp -> android.graphics.Shader.TileMode.CLAMP
TileMode.mirror -> android.graphics.Shader.TileMode.MIRROR
TileMode.repeated -> android.graphics.Shader.TileMode.REPEAT
}
}
private fun toFloatArray(stops: List<Float>?): FloatArray? {
return if (stops != null) {
FloatArray(stops.size) { i ->
stops[i]
}
} else {
return null
}
}
private fun toIntArray(colors: List<Color>): IntArray {
return IntArray(colors.size) {
i -> colors[i].value
}
}
private fun _validateColorStops(colors: List<Color>, colorStops: List<Float>?) {
if (colorStops == null && colors.size != 2) {
throw IllegalArgumentException("colors must have length 2 if colorStops " +
"is omitted.")
} else if (colors.size != colorStops?.size) {
throw IllegalArgumentException("colors and colorStops arguments must have" +
" equal length.")
}
}
}
internal override fun toFrameworkShader(): android.graphics.Shader {
return shader
}
}