From cc27bb68a62fd6510ec135755f8a138f2f77eff3 Mon Sep 17 00:00:00 2001 From: Nikita Lipsky Date: Tue, 14 Feb 2023 21:32:56 +0200 Subject: [PATCH] Revert "Support for XML Vector Drawables." This reverts commit 6060e86cbdd125a42c4315dba8e641daf4bfad1a. --- .../demo/androidApp/build.gradle.kts | 7 +- .../resources/demo/shared/UseResources.kt | 6 - .../src/commonMain/resources/vector.xml | 34 --- components/resources/library/build.gradle.kts | 8 +- .../resources/ComposeResource.common.kt | 56 +--- .../compose/resources/vector/ValueParsers.kt | 104 ------- .../resources/vector/XmlVectorParser.kt | 276 ------------------ .../resources/vector/xmldom/Element.kt | 11 - .../compose/resources/vector/xmldom/Node.kt | 14 - .../resources/vector/xmldom/NodeList.kt | 10 - .../compose/resources/Resource.ios.kt | 5 +- .../compose/resources/xmldom/DomXmlParser.kt | 114 -------- .../compose/resources/Resource.js.kt | 5 - .../resources/Resource.jvmandandroid.kt | 22 -- .../compose/resources/xmldom/ElementImpl.kt | 10 - .../compose/resources/xmldom/NodeImpl.kt | 28 -- .../compose/resources/Resource.macos.kt | 5 - 17 files changed, 19 insertions(+), 696 deletions(-) delete mode 100644 components/resources/demo/shared/src/commonMain/resources/vector.xml delete mode 100644 components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/vector/ValueParsers.kt delete mode 100644 components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/vector/XmlVectorParser.kt delete mode 100644 components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/vector/xmldom/Element.kt delete mode 100644 components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/vector/xmldom/Node.kt delete mode 100644 components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/vector/xmldom/NodeList.kt delete mode 100644 components/resources/library/src/iosMain/kotlin/org/jetbrains/compose/resources/xmldom/DomXmlParser.kt delete mode 100644 components/resources/library/src/jvmAndAndroidMain/kotlin/org/jetbrains/compose/resources/Resource.jvmandandroid.kt delete mode 100644 components/resources/library/src/jvmAndAndroidMain/kotlin/org/jetbrains/compose/resources/xmldom/ElementImpl.kt delete mode 100644 components/resources/library/src/jvmAndAndroidMain/kotlin/org/jetbrains/compose/resources/xmldom/NodeImpl.kt diff --git a/components/resources/demo/androidApp/build.gradle.kts b/components/resources/demo/androidApp/build.gradle.kts index 56f228a7c8..4aa54613a1 100644 --- a/components/resources/demo/androidApp/build.gradle.kts +++ b/components/resources/demo/androidApp/build.gradle.kts @@ -1,7 +1,6 @@ plugins { id("com.android.application") kotlin("android") - id("org.jetbrains.compose") } dependencies { @@ -13,6 +12,12 @@ dependencies { } android { + buildFeatures { + compose = true + } + composeOptions { + kotlinCompilerExtensionVersion = "1.3.2" + } compileSdk = 33 defaultConfig { applicationId = "me.user.androidApp" diff --git a/components/resources/demo/shared/src/commonMain/kotlin/org/jetbrains/compose/resources/demo/shared/UseResources.kt b/components/resources/demo/shared/src/commonMain/kotlin/org/jetbrains/compose/resources/demo/shared/UseResources.kt index bc5f514132..9b89bae350 100644 --- a/components/resources/demo/shared/src/commonMain/kotlin/org/jetbrains/compose/resources/demo/shared/UseResources.kt +++ b/components/resources/demo/shared/src/commonMain/kotlin/org/jetbrains/compose/resources/demo/shared/UseResources.kt @@ -2,10 +2,8 @@ package org.jetbrains.compose.resources.demo.shared import androidx.compose.foundation.Image import androidx.compose.foundation.layout.* -import androidx.compose.material.Icon import androidx.compose.material.Text import androidx.compose.runtime.Composable -import androidx.compose.ui.platform.LocalDensity import org.jetbrains.compose.resources.* @OptIn(ExperimentalResourceApi::class) @@ -21,9 +19,5 @@ internal fun UseResources() { bitmap = resource("img.webp").rememberImageBitmap().orEmpty(), contentDescription = null, ) - Icon( - imageVector = resource("vector.xml").rememberImageVector(LocalDensity.current).orEmpty(), - contentDescription = null - ) } } diff --git a/components/resources/demo/shared/src/commonMain/resources/vector.xml b/components/resources/demo/shared/src/commonMain/resources/vector.xml deleted file mode 100644 index 1f6bb29060..0000000000 --- a/components/resources/demo/shared/src/commonMain/resources/vector.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/components/resources/library/build.gradle.kts b/components/resources/library/build.gradle.kts index bd26802d18..796ef6019e 100644 --- a/components/resources/library/build.gradle.kts +++ b/components/resources/library/build.gradle.kts @@ -38,12 +38,8 @@ kotlin { val skikoMain by creating { dependsOn(commonMain) } - val jvmAndAndroidMain by creating { - dependsOn(commonMain) - } val desktopMain by getting { dependsOn(skikoMain) - dependsOn(jvmAndAndroidMain) } val desktopTest by getting { dependencies { @@ -52,9 +48,7 @@ kotlin { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-swing:1.6.4") } } - val androidMain by getting { - dependsOn(jvmAndAndroidMain) - } + val androidMain by getting {} val androidTest by getting { dependencies { diff --git a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ComposeResource.common.kt b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ComposeResource.common.kt index c09f0f2b6a..f39c1fcde1 100644 --- a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ComposeResource.common.kt +++ b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ComposeResource.common.kt @@ -7,25 +7,19 @@ package org.jetbrains.compose.resources import androidx.compose.runtime.* import androidx.compose.ui.graphics.ImageBitmap -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.unit.Density -import org.jetbrains.compose.resources.vector.xmldom.Element -import org.jetbrains.compose.resources.vector.parseVectorRoot -import androidx.compose.ui.unit.dp private val emptyImageBitmap: ImageBitmap by lazy { ImageBitmap(1, 1) } -private val emptyImageVector: ImageVector by lazy { - ImageVector.Builder(defaultWidth = 1.dp, defaultHeight = 1.dp, viewportWidth = 1f, viewportHeight = 1f).build() -} - -@OptIn(ExperimentalResourceApi::class) +/** + * Get and remember resource. While loading and if resource not exists result will be null. + */ +@ExperimentalResourceApi @Composable -private fun Resource.rememberLoadingResource(fromByteArrayConverter: ByteArray.()->T): LoadState { - val state: MutableState> = remember(this) { mutableStateOf(LoadState.Loading()) } +fun Resource.rememberImageBitmap(): LoadState { + val state: MutableState> = remember(this) { mutableStateOf(LoadState.Loading()) } LaunchedEffect(this) { state.value = try { - LoadState.Success(readBytes().fromByteArrayConverter()) + LoadState.Success(readBytes().toImageBitmap()) } catch (e: Exception) { LoadState.Error(e) } @@ -34,41 +28,13 @@ private fun Resource.rememberLoadingResource(fromByteArrayConverter: ByteArr } /** - * Get and remember resource. While loading and if resource not exists result will be null. - */ -@ExperimentalResourceApi -@Composable -fun Resource.rememberImageBitmap(): LoadState = - rememberLoadingResource { toImageBitmap() } - -/** - * Get and remember resource. While loading and if resource not exists result will be null. + * return current ImageBitmap or return empty while loading */ @ExperimentalResourceApi -@Composable -fun Resource.rememberImageVector(density: Density): LoadState = - rememberLoadingResource { toImageVector(density) } - -private fun LoadState.orEmpty(emptyValue: T): T = when (this) { - is LoadState.Loading -> emptyValue +fun LoadState.orEmpty(): ImageBitmap = when (this) { + is LoadState.Loading -> emptyImageBitmap is LoadState.Success -> this.value - is LoadState.Error -> emptyValue + is LoadState.Error -> emptyImageBitmap } -/** - * return current ImageBitmap or return empty while loading - */ -@ExperimentalResourceApi -fun LoadState.orEmpty(): ImageBitmap = orEmpty(emptyImageBitmap) - -/** - * return current ImageVector or return empty while loading - */ -@ExperimentalResourceApi -fun LoadState.orEmpty(): ImageVector = orEmpty(emptyImageVector) - internal expect fun ByteArray.toImageBitmap(): ImageBitmap - -internal expect fun parseXML(byteArray: ByteArray): Element - -internal fun ByteArray.toImageVector(density: Density): ImageVector = parseXML(this).parseVectorRoot(density) diff --git a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/vector/ValueParsers.kt b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/vector/ValueParsers.kt deleted file mode 100644 index cf065f4bfc..0000000000 --- a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/vector/ValueParsers.kt +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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 org.jetbrains.compose.resources.vector - -import androidx.compose.ui.graphics.PathFillType -import androidx.compose.ui.graphics.StrokeCap -import androidx.compose.ui.graphics.StrokeJoin -import androidx.compose.ui.graphics.TileMode -import androidx.compose.ui.unit.Density -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.dp - -private const val ALPHA_MASK = 0xFF000000.toInt() - -// parseColorValue is copied from Android: -// https://cs.android.com/android-studio/platform/tools/base/+/05fadd8cb2aaafb77da02048c7a240b2147ff293:sdk-common/src/main/java/com/android/ide/common/vectordrawable/VdUtil.kt;l=58 -/** - * Parses a color value in #AARRGGBB format. - * - * @param color the color value string - * @return the integer color value - */ -internal fun parseColorValue(color: String): Int { - require(color.startsWith("#")) { "Invalid color value $color" } - - return when (color.length) { - 7 -> { - // #RRGGBB - color.substring(1).toUInt(16).toInt() or ALPHA_MASK - } - 9 -> { - // #AARRGGBB - color.substring(1).toUInt(16).toInt() - } - 4 -> { - // #RGB - val v = color.substring(1).toUInt(16).toInt() - var k = (v shr 8 and 0xF) * 0x110000 - k = k or (v shr 4 and 0xF) * 0x1100 - k = k or (v and 0xF) * 0x11 - k or ALPHA_MASK - } - 5 -> { - // #ARGB - val v = color.substring(1).toUInt(16).toInt() - var k = (v shr 12 and 0xF) * 0x11000000 - k = k or (v shr 8 and 0xF) * 0x110000 - k = k or (v shr 4 and 0xF) * 0x1100 - k = k or (v and 0xF) * 0x11 - k or ALPHA_MASK - } - else -> ALPHA_MASK - } -} - -internal fun parseFillType(fillType: String): PathFillType = when (fillType) { - "nonZero" -> PathFillType.NonZero - "evenOdd" -> PathFillType.EvenOdd - else -> throw UnsupportedOperationException("unknown fillType: $fillType") -} - -internal fun parseStrokeCap(strokeCap: String): StrokeCap = when (strokeCap) { - "butt" -> StrokeCap.Butt - "round" -> StrokeCap.Round - "square" -> StrokeCap.Square - else -> throw UnsupportedOperationException("unknown strokeCap: $strokeCap") -} - -internal fun parseStrokeJoin(strokeJoin: String): StrokeJoin = when (strokeJoin) { - "miter" -> StrokeJoin.Miter - "round" -> StrokeJoin.Round - "bevel" -> StrokeJoin.Bevel - else -> throw UnsupportedOperationException("unknown strokeJoin: $strokeJoin") -} - -internal fun parseTileMode(tileMode: String): TileMode = when (tileMode) { - "clamp" -> TileMode.Clamp - "repeated" -> TileMode.Repeated - "mirror" -> TileMode.Mirror - else -> throw throw UnsupportedOperationException("unknown tileMode: $tileMode") -} - -internal fun String?.parseDp(density: Density): Dp = with(density) { - return when { - this@parseDp == null -> 0f.dp - endsWith("dp") -> removeSuffix("dp").toFloat().dp - endsWith("px") -> removeSuffix("px").toFloat().toDp() - else -> throw UnsupportedOperationException("value should ends with dp or px") - } -} diff --git a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/vector/XmlVectorParser.kt b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/vector/XmlVectorParser.kt deleted file mode 100644 index c5f142cbaa..0000000000 --- a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/vector/XmlVectorParser.kt +++ /dev/null @@ -1,276 +0,0 @@ -/* - * 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 org.jetbrains.compose.resources.vector - -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.PathFillType -import androidx.compose.ui.graphics.SolidColor -import androidx.compose.ui.graphics.StrokeCap -import androidx.compose.ui.graphics.StrokeJoin -import androidx.compose.ui.graphics.TileMode -import androidx.compose.ui.graphics.vector.DefaultPivotX -import androidx.compose.ui.graphics.vector.DefaultPivotY -import androidx.compose.ui.graphics.vector.DefaultRotation -import androidx.compose.ui.graphics.vector.DefaultScaleX -import androidx.compose.ui.graphics.vector.DefaultScaleY -import androidx.compose.ui.graphics.vector.DefaultTranslationX -import androidx.compose.ui.graphics.vector.DefaultTranslationY -import androidx.compose.ui.graphics.vector.EmptyPath -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.graphics.vector.addPathNodes -import org.jetbrains.compose.resources.vector.BuildContext.Group -import androidx.compose.ui.unit.Density -import org.jetbrains.compose.resources.vector.xmldom.* - - -// Parsing logic is the same as in Android implementation -// (compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/graphics/vector/compat/XmlVectorParser.kt) -// -// Except there is no support for linking with external resources -// (for example, we can't reference to color defined in another file) -// -// Specification: -// https://developer.android.com/reference/android/graphics/drawable/VectorDrawable - -private const val ANDROID_NS = "http://schemas.android.com/apk/res/android" -private const val AAPT_NS = "http://schemas.android.com/aapt" - -private class BuildContext { - val currentGroups = mutableListOf() - - enum class Group { - /** - * Group that exists in xml file - */ - Real, - - /** - * Group that doesn't exist in xml file. We add it manually when we see node. - * It will be automatically popped when the real group will be popped. - */ - Virtual - } -} - -fun Element.parseVectorRoot(density: Density): ImageVector { - val context = BuildContext() - val builder = ImageVector.Builder( - defaultWidth = attributeOrNull(ANDROID_NS, "width").parseDp(density), - defaultHeight = attributeOrNull(ANDROID_NS, "height").parseDp(density), - viewportWidth = attributeOrNull(ANDROID_NS, "viewportWidth")?.toFloat() ?: 0f, - viewportHeight = attributeOrNull(ANDROID_NS, "viewportHeight")?.toFloat() ?: 0f - ) - parseVectorNodes(builder, context) - return builder.build() -} - -private fun Element.parseVectorNodes(builder: ImageVector.Builder, context: BuildContext) { - childrenSequence - .filterIsInstance() - .forEach { - it.parseVectorNode(builder, context) - } -} - -private fun Element.parseVectorNode(builder: ImageVector.Builder, context: BuildContext) { - when (nodeName) { - "path" -> parsePath(builder) - "clip-path" -> parseClipPath(builder, context) - "group" -> parseGroup(builder, context) - } -} - -private fun Element.parsePath(builder: ImageVector.Builder) { - builder.addPath( - pathData = addPathNodes(attributeOrNull(ANDROID_NS, "pathData")), - pathFillType = attributeOrNull(ANDROID_NS, "fillType") - ?.let(::parseFillType) ?: PathFillType.NonZero, - name = attributeOrNull(ANDROID_NS, "name") ?: "", - fill = attributeOrNull(ANDROID_NS, "fillColor")?.let(::parseStringBrush) - ?: apptAttr(ANDROID_NS, "fillColor")?.let(Element::parseElementBrush), - fillAlpha = attributeOrNull(ANDROID_NS, "fillAlpha")?.toFloat() ?: 1.0f, - stroke = attributeOrNull(ANDROID_NS, "strokeColor")?.let(::parseStringBrush) - ?: apptAttr(ANDROID_NS, "strokeColor")?.let(Element::parseElementBrush), - strokeAlpha = attributeOrNull(ANDROID_NS, "strokeAlpha")?.toFloat() ?: 1.0f, - strokeLineWidth = attributeOrNull(ANDROID_NS, "strokeWidth")?.toFloat() ?: 1.0f, - strokeLineCap = attributeOrNull(ANDROID_NS, "strokeLineCap") - ?.let(::parseStrokeCap) ?: StrokeCap.Butt, - strokeLineJoin = attributeOrNull(ANDROID_NS, "strokeLineJoin") - ?.let(::parseStrokeJoin) ?: StrokeJoin.Miter, - strokeLineMiter = attributeOrNull(ANDROID_NS, "strokeMiterLimit")?.toFloat() ?: 1.0f, - trimPathStart = attributeOrNull(ANDROID_NS, "trimPathStart")?.toFloat() ?: 0.0f, - trimPathEnd = attributeOrNull(ANDROID_NS, "trimPathEnd")?.toFloat() ?: 1.0f, - trimPathOffset = attributeOrNull(ANDROID_NS, "trimPathOffset")?.toFloat() ?: 0.0f - ) -} - -private fun Element.parseClipPath(builder: ImageVector.Builder, context: BuildContext) { - builder.addGroup( - name = attributeOrNull(ANDROID_NS, "name") ?: "", - clipPathData = addPathNodes(attributeOrNull(ANDROID_NS, "pathData")) - ) - context.currentGroups.add(Group.Virtual) -} - -private fun Element.parseGroup(builder: ImageVector.Builder, context: BuildContext) { - builder.addGroup( - attributeOrNull(ANDROID_NS, "name") ?: "", - attributeOrNull(ANDROID_NS, "rotation")?.toFloat() ?: DefaultRotation, - attributeOrNull(ANDROID_NS, "pivotX")?.toFloat() ?: DefaultPivotX, - attributeOrNull(ANDROID_NS, "pivotY")?.toFloat() ?: DefaultPivotY, - attributeOrNull(ANDROID_NS, "scaleX")?.toFloat() ?: DefaultScaleX, - attributeOrNull(ANDROID_NS, "scaleY")?.toFloat() ?: DefaultScaleY, - attributeOrNull(ANDROID_NS, "translateX")?.toFloat() ?: DefaultTranslationX, - attributeOrNull(ANDROID_NS, "translateY")?.toFloat() ?: DefaultTranslationY, - EmptyPath - ) - context.currentGroups.add(Group.Real) - - parseVectorNodes(builder, context) - - do { - val removedGroup = context.currentGroups.removeLastOrNull() - builder.clearGroup() - } while (removedGroup == Group.Virtual) -} - -private fun parseStringBrush(str: String) = SolidColor(Color(parseColorValue(str))) - -private fun Element.parseElementBrush(): Brush? = - childrenSequence - .filterIsInstance() - .find { it.nodeName == "gradient" } - ?.parseGradient() - -private fun Element.parseGradient(): Brush? { - return when (attributeOrNull(ANDROID_NS, "type")) { - "linear" -> parseLinearGradient() - "radial" -> parseRadialGradient() - "sweep" -> parseSweepGradient() - else -> null - } -} - -@Suppress("CHANGING_ARGUMENTS_EXECUTION_ORDER_FOR_NAMED_VARARGS") -private fun Element.parseLinearGradient() = Brush.linearGradient( - colorStops = parseColorStops(), - start = Offset( - attributeOrNull(ANDROID_NS, "startX")?.toFloat() ?: 0f, - attributeOrNull(ANDROID_NS, "startY")?.toFloat() ?: 0f - ), - end = Offset( - attributeOrNull(ANDROID_NS, "endX")?.toFloat() ?: 0f, - attributeOrNull(ANDROID_NS, "endY")?.toFloat() ?: 0f - ), - tileMode = attributeOrNull(ANDROID_NS, "tileMode")?.let(::parseTileMode) ?: TileMode.Clamp -) - -@Suppress("CHANGING_ARGUMENTS_EXECUTION_ORDER_FOR_NAMED_VARARGS") -private fun Element.parseRadialGradient() = Brush.radialGradient( - colorStops = parseColorStops(), - center = Offset( - attributeOrNull(ANDROID_NS, "centerX")?.toFloat() ?: 0f, - attributeOrNull(ANDROID_NS, "centerY")?.toFloat() ?: 0f - ), - radius = attributeOrNull(ANDROID_NS, "gradientRadius")?.toFloat() ?: 0f, - tileMode = attributeOrNull(ANDROID_NS, "tileMode")?.let(::parseTileMode) ?: TileMode.Clamp -) - -@Suppress("CHANGING_ARGUMENTS_EXECUTION_ORDER_FOR_NAMED_VARARGS") -private fun Element.parseSweepGradient() = Brush.sweepGradient( - colorStops = parseColorStops(), - center = Offset( - attributeOrNull(ANDROID_NS, "centerX")?.toFloat() ?: 0f, - attributeOrNull(ANDROID_NS, "centerY")?.toFloat() ?: 0f, - ) -) - -private fun Element.parseColorStops(): Array> { - val items = childrenSequence - .filterIsInstance() - .filter { it.nodeName == "item" } - .toList() - - val colorStops = items.mapIndexedNotNullTo(mutableListOf()) { index, item -> - item.parseColorStop(defaultOffset = index.toFloat() / items.lastIndex.coerceAtLeast(1)) - } - - if (colorStops.isEmpty()) { - val startColor = attributeOrNull(ANDROID_NS, "startColor")?.let(::parseColorValue) - val centerColor = attributeOrNull(ANDROID_NS, "centerColor")?.let(::parseColorValue) - val endColor = attributeOrNull(ANDROID_NS, "endColor")?.let(::parseColorValue) - - if (startColor != null) { - colorStops.add(0f to Color(startColor)) - } - if (centerColor != null) { - colorStops.add(0.5f to Color(centerColor)) - } - if (endColor != null) { - colorStops.add(1f to Color(endColor)) - } - } - - return colorStops.toTypedArray() -} - -private fun Element.parseColorStop(defaultOffset: Float): Pair? { - val offset = attributeOrNull(ANDROID_NS, "offset")?.toFloat() ?: defaultOffset - val color = attributeOrNull(ANDROID_NS, "color")?.let(::parseColorValue) ?: return null - return offset to Color(color) -} - -private fun Element.attributeOrNull(namespace: String, name: String): String? { - val value = getAttributeNS(namespace, name) - return if (value.isNotBlank()) value else null -} - -/** - * Attribute of an element can be represented as a separate child: - * - * - * - * - * - * - * - * instead of: - * - * - */ -private fun Element.apptAttr( - namespace: String, - name: String -): Element? { - val prefix = lookupPrefix(namespace) - return childrenSequence - .filterIsInstance() - .find { - it.namespaceURI == AAPT_NS && it.localName == "attr" && - it.getAttribute("name") == "$prefix:$name" - } -} - -private val Element.childrenSequence get() = sequence { - for (i in 0 until childNodes.length) { - yield(childNodes.item(i)) - } -} diff --git a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/vector/xmldom/Element.kt b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/vector/xmldom/Element.kt deleted file mode 100644 index 1bd29a91c6..0000000000 --- a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/vector/xmldom/Element.kt +++ /dev/null @@ -1,11 +0,0 @@ -package org.jetbrains.compose.resources.vector.xmldom - -/** - * XML DOM Element. - */ -interface Element: Node { - - fun getAttributeNS(nameSpaceURI: String, localName: String): String - - fun getAttribute(name: String): String -} \ No newline at end of file diff --git a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/vector/xmldom/Node.kt b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/vector/xmldom/Node.kt deleted file mode 100644 index 88e0205cab..0000000000 --- a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/vector/xmldom/Node.kt +++ /dev/null @@ -1,14 +0,0 @@ -package org.jetbrains.compose.resources.vector.xmldom - -/** - * XML DOM Node. - */ -interface Node { - val nodeName: String - val localName: String - - val childNodes: NodeList - val namespaceURI: String - - fun lookupPrefix(namespaceURI: String): String -} \ No newline at end of file diff --git a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/vector/xmldom/NodeList.kt b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/vector/xmldom/NodeList.kt deleted file mode 100644 index 3883fad0ab..0000000000 --- a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/vector/xmldom/NodeList.kt +++ /dev/null @@ -1,10 +0,0 @@ -package org.jetbrains.compose.resources.vector.xmldom - -/** - * XML DOM Node list. - */ -interface NodeList { - fun item(i: Int): Node - - val length: Int -} \ No newline at end of file diff --git a/components/resources/library/src/iosMain/kotlin/org/jetbrains/compose/resources/Resource.ios.kt b/components/resources/library/src/iosMain/kotlin/org/jetbrains/compose/resources/Resource.ios.kt index 6e39c00bc0..c081555e1b 100644 --- a/components/resources/library/src/iosMain/kotlin/org/jetbrains/compose/resources/Resource.ios.kt +++ b/components/resources/library/src/iosMain/kotlin/org/jetbrains/compose/resources/Resource.ios.kt @@ -5,10 +5,9 @@ package org.jetbrains.compose.resources -import org.jetbrains.compose.resources.vector.xmldom.Element + import kotlinx.cinterop.addressOf import kotlinx.cinterop.usePinned -import org.jetbrains.compose.resources.vector.xmldom.parse import platform.Foundation.NSBundle import platform.Foundation.NSData import platform.Foundation.NSFileManager @@ -36,5 +35,3 @@ private class UIKitResourceImpl(path: String) : AbstractResourceImpl(path) { internal actual class MissingResourceException actual constructor(path: String) : Exception("Missing resource with path: $path") - -internal actual fun parseXML(byteArray: ByteArray): Element = parse(byteArray.decodeToString()) \ No newline at end of file diff --git a/components/resources/library/src/iosMain/kotlin/org/jetbrains/compose/resources/xmldom/DomXmlParser.kt b/components/resources/library/src/iosMain/kotlin/org/jetbrains/compose/resources/xmldom/DomXmlParser.kt deleted file mode 100644 index 1aff9bfdde..0000000000 --- a/components/resources/library/src/iosMain/kotlin/org/jetbrains/compose/resources/xmldom/DomXmlParser.kt +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2020-2021 JetBrains s.r.o. and respective authors and developers. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. - */ -package org.jetbrains.compose.resources.vector.xmldom - -import platform.Foundation.* -import platform.darwin.NSObject - -fun parse(xml: String): Element { - val parser = DomXmlParser() - NSXMLParser((xml as NSString).dataUsingEncoding(NSUTF8StringEncoding)!!).apply { - shouldReportNamespacePrefixes = true - shouldProcessNamespaces = true - delegate = parser - }.parse() - return parser.root!! -} - -class MalformedXMLException(message: String?) : Exception(message) - -private class ElementImpl(override val localName: String, - override val nodeName: String, - override val namespaceURI: String, - val prefixMap: Map, - val attributes: Map): Element { - - override val childNodes: NodeList - get() = object : NodeList { - override fun item(i: Int): Node { - return childs[i] - } - - override val length: Int - get() = childs.size - } - - - var childs = mutableListOf() - - override fun getAttributeNS(nameSpaceURI: String, localName: String): String { - val prefix = prefixMap[nameSpaceURI] - val attrKey = if (prefix == null) localName else "$prefix:$localName" - return getAttribute(attrKey) - } - - override fun getAttribute(name: String): String = attributes[name] as String? ?:"" - - override fun lookupPrefix(uri: String): String = prefixMap[uri]?:"" -} - -@Suppress("CONFLICTING_OVERLOADS") -private class DomXmlParser( - -) : NSObject(), NSXMLParserDelegateProtocol { - - val curPrefixMapInverted = mutableMapOf() - - var curPrefixMap: Map = emptyMap() - - val nodeStack = mutableListOf() - - var root: Element? = null - - override fun parser( - parser: NSXMLParser, - didStartElement: String, - namespaceURI: String?, - qualifiedName: String?, - attributes: Map - ) { - val node = ElementImpl(didStartElement, qualifiedName!!, namespaceURI?:"", - curPrefixMap, attributes) - - if (root == null) root = node - - if (!nodeStack.isEmpty()) - nodeStack.last().childs.add(node) - - nodeStack.add(node) - } - - override fun parser( - parser: NSXMLParser, - didEndElement: String, - namespaceURI: String?, - qualifiedName: String? - ) { - val node = nodeStack.removeLast() - assert(node.localName.equals(didEndElement)) - } - - override fun parser(parser: NSXMLParser, - didStartMappingPrefix: String, - toURI: String - ) { - curPrefixMapInverted.put(didStartMappingPrefix, toURI) - curPrefixMap = curPrefixMapInverted.entries.associateBy({ it.value }, { it.key }) - } - - override fun parser(parser: NSXMLParser, didEndMappingPrefix: String) { - curPrefixMapInverted.remove(didEndMappingPrefix) - curPrefixMap = curPrefixMapInverted.entries.associateBy({ it.value }, { it.key }) - } - - override fun parser(parser: NSXMLParser, validationErrorOccurred: NSError) { - throw MalformedXMLException("validation error occurred") - } - - override fun parser(parser: NSXMLParser, parseErrorOccurred: NSError) { - throw MalformedXMLException("parse error occurred") - } -} - diff --git a/components/resources/library/src/jsMain/kotlin/org/jetbrains/compose/resources/Resource.js.kt b/components/resources/library/src/jsMain/kotlin/org/jetbrains/compose/resources/Resource.js.kt index b05f8a49ad..e0a78a5193 100644 --- a/components/resources/library/src/jsMain/kotlin/org/jetbrains/compose/resources/Resource.js.kt +++ b/components/resources/library/src/jsMain/kotlin/org/jetbrains/compose/resources/Resource.js.kt @@ -5,7 +5,6 @@ package org.jetbrains.compose.resources -import org.jetbrains.compose.resources.vector.xmldom.Element import org.khronos.webgl.ArrayBuffer import org.khronos.webgl.Int8Array import org.w3c.xhr.ARRAYBUFFER @@ -43,7 +42,3 @@ private fun ArrayBuffer.toByteArray() = Int8Array(this, 0, byteLength).unsafeCas internal actual class MissingResourceException actual constructor(path: String) : Exception("Missing resource with path: $path") - -internal actual fun parseXML(byteArray: ByteArray): Element { - throw UnsupportedOperationException("XML Vector Drawables are not supported for Web target") -} \ No newline at end of file diff --git a/components/resources/library/src/jvmAndAndroidMain/kotlin/org/jetbrains/compose/resources/Resource.jvmandandroid.kt b/components/resources/library/src/jvmAndAndroidMain/kotlin/org/jetbrains/compose/resources/Resource.jvmandandroid.kt deleted file mode 100644 index f4866cc5a8..0000000000 --- a/components/resources/library/src/jvmAndAndroidMain/kotlin/org/jetbrains/compose/resources/Resource.jvmandandroid.kt +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2020-2022 JetBrains s.r.o. and respective authors and developers. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. - */ - -package org.jetbrains.compose.resources - -import org.jetbrains.compose.resources.vector.xmldom.Element -import org.jetbrains.compose.resources.vector.xmldom.ElementImpl -import org.xml.sax.InputSource -import java.io.ByteArrayInputStream -import javax.xml.parsers.DocumentBuilderFactory - -internal actual fun parseXML(byteArray: ByteArray): Element = - ElementImpl( - DocumentBuilderFactory - .newInstance().apply { - isNamespaceAware = true - } - .newDocumentBuilder() - .parse(InputSource(ByteArrayInputStream(byteArray))) - .documentElement) diff --git a/components/resources/library/src/jvmAndAndroidMain/kotlin/org/jetbrains/compose/resources/xmldom/ElementImpl.kt b/components/resources/library/src/jvmAndAndroidMain/kotlin/org/jetbrains/compose/resources/xmldom/ElementImpl.kt deleted file mode 100644 index a72eda6887..0000000000 --- a/components/resources/library/src/jvmAndAndroidMain/kotlin/org/jetbrains/compose/resources/xmldom/ElementImpl.kt +++ /dev/null @@ -1,10 +0,0 @@ -package org.jetbrains.compose.resources.vector.xmldom - -import org.w3c.dom.Element as DomElement - -class ElementImpl(val element: DomElement): NodeImpl(element), Element { - override fun getAttributeNS(nameSpaceURI: String, localName: String): String = - element.getAttributeNS(nameSpaceURI, localName) - - override fun getAttribute(name: String): String = element.getAttribute(name) -} \ No newline at end of file diff --git a/components/resources/library/src/jvmAndAndroidMain/kotlin/org/jetbrains/compose/resources/xmldom/NodeImpl.kt b/components/resources/library/src/jvmAndAndroidMain/kotlin/org/jetbrains/compose/resources/xmldom/NodeImpl.kt deleted file mode 100644 index fbafd4d499..0000000000 --- a/components/resources/library/src/jvmAndAndroidMain/kotlin/org/jetbrains/compose/resources/xmldom/NodeImpl.kt +++ /dev/null @@ -1,28 +0,0 @@ -package org.jetbrains.compose.resources.vector.xmldom - -import org.w3c.dom.Node as DomNode -import org.w3c.dom.Element as DomElement - -open class NodeImpl(val n: DomNode): Node { - override val nodeName: String - get() = n.nodeName - override val localName: String - get() = n.localName - override val childNodes: NodeList - get() = - object: NodeList { - override fun item(i: Int): Node { - val child = n.childNodes.item(i) - return if (child is DomElement) ElementImpl(child) else NodeImpl(child) - } - - override val length: Int = n.childNodes.length - - } - - override val namespaceURI: String - get() = n.namespaceURI - - override fun lookupPrefix(namespaceURI: String): String = n.lookupPrefix(namespaceURI) - -} \ No newline at end of file diff --git a/components/resources/library/src/macosMain/kotlin/org/jetbrains/compose/resources/Resource.macos.kt b/components/resources/library/src/macosMain/kotlin/org/jetbrains/compose/resources/Resource.macos.kt index c1dcf6ad30..fedc16c725 100644 --- a/components/resources/library/src/macosMain/kotlin/org/jetbrains/compose/resources/Resource.macos.kt +++ b/components/resources/library/src/macosMain/kotlin/org/jetbrains/compose/resources/Resource.macos.kt @@ -5,7 +5,6 @@ package org.jetbrains.compose.resources -import org.jetbrains.compose.resources.vector.xmldom.Element import kotlinx.cinterop.addressOf import kotlinx.cinterop.usePinned import platform.Foundation.NSData @@ -38,7 +37,3 @@ private class MacOSResourceImpl(path: String) : AbstractResourceImpl(path) { internal actual class MissingResourceException actual constructor(path: String) : Exception("Missing resource with path: $path") - -internal actual fun parseXML(byteArray: ByteArray): Element { - throw UnsupportedOperationException("XML Vector Drawables are not supported for MacOS target") -}