1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
package jp.orgflow.bridge
import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.json.Json
interface HostDocumentIo {
suspend fun importSlides(bytes: ByteArray): List<SlideSpecData>
suspend fun renderSlidePng(bytes: ByteArray, index: Int): ByteArray?
suspend fun exportPptx(slides: List<SlideSpecData>): ByteArray
suspend fun importXlsxGrid(bytes: ByteArray, sheet: Int): List<List<String>>
suspend fun exportXlsxGrid(rows: List<List<String>>, formulas: Map<String, String>): ByteArray
}
@Serializable
data class SlideSpecData(
val id: String,
val title: String = "",
val backgroundArgb: Long? = null,
val boxes: List<SlideSpecBox> = emptyList(),
val images: Map<String, ByteArray> = emptyMap(),
val notes: String = "",
) {
override fun equals(other: Any?): Boolean =
other is SlideSpecData &&
id == other.id &&
title == other.title &&
backgroundArgb == other.backgroundArgb &&
boxes == other.boxes &&
images.size == other.images.size &&
images.all { (key, value) -> other.images[key]?.contentEquals(value) == true } &&
notes == other.notes
override fun hashCode(): Int {
var result = id.hashCode()
result = 31 * result + title.hashCode()
result = 31 * result + (backgroundArgb?.hashCode() ?: 0)
result = 31 * result + boxes.hashCode()
result = 31 * result + images.entries.fold(0) { acc, entry -> 31 * acc + entry.key.hashCode() * 31 + entry.value.contentHashCode() }
result = 31 * result + notes.hashCode()
return result
}
companion object {
const val WIDTH_PT = 720.0
const val HEIGHT_PT = 405.0
}
}
@Serializable
enum class SlideSpecBoxKind {
TEXT,
IMAGE,
TABLE,
}
@Serializable
data class SlideSpecBox(
val kind: SlideSpecBoxKind,
val xPt: Double,
val yPt: Double,
val widthPt: Double,
val heightPt: Double,
val textRuns: List<SlideSpecTextRun> = emptyList(),
val imageRef: String? = null,
val tableCells: List<List<String>> = emptyList(),
)
@Serializable
data class SlideSpecTextRun(
val text: String,
val bold: Boolean = false,
val italic: Boolean = false,
val sizePt: Double? = null,
val colorArgb: Long? = null,
)
object SlideSpecCodec {
private val json = Json { ignoreUnknownKeys = true }
fun encode(slides: List<SlideSpecData>): String =
json.encodeToString(ListSerializer(SlideSpecData.serializer()), slides)
fun decode(text: String): List<SlideSpecData> =
json.decodeFromString(ListSerializer(SlideSpecData.serializer()), text)
}
|