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

androidMain.androidx.compose.ui.text.android.LayoutCompat.kt Maven / Gradle / Ivy

/*
 * Copyright 2019 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.text.android

import android.graphics.text.LineBreakConfig
import android.graphics.text.LineBreaker
import android.text.Layout
import android.text.Layout.Alignment
import android.text.TextDirectionHeuristic
import android.text.TextDirectionHeuristics
import androidx.annotation.IntDef
import androidx.annotation.IntRange

/**
 * LayoutCompat class which provides all supported attributes by framework, and also defines
 * default value of those attributes for Compose.
 *
 * @suppress
 */
@InternalPlatformTextApi
object LayoutCompat {
    const val ALIGN_NORMAL = 0
    const val ALIGN_OPPOSITE = 1
    const val ALIGN_CENTER = 2
    const val ALIGN_LEFT = 3
    const val ALIGN_RIGHT = 4

    @Retention(AnnotationRetention.SOURCE)
    @IntDef(
        ALIGN_NORMAL,
        ALIGN_CENTER,
        ALIGN_OPPOSITE,
        ALIGN_LEFT,
        ALIGN_RIGHT
    )
    internal annotation class TextLayoutAlignment

    const val JUSTIFICATION_MODE_NONE = LineBreaker.JUSTIFICATION_MODE_NONE
    const val JUSTIFICATION_MODE_INTER_WORD = LineBreaker.JUSTIFICATION_MODE_INTER_WORD

    @Retention(AnnotationRetention.SOURCE)
    @IntDef(JUSTIFICATION_MODE_NONE, JUSTIFICATION_MODE_INTER_WORD)
    internal annotation class JustificationMode

    const val HYPHENATION_FREQUENCY_NONE = Layout.HYPHENATION_FREQUENCY_NONE
    const val HYPHENATION_FREQUENCY_NORMAL = Layout.HYPHENATION_FREQUENCY_NORMAL
    const val HYPHENATION_FREQUENCY_NORMAL_FAST = Layout.HYPHENATION_FREQUENCY_NORMAL_FAST

    @Retention(AnnotationRetention.SOURCE)
    @IntDef(
        HYPHENATION_FREQUENCY_NORMAL,
        HYPHENATION_FREQUENCY_NORMAL_FAST,
        HYPHENATION_FREQUENCY_NONE
    )
    internal annotation class HyphenationFrequency

    const val BREAK_STRATEGY_SIMPLE = LineBreaker.BREAK_STRATEGY_SIMPLE
    const val BREAK_STRATEGY_HIGH_QUALITY = LineBreaker.BREAK_STRATEGY_HIGH_QUALITY
    const val BREAK_STRATEGY_BALANCED = LineBreaker.BREAK_STRATEGY_BALANCED

    @Retention(AnnotationRetention.SOURCE)
    @IntDef(
        BREAK_STRATEGY_SIMPLE,
        BREAK_STRATEGY_HIGH_QUALITY,
        BREAK_STRATEGY_BALANCED
    )
    internal annotation class BreakStrategy

    const val LINE_BREAK_STYLE_NONE = LineBreakConfig.LINE_BREAK_STYLE_NONE
    const val LINE_BREAK_STYLE_LOOSE = LineBreakConfig.LINE_BREAK_STYLE_LOOSE
    const val LINE_BREAK_STYLE_NORMAL = LineBreakConfig.LINE_BREAK_STYLE_NORMAL
    const val LINE_BREAK_STYLE_STRICT = LineBreakConfig.LINE_BREAK_STYLE_STRICT

    @Retention(AnnotationRetention.SOURCE)
    @IntDef(
        LINE_BREAK_STYLE_NONE,
        LINE_BREAK_STYLE_LOOSE,
        LINE_BREAK_STYLE_NORMAL,
        LINE_BREAK_STYLE_STRICT
    )
    internal annotation class LineBreakStyle

    const val LINE_BREAK_WORD_STYLE_NONE = LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE
    const val LINE_BREAK_WORD_STYLE_PHRASE = LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE

    @Retention(AnnotationRetention.SOURCE)
    @IntDef(
        LINE_BREAK_WORD_STYLE_NONE,
        LINE_BREAK_WORD_STYLE_PHRASE
    )
    internal annotation class LineBreakWordStyle

    const val TEXT_DIRECTION_LTR = 0
    const val TEXT_DIRECTION_RTL = 1
    const val TEXT_DIRECTION_FIRST_STRONG_LTR = 2
    const val TEXT_DIRECTION_FIRST_STRONG_RTL = 3
    const val TEXT_DIRECTION_ANY_RTL_LTR = 4
    const val TEXT_DIRECTION_LOCALE = 5

    @Retention(AnnotationRetention.SOURCE)
    @IntDef(
        TEXT_DIRECTION_LTR,
        TEXT_DIRECTION_RTL,
        TEXT_DIRECTION_FIRST_STRONG_LTR,
        TEXT_DIRECTION_FIRST_STRONG_RTL,
        TEXT_DIRECTION_ANY_RTL_LTR,
        TEXT_DIRECTION_LOCALE
    )
    internal annotation class TextDirection

    const val DEFAULT_ALIGNMENT = ALIGN_NORMAL

    internal const val DEFAULT_TEXT_DIRECTION = TEXT_DIRECTION_FIRST_STRONG_LTR

    const val DEFAULT_LINESPACING_MULTIPLIER = 1.0f

    internal const val DEFAULT_LINESPACING_EXTRA = 0.0f

    internal const val DEFAULT_INCLUDE_PADDING = false

    internal const val DEFAULT_MAX_LINES = Integer.MAX_VALUE

    internal const val DEFAULT_BREAK_STRATEGY = BREAK_STRATEGY_SIMPLE

    internal const val DEFAULT_LINE_BREAK_STYLE = LINE_BREAK_STYLE_NONE

    internal const val DEFAULT_LINE_BREAK_WORD_STYLE = LINE_BREAK_WORD_STYLE_NONE

    internal const val DEFAULT_HYPHENATION_FREQUENCY = HYPHENATION_FREQUENCY_NONE

    const val DEFAULT_JUSTIFICATION_MODE = JUSTIFICATION_MODE_NONE

    internal const val DEFAULT_FALLBACK_LINE_SPACING = true

    internal val DEFAULT_LAYOUT_ALIGNMENT = Alignment.ALIGN_NORMAL

    internal val DEFAULT_TEXT_DIRECTION_HEURISTIC: TextDirectionHeuristic =
        TextDirectionHeuristics.FIRSTSTRONG_LTR
}

/**
 * Returns the line number at the offset
 *
 * If the automatic line break didn't happen at the given offset, this returns the 0 origin line
 * number that contains the given offset character.
 * If the automatic line break happened at the given offset, this returns the preceding 0 origin
 * line number that contains the given offset character if upstream is true. Otherwise, returns
 * the line number that contains the given offset character.
 *
 * @param offset a character offset in the text
 * @param upstream true if you want to get preceding line number for the line broken offset.
 * false if you want to get the following line number for the line broken offset. This is ignored
 * if the offset it not a line broken offset.
 * @return the line number
 *
 * @suppress
 */
@InternalPlatformTextApi
fun Layout.getLineForOffset(@IntRange(from = 0) offset: Int, upstream: Boolean): Int {
    if (offset <= 0) return 0
    if (offset >= text.length) return lineCount - 1
    val downstreamLineNo = getLineForOffset(offset)
    val lineStart = getLineStart(downstreamLineNo)
    val lineEnd = getLineEnd(downstreamLineNo)

    if (lineStart != offset && lineEnd != offset) {
        return downstreamLineNo
    }

    return if (lineStart == offset) {
        if (upstream) downstreamLineNo - 1 else downstreamLineNo
    } else { // lineEnd == offset
        if (upstream) downstreamLineNo else downstreamLineNo + 1
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy