@@ -20,10 +20,12 @@ package com.neoapps.neolauncher.icons
2020
2121import android.content.Context
2222import android.graphics.Path
23+ import android.graphics.PathIterator
2324import android.graphics.PointF
2425import android.util.Log
2526import com.android.launcher3.R
2627import com.android.launcher3.Utilities
28+ import com.android.launcher3.shapes.IconShapeModel
2729
2830open class IconShape (
2931 private val topLeft : Corner ,
@@ -368,6 +370,47 @@ open class IconShape(
368370 }
369371 }
370372
373+ open fun toPathString (): String {
374+ val path = getMaskPath()
375+ return pathToSvgString(path)
376+ }
377+
378+ open fun getFolderRadiusRatio (): Float {
379+ val avgScale = (topLeft.scale.x + topLeft.scale.y +
380+ topRight.scale.x + topRight.scale.y +
381+ bottomLeft.scale.x + bottomLeft.scale.y +
382+ bottomRight.scale.x + bottomRight.scale.y) / 8f
383+ return avgScale
384+ }
385+
386+ open fun getShapeRadius (): Float {
387+ return when (this ) {
388+ is Circle -> 26f
389+ is Square -> 17.33f
390+ is SharpSquare -> 0f
391+ is RoundedSquare -> 20f
392+ is Squircle -> 26f
393+ is Sammy -> 26f
394+ is Teardrop -> 22f
395+ is Cylinder -> 24f
396+ is Cupertino -> 16f
397+ is Hexagon -> 15f
398+ is Octagon -> 18f
399+ is Egg -> 23f
400+ else -> 26f // Default for custom shapes
401+ }
402+ }
403+
404+ fun toIconShapeModel (key : String , titleId : Int ): IconShapeModel {
405+ return IconShapeModel (
406+ key = key,
407+ titleId = titleId,
408+ pathString = toPathString(),
409+ folderRadiusRatio = getFolderRadiusRatio(),
410+ shapeRadius = getShapeRadius()
411+ )
412+ }
413+
371414 companion object {
372415
373416 fun fromString (context : Context , value : String ): IconShape {
@@ -380,20 +423,21 @@ open class IconShape(
380423 }
381424
382425 fun fromString (value : String ): IconShape = when (value) {
383- " circle" -> Circle
384- " square" -> Square
385- " sharpSquare" -> SharpSquare
426+ // TODO add constants instead of string literals
427+ " circle" -> Circle
428+ " square" -> Square
429+ " sharpSquare" -> SharpSquare
386430 " roundedSquare" -> RoundedSquare
387- " squircle" -> Squircle
388- " sammy" -> Sammy
389- " teardrop" -> Teardrop
390- " cylinder" -> Cylinder
391- " cupertino" -> Cupertino
392- " hexagon" -> Hexagon
393- " octagon" -> Octagon
394- " egg" -> Egg
395- " " -> Circle
396- else -> runCatching { parseCustomShape(value) }.getOrDefault(Circle )
431+ " squircle" -> Squircle
432+ " sammy" -> Sammy
433+ " teardrop" -> Teardrop
434+ " cylinder" -> Cylinder
435+ " cupertino" -> Cupertino
436+ " hexagon" -> Hexagon
437+ " octagon" -> Octagon
438+ " egg" -> Egg
439+ " " -> Circle
440+ else -> runCatching { parseCustomShape(value) }.getOrDefault(Circle )
397441 }
398442
399443 private fun parseCustomShape (value : String ): IconShape {
@@ -408,6 +452,59 @@ open class IconShape(
408452 )
409453 }
410454
455+ private fun pathToSvgString (path : Path ): String {
456+ return buildString {
457+ val points = FloatArray (8 )
458+ val iterator = path.pathIterator
459+
460+ while (iterator.hasNext()) {
461+ when (iterator.next(points, 0 )) {
462+ PathIterator .VERB_MOVE -> {
463+ append(" M${points[0 ]} ${points[1 ]} " )
464+ }
465+
466+ PathIterator .VERB_LINE -> {
467+ append(" L${points[0 ]} ${points[1 ]} " )
468+ }
469+
470+ PathIterator .VERB_CONIC -> {
471+ append(" C${points[0 ]} ${points[1 ]} " )
472+ append(" ${points[2 ]} ${points[3 ]} " )
473+ append(" ${points[4 ]} ${points[5 ]} " )
474+ }
475+
476+ PathIterator .VERB_QUAD -> {
477+ append(" Q${points[0 ]} ${points[1 ]} " )
478+ append(" ${points[2 ]} ${points[3 ]} " )
479+ }
480+
481+ PathIterator .VERB_CLOSE -> append(" Z " )
482+ }
483+ }
484+ }.trim()
485+ }
486+
487+ fun getAllShapeModels (): Array <IconShapeModel > {
488+ return arrayOf(
489+ // TODO use constants instead of string literals for keys
490+ Circle .toIconShapeModel(" circle" , R .string.circle_shape_title),
491+ Square .toIconShapeModel(" square" , R .string.square_shape_title),
492+ SharpSquare .toIconShapeModel(" sharp_square" , R .string.sharp_square_shape_title),
493+ RoundedSquare .toIconShapeModel(
494+ " rounded_square" ,
495+ R .string.rounded_square_shape_title
496+ ),
497+ Squircle .toIconShapeModel(" squircle" , R .string.squircle_shape_title),
498+ Sammy .toIconShapeModel(" sammy" , R .string.sammy_shape_title),
499+ Teardrop .toIconShapeModel(" teardrop" , R .string.teardrop_shape_title),
500+ Cylinder .toIconShapeModel(" cylinder" , R .string.cylinder_shape_title),
501+ Cupertino .toIconShapeModel(" cupertino" , R .string.cupertino_shape_title),
502+ Hexagon .toIconShapeModel(" hexagon" , R .string.hexagon_shape_title),
503+ Octagon .toIconShapeModel(" octagon" , R .string.octagon_shape_title),
504+ Egg .toIconShapeModel(" egg" , R .string.egg_shape_title)
505+ )
506+ }
507+
411508 fun isCustomShape (iconShape : IconShape ): Boolean {
412509 return try {
413510 parseCustomShape(iconShape.toString())
0 commit comments