All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.androidx.compose.ui.graphics.PathIterator.kt Maven / Gradle / Ivy

/*
 * Copyright 2023 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.compose.ui.graphics

import androidx.compose.ui.graphics.PathIterator.ConicEvaluation

/**
 * A path iterator can be used to iterate over all the [segments][PathSegment] that make up
 * a path. Those segments may in turn define multiple contours inside the path. Conic segments
 * are by default evaluated as approximated quadratic segments. To preserve conic segments as
 * conics, set [conicEvaluation] to [AsConic][ConicEvaluation.AsConic]. The error of the
 * approximation is controlled by [tolerance].
 *
 * A [PathIterator] can be created implicitly through a given [Path] object: using one of the
 * two [Path.iterator] functions.
 *
 * @param path The [Path] to iterate over
 * @param conicEvaluation Indicates how to evaluate conic segments
 * @param tolerance When [conicEvaluation] is set to [PathIterator.ConicEvaluation.AsQuadratics]
 *        defines the maximum distance between the original conic curve and its quadratic
 *        approximations
 */
expect fun PathIterator(
    path: Path,
    conicEvaluation: ConicEvaluation = ConicEvaluation.AsQuadratics,
    tolerance: Float = 0.25f
): PathIterator

/**
 * A path iterator can be used to iterate over all the [segments][PathSegment] that make up
 * a path. Those segments may in turn define multiple contours inside the path.
 *
 * The handling of conic segments is defined by the [conicEvaluation] property. When set to
 * [AsConic][ConicEvaluation.AsConic], conic segments are preserved, but when set to
 * [AsConic][ConicEvaluation.AsQuadratics], conic segments are approximated using 1 or more
 * quadratic segments. The error of the approximation is controlled by [tolerance].
 */
interface PathIterator : Iterator {
    /**
     * Used to define how conic segments are evaluated when iterating over a [Path] using
     * [PathIterator].
     */
    enum class ConicEvaluation {
        /**
         * Conic segments are returned as conic segments.
         */
        AsConic,

        /**
         * Conic segments are returned as quadratic approximations. The quality of the
         * approximation is defined by a tolerance value.
         */
        AsQuadratics
    }

    /**
     * The [Path] this iterator iterates on.
     */
    val path: Path

    /**
     * Indicates whether conic segments, when present, are preserved as-is or converted to
     * quadratic segments, using an approximation whose error is controlled by [tolerance].
     */
    val conicEvaluation: ConicEvaluation

    /**
     * Error of the approximation used to evaluate conic segments if they are converted
     * to quadratics. The error is defined as the maximum distance between the original
     * conic segment and its quadratic approximation. See [conicEvaluation].
     */
    val tolerance: Float

    /**
     * Returns the number of verbs present in this iterator, i.e. the number of calls to
     * [next] required to complete the iteration.
     *
     * By default, [calculateSize] returns the true number of operations in the iterator. Deriving
     * this result requires converting any conics to quadratics, if [conicEvaluation] is
     * set to [ConicEvaluation.AsQuadratics], which takes extra processing time. Set
     * [includeConvertedConics] to false if an approximate size, not including conic
     * conversion, is sufficient.
     *
     * @param includeConvertedConics The returned size includes any required conic conversions.
     * Default is true, so it will return the exact size, at the cost of iterating through
     * all elements and converting any conics as appropriate. Set to false to save on processing,
     * at the cost of a less exact result.
     */
    fun calculateSize(includeConvertedConics: Boolean = true): Int

    /**
     * Returns `true` if the iteration has more elements.
     */
    override fun hasNext(): Boolean

    /**
     * Returns the [type][PathSegment.Type] of the next [path segment][PathSegment] in the iteration
     * and fills [outPoints] with the points specific to the segment type. Each pair of floats in
     * the [outPoints] array represents a point for the given segment. The number of pairs of floats
     * depends on the [PathSegment.Type]:
     *
     * - [Move][PathSegment.Type.Move]: 1 pair (indices 0 to 1)
     * - [Line][PathSegment.Type.Line]: 2 pairs (indices 0 to 3)
     * - [Quadratic][PathSegment.Type.Quadratic]: 3 pairs (indices 0 to 5)
     * - [Conic][PathSegment.Type.Conic]: 3 pairs (indices 0 to 5), and the conic
     *   [weight][PathSegment.weight] at index 6. The value of the last float is undefined.
     *   See [PathSegment.Type.Conic] for more details
     * - [Cubic][PathSegment.Type.Cubic]: 4 pairs (indices 0 to 7)
     * - [Close][PathSegment.Type.Close]: 0 pair
     * - [Done][PathSegment.Type.Done]: 0 pair
     *
     * This method does not allocate any memory.
     *
     * @param outPoints A [FloatArray] large enough to hold 8 floats starting at [offset],
     *               throws an [IllegalStateException] otherwise.
     * @param offset Offset in [outPoints] where to store the result
     */
    fun next(outPoints: FloatArray, offset: Int = 0): PathSegment.Type

    /**
     * Returns the next [path segment][PathSegment] in the iteration, or [DoneSegment] if
     * the iteration is finished. To save on allocations, use the alternative [next] function, which
     * takes a [FloatArray].
     */
    override fun next(): PathSegment
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy