Skip to content

Commit e0974d3

Browse files
committed
Pull request #80: [HWG] Adding switch between chinese and english.
Merge in SDK/iink_sdk-additional-examples-android from hwg-chinese to master * commit 'f7e3fdf5c71354ce776cfb7aec3bd7ce17117524': [HWG] Update profile preview spinner style [HWG] Adding chinese profile pictures [HWG] Let iink handle spaces. [HWG] Crash fix [HWG] Add user spaces [HWG] Switch from predifined profile enum to index [HWG] Fixed gesture recognition [HWG] Disabling shape to improve chinese recognition [HWG] Improving profile list display [HWG] Only 10 profiles for chinese [HWG] Adding chinese res download [HWG] Updating conf [HWG] Adding reset random seed [HWG] Default text size to 4 in chinese [HWG] Fixing chinese profile numbering [HWG] Safer gesture disabling [HWG] Recognition should be in chinese now. [HWG] Menu with numbers for chinese profile. [HWG] Adding switch between chinese and english.
2 parents 9a3dbb8 + f7e3fdf commit e0974d3

File tree

19 files changed

+986
-57
lines changed

19 files changed

+986
-57
lines changed

samples/hwgeneration/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ plugins {
33
id 'kotlin-android'
44
}
55

6+
ext.additionalLanguages = ["zh_CN"]
7+
68
android {
79
namespace 'com.myscript.iink.samples.hwgeneration'
810

samples/hwgeneration/src/main/assets/parts/interactivity.json

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,20 @@
22
"raw-content": {
33
"session-time": 100,
44
"classification": {
5-
"types": [ "text", "shape", "drawing" ]
5+
"types": [ "text", "drawing" ]
66
},
77
"recognition": {
8-
"types": [ "text", "shape", "math" ]
8+
"types": [ "text" ]
99
},
1010
"convert": {
1111
"shape-on-hold": true,
12-
"types": [ "text", "shape", "math" ]
13-
},
14-
"shape": {
15-
"snap-axis": [ "triangle", "rectangle", "rhombus", "parallelogram", "ellipse" ]
12+
"types": [ "text" ]
1613
},
1714
"eraser": {
1815
"erase-precisely": false,
1916
"dynamic-radius": true
2017
},
2118
"auto-connection": true,
22-
"interactive-blocks": {
23-
"feedback": [ "math" ]
24-
},
2519
"pen": {
2620
"gestures": [ "scratch-out", "strike-through", "surround", "long-press" ]
2721
},

samples/hwgeneration/src/main/java/com/myscript/iink/samples/hwgeneration/EditorViewModel.kt

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,13 @@ class EditorViewModel(application: Application) : AndroidViewModel(application)
107107
override fun onJoin(editor: Editor, tool: PointerTool?, gestureStrokeId: String, before: NativeObjectHandle<ContentSelection>, after: NativeObjectHandle<ContentSelection>): GestureAction = GestureAction.APPLY_GESTURE
108108
override fun onInsert(editor: Editor, tool: PointerTool?, gestureStrokeId: String, before: NativeObjectHandle<ContentSelection>, after: NativeObjectHandle<ContentSelection>): GestureAction = GestureAction.APPLY_GESTURE
109109
override fun onStrikethrough(editor: Editor, tool: PointerTool?, gestureStrokeId: String, selection: NativeObjectHandle<ContentSelection>): GestureAction = GestureAction.APPLY_GESTURE
110-
override fun onScratch(editor: Editor, tool: PointerTool?, gestureStrokeId: String, selection: NativeObjectHandle<ContentSelection>): GestureAction = GestureAction.APPLY_GESTURE
110+
override fun onScratch(editor: Editor, tool: PointerTool?, gestureStrokeId: String, selection: NativeObjectHandle<ContentSelection>): GestureAction {
111+
return if (isWriting.value == true) {
112+
GestureAction.IGNORE
113+
} else {
114+
GestureAction.APPLY_GESTURE
115+
}
116+
}
111117
}
112118

113119
private var contentPackage: ContentPackage? = null
@@ -153,6 +159,9 @@ class EditorViewModel(application: Application) : AndroidViewModel(application)
153159

154160
val configuration = context.assets.open("parts/interactivity.json").bufferedReader().use(Reader::readText)
155161
editor.configuration.inject(configuration)
162+
163+
editor.configuration.setString("lang", "zh_CN")
164+
156165
editor.part = contentPart
157166
editor.setGestureHandler(gestureHandler)
158167

@@ -205,6 +214,7 @@ class EditorViewModel(application: Application) : AndroidViewModel(application)
205214
}
206215

207216
fun setSelectionMode(enabled: Boolean) {
217+
editor?.waitForIdle()
208218
if (enabled) {
209219
editor?.toolController?.setToolForType(PointerType.PEN, PointerTool.SELECTOR)
210220
} else {
@@ -236,9 +246,6 @@ class EditorViewModel(application: Application) : AndroidViewModel(application)
236246
if (_isWriting.value == true) return
237247

238248
viewModelScope.launch(Dispatchers.Default) {
239-
val previousGestureConf = editor.configuration.getBoolean("gesture.enable")
240-
editor.configuration.setBoolean("gesture.enable", false)
241-
242249
setSelectionMode(false)
243250

244251
withContext(Dispatchers.Main) {
@@ -279,8 +286,6 @@ class EditorViewModel(application: Application) : AndroidViewModel(application)
279286
}
280287
}
281288

282-
editor.configuration.setBoolean("gesture.enable", previousGestureConf)
283-
284289
withContext(Dispatchers.Main) {
285290
_isWriting.value = false
286291
}

samples/hwgeneration/src/main/java/com/myscript/iink/samples/hwgeneration/GenerationViewModel.kt

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import com.myscript.iink.HandwritingResult
1717
import com.myscript.iink.IHandwritingGeneratorListener
1818
import com.myscript.iink.MimeType
1919
import com.myscript.iink.PointerEvent
20-
import com.myscript.iink.PredefinedHandwritingProfileId
2120
import com.myscript.iink.graphics.Transform
2221
import com.myscript.iink.samples.hwgeneration.None.word
2322
import kotlinx.coroutines.Dispatchers
@@ -40,23 +39,28 @@ data class Message(
4039
}
4140

4241
data class GenerationProfile(
43-
val id: PredefinedHandwritingProfileId = PredefinedHandwritingProfileId.DEFAULT,
42+
val index: Int = 0,
4443
val profilePath: String? = null) {
4544

4645
companion object {
47-
fun fromId(id: PredefinedHandwritingProfileId): GenerationProfile {
46+
fun fromId(id: Int): GenerationProfile {
4847
return GenerationProfile(id, null)
4948
}
5049

5150
fun fromPath(path: String): GenerationProfile {
52-
return GenerationProfile(PredefinedHandwritingProfileId.DEFAULT, path)
51+
return GenerationProfile(-1, path)
5352
}
5453
}
5554
}
5655

56+
enum class HWGLanguage {
57+
ENGLISH,
58+
CHINESE
59+
}
60+
5761
class GenerationViewModel(application: Application, private val engine: Engine) : AndroidViewModel(application) {
5862

59-
private val generator: HandwritingGenerator
63+
private var generator: HandwritingGenerator? = null
6064

6165
private val _isGenerating = MutableLiveData(false)
6266
val isGenerating: LiveData<Boolean>
@@ -70,34 +74,60 @@ class GenerationViewModel(application: Application, private val engine: Engine)
7074
val hwrResults: LiveData<List<HWRResult>>
7175
get() = _hwrResults
7276

73-
private var _message = MutableLiveData<Message?>(null)
77+
private val _message = MutableLiveData<Message?>(null)
7478
val message: LiveData<Message?>
7579
get() = _message
7680

81+
private val _language = MutableLiveData(DEFAULT_LANGUAGE)
82+
val language: LiveData<HWGLanguage>
83+
get() = _language
84+
7785
init {
7886
_isGenerating.value = false
7987

80-
generator = engine.createHandwritingGenerator()
88+
setLanguage(DEFAULT_LANGUAGE)
8189
}
8290

8391
private interface HWResultListener {
8492
fun onResult(result: HWRResult)
8593
}
8694

95+
fun setLanguage(language: HWGLanguage) {
96+
if (generator != null && _language.value == language) return
97+
98+
generator?.cancel()
99+
100+
engine.configuration.apply {
101+
when (language) {
102+
HWGLanguage.ENGLISH -> setString("handwriting-generation.init.resource","en-hw-gen.res")
103+
HWGLanguage.CHINESE -> setString("handwriting-generation.init.resource","zh-hw-gen.res")
104+
}
105+
}
106+
generator = engine.createHandwritingGenerator()
107+
108+
viewModelScope.launch(Dispatchers.Main) {
109+
_language.value = language
110+
}
111+
}
112+
87113
fun cancel() {
88-
generator.cancel()
114+
generator?.cancel()
89115
viewModelScope.launch(Dispatchers.Main) {
90116
_isGenerating.value = false
91117
_hwrResults.value = emptyList()
92118
}
93119
}
94120

95121
fun getProfiles(): List<GenerationProfile> {
122+
val generator = generator ?: return emptyList()
123+
96124
val userProfiles = File(getApplication<Application>().filesDir, PROFILE_FOLDER).listFiles()?.map { file ->
97125
GenerationProfile.fromPath(file.absolutePath)
98126
} ?: emptyList()
99127

100-
val predefinedProfiles = PredefinedHandwritingProfileId.entries.toList().map {
128+
var predefinedProfiles = generator.createHandwritingProfileBuilder().predefinedProfileCount.let { count ->
129+
(0 until count).toList()
130+
}.map {
101131
GenerationProfile.fromId(it)
102132
}
103133

@@ -113,6 +143,8 @@ class GenerationViewModel(application: Application, private val engine: Engine)
113143
}
114144

115145
private fun buildProfileInternal(selection: ContentSelection? = null, iinkFile: File? = null) {
146+
val generator = generator ?: return
147+
116148
viewModelScope.launch(Dispatchers.Main) {
117149
_isProfileBuilding.value = true
118150

@@ -147,14 +179,14 @@ class GenerationViewModel(application: Application, private val engine: Engine)
147179
}
148180
}
149181

150-
fun generateHandwriting(inputSentence: String, generationProfile: GenerationProfile, inputTextSize: Float, inputX: Float, inputY: Float, width: Float, transform: Transform) {
182+
fun generateHandwriting(inputSentence: String, generationProfile: GenerationProfile, inputTextSize: Float, inputX: Float, inputY: Float, width: Float, transform: Transform, forceRandomSeed: Boolean = false) {
151183
if (inputSentence.isEmpty()) return
152184

153185
viewModelScope.launch(Dispatchers.Main) {
154186
_isGenerating.value = true
155187

156188
withContext(Dispatchers.IO) {
157-
generate(inputSentence, generationProfile, inputTextSize, inputX, inputY, width, transform, object : HWResultListener {
189+
generate(inputSentence, generationProfile, inputTextSize, inputX, inputY, width, transform, forceRandomSeed, object : HWResultListener {
158190
override fun onResult(result: HWRResult) {
159191
viewModelScope.launch(Dispatchers.Main) {
160192
val previousList: MutableList<HWRResult> = _hwrResults.value?.toMutableList() ?: mutableListOf()
@@ -168,20 +200,22 @@ class GenerationViewModel(application: Application, private val engine: Engine)
168200
}
169201
}
170202

171-
private fun generate(sentence: String, generationProfile: GenerationProfile, textSize: Float, xOffset: Float, yOffset: Float, width: Float, transform: Transform, listener: HWResultListener): HWRResult {
203+
private fun generate(sentence: String, generationProfile: GenerationProfile, textSize: Float, xOffset: Float, yOffset: Float, width: Float, transform: Transform, forceRandomSeed: Boolean, listener: HWResultListener): HWRResult {
204+
val generator = generator ?: return None
205+
172206
val builder = generator.createHandwritingProfileBuilder()
173207

174208
val profile = if (generationProfile.profilePath != null && File(generationProfile.profilePath).exists()) {
175209
builder.load(generationProfile.profilePath)
176210
} else {
177-
builder.createFromId(generationProfile.id)
211+
builder.getPredefinedProfileAt(generationProfile.index)
178212
}
179213

180214
val indexLock = Any()
181215
var currentPointerEventIndex = 0
182216
var wordIndex = 0
183217

184-
val words = sentence.split(" ").filter { it.isNotEmpty() }
218+
val words = sentence.split(" ").map { "$it " }
185219

186220
generator.setListener(object: IHandwritingGeneratorListener {
187221
override fun onPartialResult(generator: HandwritingGenerator, result: HandwritingResult) {
@@ -201,7 +235,9 @@ class GenerationViewModel(application: Application, private val engine: Engine)
201235
})
202236

203237
generator.start("Text", profile, engine.createParameterSet().apply {
204-
setBoolean("handwriting-generation.session.force-new-line", false)
238+
setBoolean("handwriting-generation.session.preserve-new-line", language.value != HWGLanguage.CHINESE)
239+
240+
setNumber("handwriting-generation.session.seed", if (forceRandomSeed) 0L else -1)
205241

206242
val invertTransform = Transform(transform).apply {
207243
invert()
@@ -252,6 +288,8 @@ class GenerationViewModel(application: Application, private val engine: Engine)
252288
private const val LINE_GAP_RATIO = 3
253289

254290
private const val PROFILE_FOLDER = "profiles"
291+
292+
private val DEFAULT_LANGUAGE = HWGLanguage.ENGLISH
255293
}
256294
}
257295

0 commit comments

Comments
 (0)