[go: nahoru, domu]

blob: 3412df05b9e7792a4fccad823c9d8f00d7d397df [file] [log] [blame]
/*
* Copyright 2020 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.core
import android.graphics.Matrix
import android.graphics.RectF
import androidx.ui.graphics.Canvas
import androidx.ui.unit.IntPxPosition
import androidx.ui.unit.PxPosition
import androidx.ui.unit.px
internal class LayerWrapper(
wrapped: LayoutNodeWrapper,
modifier: DrawLayerModifier
) : DelegatingLayoutNodeWrapper<DrawLayerModifier>(wrapped, modifier) {
private var _layer: OwnedLayer? = null
private var layerDestroyed = false
// Do not invalidate itself on position change.
override val invalidateLayerOnBoundsChange get() = false
private val invalidateParentLayer: () -> Unit = {
wrappedBy?.findLayer()?.invalidate()
}
val layer: OwnedLayer
get() {
return _layer ?: layoutNode.requireOwner().createLayer(
modifier,
wrapped::draw,
invalidateParentLayer
).also {
_layer = it
invalidateParentLayer()
}
}
// TODO(mount): This cache isn't thread safe at all.
private var positionCache: FloatArray? = null
// TODO (njawad): This cache matrix is not thread safe
private var inverseMatrixCache: Matrix? = null
override fun performMeasure(constraints: Constraints): Placeable {
val placeable = super.performMeasure(constraints)
layer.resize(measuredSize)
return placeable
}
override fun place(position: IntPxPosition) {
super.place(position)
layer.move(position)
}
override fun draw(canvas: Canvas) {
layer.drawLayer(canvas)
}
override fun detach() {
super.detach()
_layer?.destroy()
}
override fun findLayer(): OwnedLayer? {
return layer
}
override fun fromParentPosition(position: PxPosition): PxPosition {
val matrix = layer.getMatrix()
val targetPosition =
if (!matrix.isIdentity) {
val inverse = inverseMatrixCache ?: Matrix().also { inverseMatrixCache = it }
matrix.invert(inverse)
mapPointsFromMatrix(inverse, position)
} else {
position
}
return super.fromParentPosition(targetPosition)
}
override fun toParentPosition(position: PxPosition): PxPosition {
val matrix = layer.getMatrix()
val targetPosition =
if (!matrix.isIdentity) {
mapPointsFromMatrix(matrix, position)
} else {
position
}
return super.toParentPosition(targetPosition)
}
/**
* Return a transformed [PxPosition] based off of the provided matrix transformation
* and untransformed position.
*/
private fun mapPointsFromMatrix(matrix: Matrix, position: PxPosition): PxPosition {
val x = position.x.value
val y = position.y.value
val cache = positionCache
val point = if (cache != null) {
cache[0] = x
cache[1] = y
cache
} else {
floatArrayOf(x, y).also { positionCache = it }
}
matrix.mapPoints(point)
return PxPosition(point[0].px, point[1].px)
}
override fun rectInParent(bounds: RectF) {
if ((modifier.clipToBounds ||
(modifier.clipToOutline && modifier.outlineShape != null)) &&
!bounds.intersect(0f, 0f, size.width.value.toFloat(), size.height.value.toFloat())
) {
bounds.setEmpty()
}
val matrix = layer.getMatrix()
matrix.mapRect(bounds)
return super.rectInParent(bounds)
}
}