├── BuildProcessTemplates ├── DefaultTemplate.11.1.xaml ├── LabDefaultTemplate.11.xaml └── UpgradeTemplate.xaml ├── InkMLjs ├── InkMLjs.sln ├── InkMLjs.vssscc ├── Web.config ├── dragdrop.htm ├── index.htm ├── ink.png ├── ink.pptx ├── ink1.xml ├── ink2.xml ├── inkml.js └── svg.png ├── LICENSE ├── README.md ├── SECURITY.md ├── nopressure.png └── pressure.png /BuildProcessTemplates/DefaultTemplate.11.1.xaml: -------------------------------------------------------------------------------- 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 | [New Microsoft.TeamFoundation.Build.Workflow.Activities.BuildSettings()] 27 | [False] 28 | [New Microsoft.TeamFoundation.Build.Workflow.Activities.TestSpecList(New Microsoft.TeamFoundation.Build.Workflow.Activities.AgileTestPlatformSpec("**\*test*.dll"))] 29 | ["$(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.r)"] 30 | [False] 31 | [True] 32 | [True] 33 | [Microsoft.TeamFoundation.Build.Workflow.Activities.CleanWorkspaceOption.All] 34 | 35 | 36 | 37 | [Microsoft.TeamFoundation.Build.Workflow.Activities.CodeAnalysisOption.AsConfigured] 38 | [True] 39 | [Microsoft.TeamFoundation.Build.Workflow.Activities.ToolPlatform.Auto] 40 | [True] 41 | [New Microsoft.TeamFoundation.Build.Workflow.Activities.SourceAndSymbolServerSettings(True, Nothing)] 42 | [True] 43 | 44 | 45 | 46 | [New Microsoft.TeamFoundation.Build.Workflow.Activities.AgentSettings() With {.MaxWaitTime = New System.TimeSpan(4, 0, 0), .MaxExecutionTime = New System.TimeSpan(0, 0, 0), .TagComparison = Microsoft.TeamFoundation.Build.Workflow.Activities.TagComparison.MatchExactly }] 47 | [Microsoft.TeamFoundation.Build.Workflow.BuildVerbosity.Normal] 48 | 49 | 50 | 51 | 52 | 53 | 54 | All 55 | 11.0 56 | Assembly references and imported namespaces serialized as XML namespaces 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 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | -------------------------------------------------------------------------------- /BuildProcessTemplates/LabDefaultTemplate.11.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 11.0 16 | 17 | 18 | 19 | 20 | 21 | 920,3702 22 | Assembly references and imported namespaces serialized as XML namespaces 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | True 44 | 45 | 46 | 47 | 48 | 49 | 50 | [LabWorkflowParameters.BuildDetails.BuildUri] 51 | 52 | 53 | [ChildBuildDetail.Uri] 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | [BuildLocation] 66 | 67 | 68 | [If(LabWorkflowParameters.BuildDetails.Configuration Is Nothing, BuildLocation, If(LabWorkflowParameters.BuildDetails.Configuration.IsEmpty Or (SelectedBuildDetail.Information.GetNodesByType(Microsoft.TeamFoundation.Build.Common.InformationTypes.ConfigurationSummary, True)).Count = 1, BuildLocation, If(LabWorkflowParameters.BuildDetails.Configuration.IsPlatformEmptyOrAnyCpu, BuildLocation + "\" + LabWorkflowParameters.BuildDetails.Configuration.Configuration, BuildLocation + "\" + LabWorkflowParameters.BuildDetails.Configuration.Platform + "\" + LabWorkflowParameters.BuildDetails.Configuration.Configuration)))] 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | [LabEnvironmentUri] 81 | 82 | 83 | [LabWorkflowParameters.EnvironmentDetails.LabEnvironmentUri.ToString()] 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | [PostDeploymentSnapshotName] 143 | 144 | 145 | [If(LabWorkflowParameters.BuildDetails.IsTeamSystemBuild = True,String.Format("{0}_{1}_{2}", LabWorkflowParameters.DeploymentDetails.PostDeploymentSnapshotName, BuildNumber,BuildDetail.BuildNumber),String.Format("{0}_{1}", LabWorkflowParameters.DeploymentDetails.PostDeploymentSnapshotName, BuildDetail.BuildNumber))] 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | [BuildStatus] 184 | 185 | 186 | [Microsoft.TeamFoundation.Build.Client.BuildStatus.PartiallySucceeded] 187 | 188 | 189 | 190 | 191 | 192 | 193 | [BuildStatus] 194 | 195 | 196 | [Microsoft.TeamFoundation.Build.Client.BuildStatus.Failed] 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | -------------------------------------------------------------------------------- /BuildProcessTemplates/UpgradeTemplate.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | [New Microsoft.TeamFoundation.Build.Workflow.Activities.AgentSettings() With {.MaxWaitTime = New System.TimeSpan(4, 0, 0), .MaxExecutionTime = New System.TimeSpan(0, 0, 0), .TagComparison = Microsoft.TeamFoundation.Build.Workflow.Activities.TagComparison.MatchExactly }] 21 | 22 | 23 | 24 | [Microsoft.TeamFoundation.Build.Workflow.Activities.ToolPlatform.Auto] 25 | [False] 26 | [False] 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | [Microsoft.TeamFoundation.VersionControl.Client.RecursionType.OneLevel] 37 | [Microsoft.TeamFoundation.Build.Workflow.BuildVerbosity.Normal] 38 | 39 | 40 | 41 | All 42 | Assembly references and imported namespaces serialized as XML namespaces 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 | -------------------------------------------------------------------------------- /InkMLjs/InkMLjs.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "InkMLjs", "..\InkMLjs", "{E7DF6F3E-96AB-4B4C-84D6-AF552913CA0B}" 5 | ProjectSection(WebsiteProperties) = preProject 6 | SccProjectName = "SAK" 7 | SccAuxPath = "SAK" 8 | SccLocalPath = "SAK" 9 | SccProvider = "SAK" 10 | TargetFrameworkMoniker = ".NETFramework,Version%3Dv4.0" 11 | Debug.AspNetCompiler.VirtualPath = "/Ink2SVG" 12 | Debug.AspNetCompiler.PhysicalPath = "..\InkMLjs\" 13 | Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\Ink2SVG\" 14 | Debug.AspNetCompiler.Updateable = "true" 15 | Debug.AspNetCompiler.ForceOverwrite = "true" 16 | Debug.AspNetCompiler.FixedNames = "false" 17 | Debug.AspNetCompiler.Debug = "True" 18 | Release.AspNetCompiler.VirtualPath = "/Ink2SVG" 19 | Release.AspNetCompiler.PhysicalPath = "..\InkMLjs\" 20 | Release.AspNetCompiler.TargetPath = "PrecompiledWeb\Ink2SVG\" 21 | Release.AspNetCompiler.Updateable = "true" 22 | Release.AspNetCompiler.ForceOverwrite = "true" 23 | Release.AspNetCompiler.FixedNames = "false" 24 | Release.AspNetCompiler.Debug = "False" 25 | VWDPort = "55486" 26 | EndProjectSection 27 | EndProject 28 | Global 29 | GlobalSection(TeamFoundationVersionControl) = preSolution 30 | SccNumberOfProjects = 2 31 | SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C} 32 | SccTeamFoundationServer = https://tfs.codeplex.com/tfs/tfs30 33 | SccLocalPath0 = . 34 | SccWebProject1 = true 35 | SccProjectUniqueName1 = . 36 | SccLocalPath1 = . 37 | SccProjectEnlistmentChoice1 = 2 38 | EndGlobalSection 39 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 40 | Debug|Any CPU = Debug|Any CPU 41 | Description = TFS user:snd\tomun_cp 42 | EndGlobalSection 43 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 44 | {E7DF6F3E-96AB-4B4C-84D6-AF552913CA0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 45 | {E7DF6F3E-96AB-4B4C-84D6-AF552913CA0B}.Debug|Any CPU.Build.0 = Debug|Any CPU 46 | EndGlobalSection 47 | GlobalSection(SolutionProperties) = preSolution 48 | HideSolutionNode = FALSE 49 | EndGlobalSection 50 | EndGlobal 51 | -------------------------------------------------------------------------------- /InkMLjs/InkMLjs.vssscc: -------------------------------------------------------------------------------- 1 | "" 2 | { 3 | "FILE_VERSION" = "9237" 4 | "ENLISTMENT_CHOICE" = "NEVER" 5 | "PROJECT_FILE_RELATIVE_PATH" = "" 6 | "NUMBER_OF_EXCLUDED_FILES" = "0" 7 | "ORIGINAL_PROJECT_FILE_PATH" = "" 8 | "NUMBER_OF_NESTED_PROJECTS" = "0" 9 | "SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT" 10 | } 11 | -------------------------------------------------------------------------------- /InkMLjs/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 10 | 11 | 12 | 13 | 14 | 20 | 21 | 22 | 27 | 28 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /InkMLjs/dragdrop.htm: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Client side conversion of InkML to SVG Example 5 | 6 | 7 | 8 | 42 | 43 | 44 |

45 | Client side conversion of InkML to SVG Example

46 |
47 |
48 | Drop InkML files here 49 |
50 | 51 | 52 |
53 | 54 | 55 | 128 |

129 | Works on latest versions of Chrome and FireFox. Drag and drop does not work on Safari, Opera, or IE9. 130 |

131 | 132 | 133 | -------------------------------------------------------------------------------- /InkMLjs/index.htm: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Client side conversion of InkML to SVG Example 5 | 6 | 7 | 94 | 128 | 129 | 130 |

131 | Client side conversion of InkML to SVG Example

132 |

133 | Source PowerPoint file: ink.pptx.

134 |

135 | ink.pptx

136 |

137 | The InkML part of the PowerPoint PPTX file above is here: ink1.xml. 138 |

139 | 140 | 141 | 144 | 147 | 148 | 149 | 152 | 155 | 156 |
142 | This is the original InkML generated by PowerPoint 2010: 143 | 145 | This is the InkML loaded by the JavaScript library and then saved back out: 146 |
150 | 151 | 153 | 154 |
157 |

158 | Below is the InkML part rendered directly in the browser. 159 |

160 | 161 | 162 | 165 | 168 | 169 | 170 | 174 | 178 | 179 |
163 | Ignoring pressure, drawing continuous, single width strokes: 164 | 166 | Using pressure, drawing line segments with variable widths: 167 |
171 | 172 | 173 | 175 | 176 | 177 |
180 |

181 | Draw some ink below 182 |

183 | 184 | 185 |

186 | The ink is rendered directly into an HTML5 canvas element via a JavaScript function 187 | that converts the InkML traces into SVG strokes.   The inkml to be rendered 188 | is specified using a data-inkml-src attribute on 189 | the <canvas> element.   For example:

190 |
<canvas width="600" height="200" data-inkml-src="ink1.xml"></canvas>
191 |
192 |
193 | Drop InkML files here 194 |
195 | 196 | 197 |
198 | 199 | 200 | 273 |

274 | Tested on the following browsers: IE9 RC, Chrome 9.0.597.98, FireFox 3.6.13, Opera 275 | 11.01, and Safari 5.0.3.  Uses jQuery 1.5 for XML loading and parsing. 276 |

277 | 278 | 279 | -------------------------------------------------------------------------------- /InkMLjs/ink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/InkMLjs/b4f5de01955ced9fe79d43ddc4bb46cbbdd24885/InkMLjs/ink.png -------------------------------------------------------------------------------- /InkMLjs/ink.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/InkMLjs/b4f5de01955ced9fe79d43ddc4bb46cbbdd24885/InkMLjs/ink.pptx -------------------------------------------------------------------------------- /InkMLjs/ink1.xml: -------------------------------------------------------------------------------- 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 | This 65 | 66 | 67 | Thins 68 | 69 | 70 | Thais 71 | 72 | 73 | Thi 74 | 75 | 76 | this 77 | 78 | 79 | 80 | 81 | 32 635 2757,'34'0'1090,"0"0"2950,-2 0-1347,2 0-1282,34 0-963,-2-33-63,1-1 321,-33 1-514,32-1 513,2 1-64,-2-34-63,1 34-1,33-34-513,0 33 192,-32-33-256,-2 0 64,1 34 129,-1-1-386,-32 2 514,-34-3-449,34 35 384,-34 0 1,0 0-770,0 35 705,0 64-128,0 35-64,0 34 64,-34-1-192,0-1 128,2 2 128,-36-1-192,35 1 193,-67-34-258,34-1 193,-36-32 129,36 0-257,-35-68 384,35 1-191,-34-34 255,32 0 65,-31-67-641,31-34 448,2 0-192,32 1-256,0 0 384,1-1-512,33 34 448,0 34-64,0 33-256,0 0 128,0 0-321,0 0 513,33 33-64,35 1-192,-2 33 256,2-34-192,31 34 64,1-67 0,2 34-449,31-34 513,1-34 321,0-33-257,33-33 1,0-66-450,-33-2 385,0 34-320,-1-67 63,-33 67 193,-32 0-449,-2 0 321,-32 67 192,-34 35-64,0-3 129,0 35-578,-34 0 64,-32 35 321,-2 64-257,-32 35 321,33 34 0,1-1 0,32 34 257,0-1-642,0 1 513,34-67-128,-32-1 0,32-32 193,0-34-450,0-33 514,0-34-129,0 0 0,0 0 257,0-68-706,66 1 449,2-66 1,-2 32-258,35 1 65,-35-1-192,-32 36 256,32 65-128,-66 0 128,34 65 320,-34 36-320,0-1 128,0 1-63,0-1-194,0 0 322,0-66-386,0 0 322,0-34 319,34 0-448,33-34 193,33-33-514,34-34 257,-34-32 64,-33 32-449,-1 34 449,-66 0-64,34 67 128,-34 0 64,0 0-448,0 34 512,0-1-128,0 68-128,0-34 192,0 0-320,0-1 384,34-32-127,0-1-322,-34-33 514,66 0-129,-32 0 257,33-67-321,-1 1-193,34-35 386,-32 1-385,32 33 192,-33-32-257,33 32-255,-66 32 512,0 35-193,-34 0 65,32 0 193,2 67-65,-1 0 0,1 0 64,-2 33-128,36 1-128,-34-34 0,0 33 192,-34-67-128,0 34 128,0-67 0,-34 34 192,-68-34 65,3 0 256,-1 0-449,0 0 193,-1-34-321,1-33 64,66 0-256,0 1-834,2-35-1090,32 34-2501 82 | 2976 602 18916,'0'-34'-1283,"0"34"1732,0-33 1603,0 33-1924,0 0-576,0 0-1733,0 0-3333,0 0-6604 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | is 93 | 94 | 95 | io 96 | 97 | 98 | His 99 | 100 | 101 | Jes 102 | 103 | 104 | les 105 | 106 | 107 | 108 | 109 | 4647 1639 1346,'0'0'-192,"0"0"1346,0 0 257,0 0-321,34 0 320,-34 0 194,0 0-65,0 0 256,0 0-577,0 0 193,0-34-834,34 34-449,33-67-64,-1 0-128,34 1 257,34-1-322,-33-34 129,-1 1 257,-32 33-514,-2 0 578,-66 35-321,33 32 0,-33 0 192,0 0-576,-33 32 191,-1 3 386,2 64-193,-2-32-129,34 0 65,0 0 257,0-34-193,0 1-193,0-1 193,0-33-64,66 0 64,-32 0 257,33 0-578,-1-33 513,36-34-320,-36 33 256,1-33 1,-1 0-322,2 0 129,-2 34 64,-32 1-128,33 32 192,-34 0-256,1 0 320,-34 0-64,33 65-64,-33 2-64,0 0 128,0 0 128,0 0 1,0-33-193,-33-1 320,33 0 1,-34-33 64,-32 0 320,32 0-256,-32 0 64,-2 0 192,1 0-448,1-33-65,-2 0-448,2-1 448,32 1-1154,34-1-1410,0 1-2181,0-1-5194 110 | 5618 803 14940,'-68'0'-385,"68"0"1155,0 0 1474,0 0-2244,0-35-256,0 3-257,0-3-64,0 3-706,0 32-1666,0-34-4490 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | a 121 | 122 | 123 | on 124 | 125 | 126 | or 127 | 128 | 129 | an 130 | 131 | 132 | ar 133 | 134 | 135 | 136 | 137 | 7892 1170 3398,'67'0'-513,"-67"-33"834,34 33 833,-34-34-449,32 34 65,-32-33 897,0 33-64,0-32-449,0-3 0,0 3 1,0-3-578,0 35-64,-32-32-513,-2 32 0,-33 0-513,0 0 385,-66 67 448,-1 0-512,33-2 641,1 36-193,32-68 1,36 34-1,32-33-448,0-34 192,66 0 192,34 0-705,35 0 321,31-67-1,-65 0 65,-1 33 321,0 1-450,-66 33 898,0 0-256,-34 0 320,34 0 257,-34 33-449,0 34-192,0 0-193,0-33-256,0 33 0,0-67-1091,66 33-1089,1-33-3271 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | test 148 | 149 | 150 | best 151 | 152 | 153 | Best 154 | 155 | 156 | hest 157 | 158 | 159 | fest 160 | 161 | 162 | 163 | 164 | 9698 234 3590,'34'-34'449,"-34"34"513,0 0 1539,0 0-770,0 0-512,0 0-899,-68 34 65,2 66 449,-1-33-578,-33 67 449,32-34-320,2 33-513,32-31 384,1 31-127,33-33 63,0 1-64,0-1-384,33-33 128,33 0-65,2-34 386,-2 1-129,2-34 192,32 0 385,1-34-384,-1-66-257,0 33 0,-33-33-321,-1-34 321,2 35-256,-34-2 192,-34 34-321,0 0 577,0 67-192,-68 0 0,-32 0-192,33 67 320,1 34-64,-2-2-128,34 1 321,2 1-450,32-34 322,0 0-129,66-34 0,-32 1 256,66-34-384,1 0 448,-1 0-384,33-67-64,-33 0 256,2 0-512,-2-34 448,-1 1-128,-31 1-129,-34 30 514,32 2-257,-32 35-128,-34 32 256,33 0-512,0 0 512,1 0-384,-1 67-129,-33 34 385,34-34-385,-34 32 514,0 1-193,0-33 128,0 0 449,0 0-641,-34-33 577,1-1-128,-34-33-65,0 0-63,33 0-129,-32-67-128,32 0-64,0 0 0,34 34 0,-33-1 0,33 1 128,0 33-193,0 0 129,33 0 193,35 33-257,-2-33 64,35 34 128,-1-34-128,34 0 385,-34 0-129,34-34-192,-33-33 193,33-33-514,-35 1 450,1-2-450,-32-1 65,-1 3 192,-1 32-321,-32 0 321,0 0 193,-34 67 63,0 0-64,0 0-512,0 0 512,-34 34-64,0 66-63,-32-33 319,-1 32-448,-1 3 385,36-1-129,-2-34 193,34 0-64,0-2-257,34-31 64,32 33-128,-32-34-128,33-33 192,-34 0-192,34 0 256,-33 0 64,32 0-833,-32 0 0,32-33-1475,2-1-1604,-35-33-1987 165 | 11236 736 7887,'-66'0'-577,"66"0"1218,0 0 770,0 0-514,0 0 257,34 0 193,-2 0-257,35 0 0,67 0-705,34-35-513,31 3 128,2-2-706,1 1-1794,-69 33-707,1-34-4680 166 | 8996 701 512,'0'0'385,"32"0"1347,-32 0 127,34 0-63,34 0-257,-2 0 512,35 0 66,65-32-899,35 32 0,1-34-1282,-35 1 0,-33-1-577,-1 1-1732,-67-1-7630 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | Blue 195 | 196 | 197 | Bloe 198 | 199 | 200 | Blve 201 | 202 | 203 | B\ve 204 | 205 | 206 | Blvd 207 | 208 | 209 | 210 | 211 | -905 6123 4168,'0'0'-898,"0"0"257,34 0 576,0 0-576,0-34-192,-34 34 512,0-32 706,33 32 256,-33-67-128,33 0-64,34-2 64,67-30-449,67-1 0,-1-1-705,35 1 0,32-1-1,-67 68-255,1 0 704,-33 33 193,-69 0 385,-65 33 641,-34 34-64,-34 33 256,-65 34-192,-35 0-256,0-35-386,-33 37-704,67-37 127,-35-65-127,69 33 256,32-67 192,34 0-256,0 0-129,34-34-320,66-33 577,33 0 513,68 0-898,-33 1 385,-1 31 257,-1 3-129,-64 32 385,31 0-577,-67 32 128,-32 37 128,0 30-63,-34 2 255,-68 33-63,-31 33-65,-35 0 322,66-34-963,-65 1 577,33-33-192,0-1 0,32-33 0,2-67-385,-1 0-63,-33 0-1797 212 | -402 6022 256,'-34'-67'1860,"34"35"-321,-34-2-257,34-1 385,0 35-641,-32 0 641,32 0-256,0 0-706,0 0 321,0 0-320,0 0-129,32 0 256,2 35-384,33 31 128,-1 36-192,36-3 64,-2 69 192,33-1-1025,-33 0 832,-32 1-319,32-2-65,-33-65 321,-33-1-578,-2-33 450,-32 0-1,0-67-128,0 0 129,0 0-514,0 0 65,0 0-257,0 0-1090,0-33-513,0-1-2500,-32 1-2887 213 | 2006 5220 3783,'-67'0'256,"33"0"898,34 67 450,0-1 63,0 35-257,34 33-127,0 33-321,32 33 64,-33-32-706,1-1-640,32-67 448,-32 1-962,0-1-1089,0-66-2245 214 | 2473 5822 1474,'68'0'-320,"-68"0"1089,34 0-128,-2 32-63,2 37 1153,0 30-962,-1 2 514,1-1-642,32 1-192,2-1-385,-2-67-192,1 1 256,0-34 0,0 0-320,-1-67 192,-32 0-257,0-67 322,-34 34 127,0-33 0,0 32-128,0-33 193,0 67 320,0 34-449,0 33-1090,0 0-2628 215 | 3879 5822 6732,'66'0'-897,"-32"0"1153,33 0 642,-1 0-1155,34 0 1,-32 0-578,-1-35 193,0 3 449,-34-35-1,1 34 258,-34-34 319,32 0 65,-32 33 128,34-33-320,-34 34 192,0-1-257,0 1-577,-34 33 257,2 0-385,-35 0 321,33 67 256,-32 0-257,-2 33 322,2-33-1,32 33 705,0 1 450,34 0-642,0-2 577,0-32 1,68 0-899,66 0-255,65-33-1348,36-1-961,-1-33-4489 216 | 217 | 218 | 219 | 220 | -------------------------------------------------------------------------------- /InkMLjs/ink2.xml: -------------------------------------------------------------------------------- 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 | The 58 | 59 | 60 | she 61 | 62 | 63 | the 64 | 65 | 66 | She 67 | 68 | 69 | Thi 70 | 71 | 72 | 73 | 74 | 267 400 4616,'0'0'706,"0"-33"-257,0 33 961,0 0-961,0 0 321,0 0 192,0 0-193,0 0 385,0 0-448,0 0-1,0 0 321,34 0-898,0-34 65,-2 1-1,35-1-256,33-33 256,-32 0-320,-34 0 256,-2 33-64,2 2-64,-1 32 128,-33 0-192,0 0 0,0 0 128,0 66-64,0 35 193,0-1-193,0 67-129,0-33 386,0 32-385,0-30 192,-33-2 0,-33-35-192,32-32 192,-34 0-257,36-33 450,-36-1-321,1-33 256,1 0 193,-2-33-706,2-68 321,-1 34 129,0 0-322,34 0 321,33 35-256,0 32 128,0 0 193,0 0-258,0 0 1,67 32 128,33 3 65,0-35-129,0 0-257,1 0 193,-1 0 0,0-35 0,1-32 256,-1 0-320,-32-34 192,-2 2 0,-32-35-192,-34 34 384,0-34-512,0 67 256,0-33-64,0 66 128,-34 34 0,34 0-449,0 0 321,0 0 0,0 0-256,0 34 512,0 33-256,0 33 128,34 34 0,-34 0-192,0 0 320,0-2-320,0 4 256,0-37-64,-34 2-320,0-34 448,34-34-192,-32 1-64,32-34 128,0 0-320,0-67-1,32 0 1,36-34 127,-35 34 129,33 0-128,2 0 64,-2 67 128,-32-34-128,33 34 385,-34 0-385,1 0 128,-1 34 128,1 1-256,-34-3 385,32 35-257,-32-32-128,34-3 256,0-32-577,-34 34 834,34-34-193,0 0 1,32-34-193,-33 2-513,34-35 321,-34 0 128,1-2-128,0 2 128,-34 2-128,0 31 320,0 34 257,-34 0-642,0 0 1,1 0 128,0 34 64,-1 31 449,34 36-449,0 1 384,0-35 65,0-1-513,34 1 192,32-34-320,34 1 0,-32-34-770,32 0-1282,-33 0-3463 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | quick 85 | 86 | 87 | quack 88 | 89 | 90 | quirk 91 | 92 | 93 | quid 94 | 95 | 96 | quiche 97 | 98 | 99 | 100 | 101 | 3645 500 1603,'0'0'-65,"0"0"2374,0 0-385,-34 0-1155,-32 34 65,-1-1-129,1 34 578,32-33-322,-34 31 1,36-30-64,32 31-577,0-31-386,0-35-127,0 32 0,0-32 320,66 0-256,2 0-129,-2-32 257,1-37-256,-1 37 127,2-35 1,-2 34-128,-32-1 256,-1 34-321,-33 0 578,0 0 256,0 67-321,-67 0 513,35 34-641,-36-2 321,0 2 64,36-1-449,-35 1 321,67-1-385,0-33 448,0 0-255,0 0-322,67-34 450,-35 1-514,70-2 321,-36-32-256,1 0-65,33-66 450,-32-1-514,-36-33 193,-32 0 128,0-1-192,0 1 384,-32-1-256,-36 34 192,2 35 449,32 32-513,-33 0-128,35 0 128,32 32-192,0 3 449,0-3-321,0 2-64,66-1 320,1-33-384,-1 0 192,2 0-192,32-33-65,-33-33 322,-1 31-258,-32-32 258,0 35-1,-34 32 64,0 0 129,0 0-578,0 0 321,0 0-256,-34 32 256,34 35 64,0 0-320,0-33 320,0-1-128,0-33 64,34 0-64,32 0-128,-32 0 64,33-67-64,-34 0 0,1 0 320,-1 0-320,1 33 384,-34 2 193,0 32-385,0 0 64,0 0-192,0 32 0,0 2 256,0 1-320,0 32 192,0-35-64,32 3 64,2-35 257,-34 32-513,34-32 512,0 0-191,-2-32-258,2-3 193,33 3-192,-33-3 192,-1-32 0,34 33-128,-67 2 128,0 32-192,34-35 256,-34 35-128,0 0-128,0 35 449,0-3-514,0 2 386,32 1-193,-32-35-128,34 32 256,0-32-192,0 35 256,-2-35 129,35 0-578,-33 0 578,32-35-321,-32 3 0,0-3 128,0 1-320,-2 2 320,2 32-192,-1-35 0,1 35 64,-34 0-257,34 0 257,-34 0 257,0 0-578,0 0 385,0 0-192,0 0 192,0 0 0,-34 0-320,0 0 384,1 0-192,-1 0 0,2 35 64,-36-3-257,34 2 514,2 1-65,32 32-128,0-35 321,0 35-770,0-67 578,32 34-65,36-34-64,-2 0 0,1 0-128,33-34 64,-32-33 128,32-32-128,-33 30 128,-1-30-256,-32-35 256,34 67 1,-36-33-322,-32 33 322,34 34 127,-34-1-192,34 34 64,-34-32-448,0 32 705,0 0-642,0 32 257,0 2 257,-34 33-642,0 33 705,2 0-448,-2 1 192,0-1 65,0 1-258,1-34 193,33-35 1,0 3-194,0-3 258,0-32-386,0-32 129,0-35 320,67 0-384,-33-34 320,32 1-577,35 33 257,-34 33 256,-34 1-449,33-1 385,-32 34 0,0 0 193,-34 0-1,0 34-320,0-1 192,-34 1-192,0-1 128,-65 1 192,32-34-577,0 33 706,33-1-257,2-32-64,32 0 64,0 35 128,0-35 1,0 32 448,66 2-320,1 1 576,0-3-832,0-32 319,-35 35-191,36-35-450,-34 0 129,-34 0-706,34 0 1,-34 0-65,0 0-1539,0 0-1282,0-67-4809 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | brown 112 | 113 | 114 | mown 115 | 116 | 117 | moan 118 | 119 | 120 | mean 121 | 122 | 123 | moun 124 | 125 | 126 | 127 | 128 | 7191 166 6476,'0'-34'641,"0"34"0,0 0 129,0 0 64,0-33-963,0 33 129,0 0 64,0 33 898,0 34 257,0 0-514,0 67-256,0 0-385,33 0 0,-33-2 128,0-31-384,33-34 384,-33 0-63,0-67-129,0 0 513,0 0-257,33-32-192,1-70 65,0 1-450,-2 2 449,36-35-320,-2 67-257,35-33 257,-35 67-129,2-1 321,-2 34 0,2 0 256,-35 67-63,0 0-193,-33 0 449,0 33-129,0-33-191,-66 0-1,-2-1-128,2-31 64,-34-3-128,33-32 0,-1 0 0,36 0-65,32 0 65,0-32 64,0-3-256,32 1 384,36 34-64,-1 0-128,33 0 192,0 0-192,-33 0 128,33 0-64,-32 0 0,-36-32 321,2-3-257,0-30 128,-34-2-64,0 0-128,0 33 193,0-33-450,0 34 193,0 33-64,34 0-321,32 0 449,-33 0 64,67 0-128,-32 0 64,32 0-256,-66 33 320,-1 1 0,0-1 64,-33 1 193,0-1-257,0 34 192,-33-33-320,0 31 0,-1-30 128,34-3-128,-34 37 192,34-69-192,0 32 64,0-32 449,0 35-192,34-35 256,33 0-385,-34 0-128,34 0 64,1-35-321,-36 3 257,2-3 193,0 1-257,-34 34 192,0 0-64,0 0-64,0 0 0,0 0-321,0 34 450,-34 33-193,34-32 64,0 32 128,34-35-385,-1 2 386,0-34-194,34 0 65,-33 0 321,-2 0-449,36-34 320,-34 2-192,-1-35 0,0 0 0,1-34-385,-34 34 450,0 0-130,0 34 130,0-1 63,-67 34-128,34 0-64,-35 34 192,34-1-192,2 34 192,32-35-256,0 3 128,0-3 0,32-32-321,2 0 578,0 0-257,66 0 0,-33-32 0,33-3-321,-32 3-128,-36-1 0,36-1 321,-68 34 192,0 0 257,0 0 448,0 0-640,-34 0-129,0 34 192,2 31-256,-2-30 128,34 31 0,0-31-320,0-3 191,66 3 65,-32-35 0,33 0 257,-33 0-514,32-35 386,-32 3 63,-34-3-192,34 1 64,-34 34-64,0-32 641,0 32-641,0 0 0,0 0-64,0 32 0,0 2 0,0 1 192,0-3-256,32-32 256,2 35-192,0-35 0,-34 32 192,34-32-256,-34 0 385,0 0-129,0 0 321,0-32-129,0-35-320,0-2 129,0-30-129,0 32-65,33 0 322,-33 34-578,33-1 321,0 34-128,1 0-64,32 0 192,-32 0-129,34 0 129,-36 67 0,2-33-128,-1-1 321,-33 34-193,0-35 64,0 35 256,0 2-448,-33-37 192,-1 35 0,34-32-64,-32-35 321,32 32-642,0-32 706,0 0-385,0 0 0,32-32 0,-32-35-321,34 32 578,33-32-514,-33 1 257,-2 31 65,2-30-322,-34 65 321,34-34 64,0 34-128,-34 0 257,32 0-385,2 0 641,0 34 64,-1 66 192,-33-34 193,33 36-321,34-3-577,-33 2-64,66-34-1667,0-67-2373 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | fox 139 | 140 | 141 | tox 142 | 143 | 144 | for 145 | 146 | 147 | fax 148 | 149 | 150 | fox, 151 | 152 | 153 | 154 | 155 | 11572 500 9874,'34'-33'-512,"66"33"3525,-1-34-1923,35 1-833,33 0-65,-33-1-384,0 1 320,-1-1-192,-65 34 64,-34 0 128,-2 0 193,-32 0 769,0 0-192,-66 67-706,-2 0 385,2 0-513,-1 0 193,33 0-129,2 0-64,32-2 449,0-30-513,32-3-256,36 2 127,-1 1-63,33-35 128,0 0-128,0 0-1,-33-35 1,-33-31 64,0-1 512,-34 0-320,0 0 449,-34 0 385,-33 34-705,0 33 191,0 0-320,1 0-192,32 0 192,0 33-833,34 1-193,0-1-449,34 1-897,32-34-706,2 0-3462 156 | 12174 234 128,'32'-35'3719,"-32"35"-1411,0 0-63,0 0-642,0-33-449,34 33-64,0-34-64,-34 34 256,34-33-127,-34-1-642,0 0 0,0 2-449,0-3 321,-34 35-578,-34-33-63,2 33 448,-1 0-513,1 0 386,32 33 319,34 2-255,0-3-65,0 36-64,0 32 0,34-33 320,32 34-640,-33-1 640,1 0-320,-34 1 0,34-36 129,-34 36-129,0-34 384,0-32-384,0-3 0,0 3 64,0-35-833,0 0-642,0 0-2116,-34 0-7117 157 | 13211 367 9233,'66'0'1283,"-32"33"3334,0 34-2181,32 0-1602,1 33-321,33-1-577,0 2-449,1-34-2180,-1 0-5195 158 | 13746 333 11093,'0'0'0,"0"0"3014,0 0-962,0 0-1539,-34 34 897,0-1-640,2 34-386,-36 33 129,34-33-513,1 0 0,0-35-64,33 3-769,-33-3-65,33-32-705,0 0-962,0 0-641,-34 0-1668,34 0-255 159 | 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /InkMLjs/inkml.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * InkML.js 3 | * Load InkML into a JavaScript object and then render the object into a canvas. 4 | * Capture mouse/pen/touch strokes on a canvas and save the results to InkML. 5 | * Tom Underhill 6 | * version 0.1 7 | */ 8 | 9 | // dpi for converting ink space (himetric) to pixels 10 | var g_dpi = 150; 11 | 12 | // xml namespaces 13 | var c_inkmlNS = "http://www.w3.org/2003/InkML"; 14 | var c_xmlNS = "http://www.w3.org/XML/1998/namespace"; 15 | var c_xmlnsNS = "http://www.w3.org/2000/xmlns/"; 16 | 17 | $(document).ready(function () 18 | { 19 | $(this).find("canvas").each(function () 20 | { 21 | var canvas = $(this).get(0); 22 | 23 | var src = $(this).attr("data-inkml-src"); 24 | if (src) 25 | { 26 | var ignorePressure = $(this).attr("data-inkml-ignorePressure"); 27 | 28 | $.get(src, {}, function (xml, textStatus, jqXHR) 29 | { 30 | var ink = new Ink(xml); 31 | ink.draw(canvas, ignorePressure); 32 | }); 33 | } 34 | 35 | var trg = $(this).attr("data-inkml-trg"); 36 | if (trg) 37 | { 38 | var ink = new Ink(); 39 | ink.initForCapture(canvas); 40 | } 41 | }); 42 | }); 43 | 44 | // Ink class 45 | Ink = function (inkml) 46 | { 47 | this.init(inkml); 48 | } 49 | $.extend(Ink.prototype, 50 | { 51 | // init this object by deserializing InkML 52 | init: function (inkml) 53 | { 54 | // members 55 | this.contexts = {}; 56 | this.brushes = {}; 57 | this.traces = {}; 58 | this.mins = []; 59 | this.maxs = []; 60 | this.sums = []; 61 | this.count = 0; 62 | 63 | this.deltas = []; 64 | this.ctx = null; 65 | 66 | if (inkml == null) 67 | return; 68 | 69 | var This = this; 70 | 71 | // iterate over the contexts 72 | $(inkml).find("inkml\\:context, context").each(function () 73 | { 74 | var id = $(this).attr("xml:id"); 75 | if (id == null) 76 | id = $(this).attr("id"); // "xml:id" fails on opera, "id" works but fails on all other browsers 77 | if (id == null) 78 | { 79 | // InkML files may contain inkml:context and msink:context elements, but WebKit and Opera do 80 | // not distiguish between xml namespaces, so if the required xml:id attribute isn't present, 81 | // just assume its an msink:context and skip it. 82 | } 83 | else 84 | id = "#" + id; 85 | if (id) 86 | { 87 | var context = new InkContext($(this)); 88 | This.contexts[id] = context; 89 | } 90 | }); 91 | 92 | // iterate over the brushes 93 | $(inkml).find("inkml\\:brush, brush").each(function () 94 | { 95 | var brush = new InkBrush($(this)); 96 | var id = $(this).attr("xml:id"); 97 | if (id == null) 98 | id = $(this).attr("id"); // "xml:id" fails on opera, "id" works but fails on all other browsers 99 | if (id == null || id == "") 100 | { 101 | var count = 0; 102 | for (k in This.brushes) if (This.brushes.hasOwnProperty(k)) count++; 103 | id = "brush#" + count.toString(); 104 | } 105 | else 106 | id = "#" + id; 107 | This.brushes[id] = brush; 108 | }); 109 | 110 | // iterate over the traces 111 | $(inkml).find("inkml\\:trace, trace").each(function () 112 | { 113 | var trace = new InkTrace(This, $(this)); 114 | var id = $(this).attr("xml:id"); 115 | if (id == null) 116 | id = $(this).attr("id"); // "xml:id" fails on opera, "id" works but fails on all other browsers 117 | if (id == null || id == "") 118 | { 119 | var count = 0; 120 | for (k in This.traces) if (This.traces.hasOwnProperty(k)) count++; 121 | id = "trace#" + count.toString(); 122 | } 123 | else 124 | id = "#" + id; 125 | This.traces[id] = trace; 126 | }); // next trace 127 | }, 128 | 129 | toInkML: function () 130 | { 131 | var inkml = document.implementation.createDocument(c_inkmlNS, "inkml:ink", null); 132 | 133 | // Root with xmlns:xml Root without xmlns:xml 134 | // IE9 children have xmlns:xml children have xmlns:xml 135 | // FF: children clean children clean 136 | // Chrome: children clean children have xmlns:xml 137 | // Opera: children clean children clean 138 | var xmlns = inkml.createAttributeNS(c_xmlnsNS, "xmlns:xml"); 139 | xmlns.nodeValue = c_xmlNS; 140 | inkml.documentElement.setAttributeNode(xmlns); 141 | 142 | var definitions = inkml.createElementNS(c_inkmlNS, "inkml:definitions"); 143 | inkml.documentElement.appendChild(definitions); 144 | 145 | $.each(this.contexts, function (id, context) 146 | { 147 | var inkmlContext = context.toInkML(inkml); 148 | 149 | var xmlid = inkml.createAttributeNS(c_xmlNS, "xml:id"); 150 | xmlid.nodeValue = id.substr(1); // strip leading '#' 151 | 152 | inkmlContext.setAttributeNode(xmlid); 153 | definitions.appendChild(inkmlContext); 154 | }); 155 | 156 | $.each(this.brushes, function (id, brush) 157 | { 158 | var inkmlBrush = brush.toInkML(inkml); 159 | 160 | var xmlid = inkml.createAttributeNS(c_xmlNS, "xml:id"); 161 | xmlid.nodeValue = id.substr(1); // strip leading '#' 162 | 163 | inkmlBrush.setAttributeNode(xmlid); 164 | definitions.appendChild(inkmlBrush); 165 | }); 166 | 167 | // TODO: handle traceGroups 168 | $.each(this.traces, function (id, trace) 169 | { 170 | var inkmlTrace = trace.toInkML(inkml); 171 | 172 | if (typeof (id) != 'number') 173 | { 174 | var xmlid = inkml.createAttributeNS(c_xmlNS, "xml:id"); 175 | xmlid.nodeValue = id.substr(1); // strip leading '#' 176 | 177 | inkmlTrace.setAttributeNode(xmlid); 178 | } 179 | inkml.documentElement.appendChild(inkmlTrace); 180 | }); 181 | 182 | return inkml; 183 | }, 184 | 185 | getPixelWidth: function () 186 | { 187 | var This = this; 188 | 189 | var width = This.maxs[0] - This.mins[0]; 190 | return width; 191 | }, 192 | 193 | getPixelHeight: function () 194 | { 195 | var This = this; 196 | 197 | var height = This.maxs[1] - This.mins[1]; 198 | return height; 199 | }, 200 | 201 | clear: function (canvas) 202 | { 203 | var This = this; 204 | 205 | if (canvas.getContext == null) 206 | { 207 | alert("error: couldn't get context on canvas"); 208 | return; 209 | } 210 | var ctx = canvas.getContext('2d'); 211 | ctx.clearRect(0, 0, canvas.width, canvas.height); 212 | }, 213 | 214 | draw: function (canvas, ignorePressure) 215 | { 216 | var This = this; 217 | 218 | if (canvas.getContext == null) 219 | { 220 | alert("error: couldn't get context on canvas"); 221 | return; 222 | } 223 | var ctx = canvas.getContext('2d'); 224 | // draw the traces 225 | $.each(this.traces, function (id, trace) 226 | { 227 | ctx.save(); 228 | 229 | // TODO: handle traceRef versus contextRef 230 | var context = This.contexts[trace.contextRef]; 231 | 232 | ctx.scale(context.xFactor, context.xFactor); 233 | 234 | var brush = null; 235 | if (trace.brushRef != null) 236 | { 237 | brush = This.brushes[trace.brushRef]; 238 | if (brush == null) 239 | alert("error: brush with xml:id='" + trace.brushRef + "' not found."); 240 | } 241 | else if (context.brush) 242 | { 243 | brush = context.brush; 244 | } 245 | if (brush != null) 246 | { 247 | // TODO: alpha 248 | // TODO: approximate rasterOps 249 | ctx.strokeStyle = brush.color; 250 | // TODO: approximate ink rectangluar brushes 251 | ctx.lineCap = "round"; 252 | ctx.lineJoin = "round"; 253 | 254 | var pixelWidth = HiMetricToPixel(brush.width, g_dpi); 255 | ctx.lineWidth = pixelWidth * 10; 256 | } 257 | 258 | ctx.beginPath(); 259 | for (var i = 0; i < trace.value.length; i++) 260 | { 261 | if (i == 0) 262 | { 263 | if (ignorePressure) 264 | { 265 | var x = trace.value[i][0] - This.mins[0]; 266 | var y = trace.value[i][1] - This.mins[1]; 267 | ctx.moveTo(x, y); 268 | } 269 | else 270 | { 271 | // nop on first point 272 | } 273 | // TODO: handle traces with only a single point. 274 | } 275 | else 276 | { 277 | if (ignorePressure) 278 | { 279 | var x = trace.value[i][0] - This.mins[0]; 280 | var y = trace.value[i][1] - This.mins[1]; 281 | ctx.lineTo(x, y); 282 | } 283 | else 284 | { 285 | var x1 = trace.value[i - 1][0] - This.mins[0]; 286 | var y1 = trace.value[i - 1][1] - This.mins[1]; 287 | var x2 = trace.value[i][0] - This.mins[0]; 288 | var y2 = trace.value[i][1] - This.mins[1]; 289 | if (brush) 290 | { 291 | // TODO: use named channels instead of assuming index 2 is force 292 | var width = brush.width; // in himetric 293 | var force = (trace.value[i - 1][2] + trace.value[i][2]) / 2; 294 | if (force) 295 | { 296 | var avg = This.sums[2] / This.count; 297 | force -= context.fNeutral; 298 | force *= context.fFactor; 299 | width += (width * force); 300 | } 301 | var pixelWidth = HiMetricToPixel(width, g_dpi); 302 | ctx.lineWidth = pixelWidth * 10; 303 | } 304 | ctx.moveTo(x1, y1); 305 | ctx.lineTo(x2, y2); 306 | ctx.stroke(); 307 | } 308 | } 309 | } 310 | if (ignorePressure) 311 | ctx.stroke(); 312 | ctx.restore(); 313 | }); 314 | }, 315 | 316 | initForCapture: function (canvas) 317 | { 318 | var This = this; 319 | $(canvas).bind("mousedown", function (event) { This.onMouseDown(event); }); 320 | $(canvas).bind("mousemove", function (event) { This.onMouseMove(event); }); 321 | $(canvas).bind("mouseup", function (event) { This.onMouseUp(event); }); 322 | }, 323 | 324 | pushCoord: function (event) 325 | { 326 | // TODO: incomplete 327 | 328 | /* 329 | var i = this.value.length; 330 | var x = event.offsetX; 331 | var y = event.offsetY; 332 | 333 | if (i == 0) 334 | { 335 | // absolute 336 | } 337 | if (i == 1) 338 | { 339 | // first derivative 340 | deltas.push(table[i][j]); 341 | table[i][j] = table[i - 1][j] + deltas[j]; 342 | } 343 | else if (i > 1) 344 | { 345 | // second derivative 346 | deltas[j] += table[i][j]; 347 | table[i][j] = table[i - 1][j] + deltas[j]; 348 | } 349 | 350 | table.push([]); 351 | table[table.length - 1].push(x); 352 | table[table.length - 1].push(y); 353 | */ 354 | }, 355 | 356 | onMouseDown: function (event) 357 | { 358 | var canvas = event.target; 359 | if ($.browser.msie) 360 | canvas.setCapture(); 361 | 362 | this.ctx = canvas.getContext('2d'); 363 | 364 | this.ctx.beginPath(); 365 | this.ctx.strokeStyle = "#00FF00"; 366 | this.ctx.lineWidth = 2; 367 | 368 | // fix for FireFix which doesn't have offsetX, offsetY 369 | if (!event.offsetX) 370 | event.offsetX = event.layerX - $(event.target).position().left; 371 | if (!event.offsetY) 372 | event.offsetY = event.layerY - $(event.target).position().top; 373 | 374 | this.ctx.moveTo(event.offsetX, event.offsetY); 375 | this.pushCoord(event); 376 | }, 377 | 378 | onMouseMove: function (event) 379 | { 380 | if (this.ctx) 381 | { 382 | // fix for FireFix which doesn't have offsetX, offsetY 383 | if (!event.offsetX) 384 | event.offsetX = event.layerX - $(event.target).position().left; 385 | if (!event.offsetY) 386 | event.offsetY = event.layerY - $(event.target).position().top; 387 | 388 | this.ctx.lineTo(event.offsetX, event.offsetY); 389 | this.ctx.stroke(); 390 | this.pushCoord(event); 391 | } 392 | }, 393 | 394 | onMouseUp: function (event) 395 | { 396 | if (this.ctx) 397 | { 398 | // working in all but FireFox: in FF, event is reached, but nothing is drawn. Wrong ctx? 399 | var canvas = event.target; 400 | if ($.browser.msie) 401 | canvas.releaseCapture(); 402 | 403 | // fix for FireFix which doesn't have offsetX, offsetY 404 | if (!event.offsetX) 405 | event.offsetX = event.layerX - $(event.target).position().left; 406 | if (!event.offsetY) 407 | event.offsetY = event.layerY - $(event.target).position().top; 408 | 409 | this.ctx.lineTo(event.offsetX, event.offsetY); 410 | this.ctx.stroke(); 411 | this.pushCoord(event); 412 | 413 | this.ctx = null; 414 | } 415 | } 416 | }); 417 | 418 | // InkContext class 419 | InkContext = function (inkmlContext) 420 | { 421 | this.init(inkmlContext); 422 | } 423 | $.extend(InkContext.prototype, 424 | { 425 | // init this object by deserializing an InkML context 426 | init: function (inkmlContext) 427 | { 428 | // members 429 | this.inkSource = null; 430 | this.brush = null; 431 | this.timestamp = null; 432 | this.xFactor = 1; 433 | this.yFactor = 1; 434 | this.fFactor = 1; 435 | this.fNeutral = .5; 436 | 437 | var This = this; 438 | 439 | // find the optional inkSource 440 | // TODO: handle inkSourceRef 441 | var inkmlInkSource = $(inkmlContext).find("inkml\\:inkSource, inkSource"); 442 | if (inkmlInkSource.length) 443 | { 444 | This.inkSource = new InkSource(inkmlInkSource); 445 | 446 | // compute and cache Ink to SVG scaling factors 447 | // TODO: defaults for missing explicit X and Y channels 448 | var xChan = This.inkSource.traceFormat.channels["X"]; 449 | var yChan = This.inkSource.traceFormat.channels["Y"]; 450 | 451 | var xRes = UnitsToHiMetric(1 / xChan.resolution, xChan.units); 452 | var yRes = UnitsToHiMetric(1 / yChan.resolution, yChan.units); 453 | This.xFactor = HiMetricToPixel(xRes, g_dpi); 454 | This.yFactor = HiMetricToPixel(yRes, g_dpi); 455 | 456 | // compute force scaling factor 457 | var fChan = This.inkSource.traceFormat.channels["F"]; 458 | if (fChan) 459 | { 460 | This.fFactor = 1 / (fChan.max - fChan.min); 461 | This.fNeutral = (fChan.max - fChan.min) / 2; 462 | } 463 | } 464 | 465 | // find the optional brush 466 | var inkmlBrush = $(inkmlContext).find("inkml\\:brush, brush"); 467 | if (inkmlBrush.length) 468 | { 469 | This.brush = new InkBrush(inkmlBrush); 470 | } 471 | 472 | var inkmlTimestamp = $(inkmlContext).find("inkml\\:timestamp, timestamp"); 473 | if (inkmlTimestamp.length) 474 | this.timestamp = new InkTimestamp(inkmlTimestamp); 475 | }, 476 | 477 | toInkML: function (inkml) 478 | { 479 | var inkmlContext = inkml.createElementNS(c_inkmlNS, "inkml:context"); 480 | 481 | if (this.inkSource) 482 | { 483 | var inkmlInkSource = this.inkSource.toInkML(inkml); 484 | inkmlContext.appendChild(inkmlInkSource); 485 | } 486 | 487 | if (this.timestamp) 488 | { 489 | var inkmlTimestamp = this.timestamp.toInkML(inkml); 490 | inkmlContext.appendChild(inkmlTimestamp); 491 | } 492 | 493 | return inkmlContext; 494 | } 495 | }); 496 | 497 | // InkSource class 498 | InkSource = function (inkmlInkSource) 499 | { 500 | this.init(inkmlInkSource); 501 | } 502 | $.extend(InkSource.prototype, 503 | { 504 | // init this object by deserializing an InkML inkSource 505 | init: function (inkmlInkSource) 506 | { 507 | // members 508 | this.id = $(inkmlInkSource).attr("xml:id"); 509 | if (this.id == null) 510 | this.id = $(inkmlInkSource).attr("id"); 511 | this.traceFormat = null; 512 | this.channelProperties = []; 513 | 514 | var inkmlTraceFormat = $(inkmlInkSource).find("inkml\\:traceFormat, traceFormat"); 515 | if (inkmlTraceFormat.length < 1) 516 | alert("error: traceFormat is required on inkSource"); 517 | var inkmlChannelProperties = $(inkmlInkSource).find("inkml\\:channelProperties, channelProperties"); 518 | 519 | this.traceFormat = new InkTraceFormat(inkmlTraceFormat, inkmlChannelProperties); 520 | 521 | this.channels = {}; 522 | 523 | var This = this; 524 | 525 | // iterate over the channelProperties 526 | $(inkmlInkSource).find("inkml\\:channelProperty, channelProperty").each(function () 527 | { 528 | var channelProperty = new InkChannelProperty($(this)); 529 | This.channelProperties.push(channelProperty); 530 | }); 531 | }, 532 | 533 | toInkML: function (inkml) 534 | { 535 | var inkmlSource = inkml.createElementNS(c_inkmlNS, "inkml:inkSource"); 536 | 537 | var xmlid = inkml.createAttributeNS(c_xmlNS, "xml:id"); 538 | xmlid.nodeValue = this.id; 539 | inkmlSource.setAttributeNode(xmlid); 540 | 541 | var inkmlTraceFormat = this.traceFormat.toInkML(inkml); 542 | inkmlSource.appendChild(inkmlTraceFormat); 543 | 544 | var inkmlChannelProperties = inkml.createElementNS(c_inkmlNS, "inkml:channelProperties"); 545 | inkmlSource.appendChild(inkmlChannelProperties); 546 | 547 | $.each(this.channelProperties, function (index, channelProperty) 548 | { 549 | var inkmlChannelProperty = channelProperty.toInkML(inkml); 550 | inkmlChannelProperties.appendChild(inkmlChannelProperty); 551 | }); 552 | 553 | return inkmlSource; 554 | } 555 | }); 556 | 557 | // InkTimestamp class 558 | InkTimestamp = function (inkmlTimestamp) 559 | { 560 | this.init(inkmlTimestamp); 561 | } 562 | $.extend(InkTimestamp.prototype, 563 | { 564 | // init this object by deserializing an InkML timestamp 565 | init: function (inkmlTimestamp) 566 | { 567 | // members 568 | this.id = $(inkmlTimestamp).attr("xml:id"); 569 | if (this.id == null) 570 | this.id = $(inkmlTimestamp).attr("id"); 571 | this.timeString = $(inkmlTimestamp).attr("timeString"); 572 | }, 573 | 574 | toInkML: function (inkml) 575 | { 576 | var inkmlTimestamp = inkml.createElementNS(c_inkmlNS, "inkml:timestamp"); 577 | 578 | var xmlid = inkml.createAttributeNS(c_xmlNS, "xml:id"); 579 | xmlid.nodeValue = this.id; 580 | inkmlTimestamp.setAttributeNode(xmlid); 581 | 582 | inkmlTimestamp.setAttribute("timeString", this.timeString); 583 | 584 | return inkmlTimestamp; 585 | } 586 | }); 587 | 588 | // InkTraceFormat class 589 | InkTraceFormat = function (inkmlTraceFormat, inkmlChannelProperties) 590 | { 591 | this.init(inkmlTraceFormat, inkmlChannelProperties); 592 | } 593 | $.extend(InkTraceFormat.prototype, 594 | { 595 | // init this object by deserializing an InkML traceFormat and an optional channelProperties 596 | init: function (inkmlTraceFormat, inkmlChannelProperties) 597 | { 598 | // members 599 | this.id = $(inkmlTraceFormat).attr("xml:id"); 600 | if (this.id == null) 601 | this.id = $(inkmlTraceFormat).attr("id"); 602 | 603 | this.channels = {}; 604 | 605 | var This = this; 606 | 607 | // iterate over the channels 608 | $(inkmlTraceFormat).find("inkml\\:channel, channel").each(function () 609 | { 610 | var name = $(this).attr("name"); 611 | var channel = new InkChannel($(this), inkmlChannelProperties); 612 | This.channels[name] = channel; 613 | }); 614 | }, 615 | 616 | toInkML: function (inkml) 617 | { 618 | var inkmlTraceFormat = inkml.createElementNS(c_inkmlNS, "inkml:traceFormat"); 619 | 620 | var xmlid = inkml.createAttributeNS(c_xmlNS, "xml:id"); 621 | xmlid.nodeValue = this.id; 622 | inkmlTraceFormat.setAttributeNode(xmlid); 623 | 624 | $.each(this.channels, function (name, channel) 625 | { 626 | var inkmlChannel = channel.toInkML(inkml); 627 | inkmlTraceFormat.appendChild(inkmlChannel); 628 | }); 629 | 630 | return inkmlTraceFormat; 631 | } 632 | }); 633 | 634 | // InkChannel class 635 | InkChannel = function (inkmlChannel, inkmlChannelProperties) 636 | { 637 | this.init(inkmlChannel, inkmlChannelProperties); 638 | } 639 | $.extend(InkChannel.prototype, 640 | { 641 | // init this object by deserializing an InkML InkChannel and an optional channelProperties 642 | init: function (inkmlChannel, inkmlChannelProperties) 643 | { 644 | // members 645 | this.name = inkmlChannel.attr("name"); 646 | this.type = inkmlChannel.attr("type"); 647 | var minAttr = inkmlChannel.attr("min"); 648 | if (minAttr == null) 649 | this.min = 0; 650 | else 651 | this.min = parseFloat(minAttr); 652 | this.max = parseFloat(inkmlChannel.attr("max")); 653 | this.units = inkmlChannel.attr("units"); 654 | this.resolution = 0; 655 | 656 | var This = this; 657 | 658 | var resProp = inkmlChannelProperties.find("inkml\\:channelProperty[channel='" + this.name + "'][name='resolution'], channelProperty[channel='" + this.name + "'][name='resolution']"); 659 | if (resProp.length) 660 | { 661 | var value = resProp.attr("value"); 662 | var units = resProp.attr("units"); 663 | if (units.substr(0, 2) != "1/") 664 | alert("error: units of resolution property expected to be 1/unit"); 665 | units = units.substring(2); 666 | if (This.units != units) 667 | alert("error: units of resolution property expected to be same as channel"); 668 | This.resolution = value; 669 | } 670 | }, 671 | 672 | toInkML: function (inkml) 673 | { 674 | var inkmlChannel = inkml.createElementNS(c_inkmlNS, "inkml:channel"); 675 | 676 | inkmlChannel.setAttribute("name", this.name); 677 | inkmlChannel.setAttribute("type", this.type); 678 | if (this.min != 0) 679 | inkmlChannel.setAttribute("min", this.min); 680 | inkmlChannel.setAttribute("max", this.max); 681 | inkmlChannel.setAttribute("units", this.units); 682 | 683 | return inkmlChannel; 684 | } 685 | }); 686 | 687 | // InkChannelProperty class 688 | InkChannelProperty = function (inkmlChannelProperty) 689 | { 690 | this.init(inkmlChannelProperty); 691 | } 692 | $.extend(InkChannelProperty.prototype, 693 | { 694 | // init this object by deserializing an InkML InkChannelProperty 695 | init: function (inkmlChannelProperty) 696 | { 697 | // members 698 | this.channel = inkmlChannelProperty.attr("channel"); 699 | this.name = inkmlChannelProperty.attr("name"); 700 | this.value = parseFloat(inkmlChannelProperty.attr("value")); 701 | this.units = inkmlChannelProperty.attr("units"); 702 | }, 703 | 704 | toInkML: function (inkml) 705 | { 706 | var inkmlChannelProperty = inkml.createElementNS(c_inkmlNS, "inkml:channelProperty"); 707 | 708 | inkmlChannelProperty.setAttribute("channel", this.channel); 709 | inkmlChannelProperty.setAttribute("name", this.name); 710 | inkmlChannelProperty.setAttribute("value", this.value); 711 | inkmlChannelProperty.setAttribute("units", this.units); 712 | 713 | return inkmlChannelProperty; 714 | } 715 | }); 716 | 717 | // InkBrush class 718 | InkBrush = function (inkmlBrush) 719 | { 720 | this.init(inkmlBrush); 721 | } 722 | $.extend(InkBrush.prototype, 723 | { 724 | // init this object by deserializing an InkML brush 725 | init: function (inkmlBrush) 726 | { 727 | // members 728 | this.width = 10; 729 | this.color = "#000000"; 730 | this.brushProperties = {}; 731 | 732 | var This = this; 733 | 734 | // iterate over the brushes 735 | $(inkmlBrush).find("inkml\\:brushProperty, brushProperty").each(function () 736 | { 737 | var name = $(this).attr("name"); 738 | switch (name) 739 | { 740 | case "color": 741 | This.color = $(this).attr("value"); 742 | break; 743 | case "width": 744 | This.width = UnitsToHiMetric(parseFloat($(this).attr("value")), $(this).attr("units")); 745 | break; 746 | default: 747 | break; 748 | } 749 | 750 | var brushProperty = new InkBrushProperty($(this)); 751 | This.brushProperties[name] = brushProperty; 752 | }); 753 | }, 754 | 755 | toInkML: function (inkml) 756 | { 757 | var inkmlBrush = inkml.createElementNS(c_inkmlNS, "inkml:brush"); 758 | 759 | $.each(this.brushProperties, function (name, brushProperty) 760 | { 761 | var inkmlBrushProperty = brushProperty.toInkML(inkml); 762 | inkmlBrush.appendChild(inkmlBrushProperty); 763 | }); 764 | 765 | return inkmlBrush; 766 | } 767 | }); 768 | 769 | 770 | // InkBrushProperty class 771 | InkBrushProperty = function (inkmlBrushProperty) 772 | { 773 | this.init(inkmlBrushProperty); 774 | } 775 | $.extend(InkBrushProperty.prototype, 776 | { 777 | // init this object by deserializing an InkML BrushProperty 778 | init: function (inkmlBrushProperty) 779 | { 780 | // members 781 | this.name = inkmlBrushProperty.attr("name"); 782 | this.value = inkmlBrushProperty.attr("value"); 783 | this.units = inkmlBrushProperty.attr("units"); 784 | }, 785 | 786 | toInkML: function (inkml) 787 | { 788 | var inkmlBrushProperty = inkml.createElementNS(c_inkmlNS, "inkml:brushProperty"); 789 | 790 | inkmlBrushProperty.setAttribute("name", this.name); 791 | inkmlBrushProperty.setAttribute("value", this.value); 792 | inkmlBrushProperty.setAttribute("units", this.units); 793 | 794 | return inkmlBrushProperty; 795 | } 796 | }); 797 | 798 | // InkTrace class 799 | InkTrace = function (ink, inkmlTrace) 800 | { 801 | this.init(ink, inkmlTrace); 802 | } 803 | $.extend(InkTrace.prototype, 804 | { 805 | // init this object with an ink object and an InkML trace 806 | init: function (ink, inkmlTrace) 807 | { 808 | // members 809 | this.ink = ink; 810 | this.value = []; 811 | this.deriv = []; 812 | this.brushRef = inkmlTrace.attr("brushRef"); 813 | this.contextRef = inkmlTrace.attr("contextRef"); 814 | this.timeOffset = inkmlTrace.attr("timeOffset"); 815 | 816 | var This = this; 817 | 818 | // iterate over each coord in the trace 819 | var trace = inkmlTrace.text(); 820 | var packets = trace.split(","); 821 | var iPacket = 0; 822 | var thisDeriv = "!"; 823 | while (iPacket < packets.length) 824 | { 825 | This.value.push([]); 826 | This.deriv.push([]); 827 | var packet = packets[iPacket]; 828 | 829 | var iProp = 0; 830 | var thisValue = ""; 831 | var iChar = 0; 832 | while (iChar < packet.length) 833 | { 834 | var ch = packet.charAt(iChar); 835 | 836 | if (isDigit(ch) || ch == '.') 837 | { 838 | thisValue += ch; 839 | } 840 | else 841 | { 842 | if (thisValue.length > 0) 843 | { 844 | This.value[iPacket].push(parseFloat(thisValue)); 845 | This.deriv[iPacket].push(thisDeriv); 846 | if (ch == "-") 847 | { 848 | thisValue = ch; 849 | } 850 | else if (ch == "!" || ch == "'" || ch == "\"") 851 | { 852 | thisValue = ""; 853 | thisDeriv = ch; 854 | } 855 | else 856 | { 857 | thisValue = ""; 858 | } 859 | } 860 | else 861 | { 862 | if (ch == "-") 863 | { 864 | thisValue = ch; 865 | } 866 | else if (ch == "!" || ch == "'" || ch == "\"") 867 | { 868 | thisDeriv = ch; 869 | } 870 | } 871 | } 872 | iChar += 1; 873 | } 874 | 875 | if (thisValue.length > 0) 876 | { 877 | This.value[iPacket].push(parseFloat(thisValue)); 878 | This.deriv[iPacket].push(thisDeriv); 879 | thisValue = ""; 880 | } 881 | 882 | iPacket += 1; 883 | } 884 | 885 | // TODO: compute derivatives in a single pass above 886 | var deltas = []; 887 | for (var i = 0; i < This.value.length; i++) 888 | { 889 | for (var j = 0; j < This.value[i].length; j++) 890 | { 891 | if (This.deriv[i][j] == "'") 892 | { 893 | // first derivative 894 | deltas.push(This.value[i][j]); 895 | This.value[i][j] = This.value[i - 1][j] + deltas[j]; 896 | } 897 | else if (This.deriv[i][j] == "\"") 898 | { 899 | // second derivative 900 | deltas[j] += This.value[i][j]; 901 | This.value[i][j] = This.value[i - 1][j] + deltas[j]; 902 | } 903 | 904 | if (This.ink.mins.length <= j) 905 | This.ink.mins.push(This.value[i][j]) 906 | else 907 | { 908 | if (This.ink.mins[j] > This.value[i][j]) 909 | This.ink.mins[j] = This.value[i][j]; 910 | } 911 | 912 | if (This.ink.maxs.length <= j) 913 | This.ink.maxs.push(This.value[i][j]) 914 | else 915 | { 916 | if (This.ink.maxs[j] < This.value[i][j]) 917 | This.ink.maxs[j] = This.value[i][j]; 918 | } 919 | 920 | if (This.ink.sums.length <= j) 921 | { 922 | This.ink.sums.push(This.value[i][j]) 923 | This.ink.count++; 924 | } 925 | else 926 | { 927 | This.ink.sums[j] += This.value[i][j]; 928 | This.ink.count++; 929 | } 930 | } 931 | } 932 | }, 933 | 934 | toInkML: function (inkml) 935 | { 936 | var inkmlTrace = inkml.createElementNS(c_inkmlNS, "inkml:trace"); 937 | 938 | inkmlTrace.setAttribute("contextRef", this.contextRef); 939 | inkmlTrace.setAttribute("brushRef", this.brushRef); 940 | inkmlTrace.setAttribute("timeOffset", this.timeOffset); 941 | 942 | // TODO: do first and second derivative calc to compress output 943 | var traceText = ""; 944 | $.each(this.value, function (index, row) 945 | { 946 | if (traceText.length) 947 | traceText += ","; 948 | var colText = ""; 949 | $.each(row, function (index, col) 950 | { 951 | if (colText.length) 952 | colText += " "; 953 | colText += col; 954 | }); 955 | traceText += colText; 956 | }); 957 | var inkmlTraceText = inkml.createTextNode(traceText); 958 | inkmlTrace.appendChild(inkmlTraceText); 959 | 960 | return inkmlTrace; 961 | } 962 | }); 963 | 964 | // Utilities 965 | 966 | function isDigit(ch) 967 | { 968 | if (ch.length > 1) 969 | { 970 | return false; 971 | } 972 | var string = "1234567890"; 973 | if (string.indexOf(ch) != -1) 974 | { 975 | return true; 976 | } 977 | return false; 978 | } 979 | 980 | var HiMetricPerUnit = 981 | { 982 | "m": 100000, 983 | "cm": 1000, 984 | "mm": 100, 985 | "in": 2540, 986 | "pt": 35.27778, 987 | "pc": 424.3333 988 | }; 989 | 990 | function HiMetricToUnits(value, unit) 991 | { 992 | var factor = HiMetricPerUnit[units]; 993 | if (factor == null) 994 | return value; 995 | var result = value * (1 / factor); 996 | return result; 997 | } 998 | 999 | function UnitsToHiMetric(value, units) 1000 | { 1001 | var factor = HiMetricPerUnit[units]; 1002 | if (factor == null) 1003 | return value; 1004 | var result = value * factor; 1005 | return result; 1006 | } 1007 | 1008 | function PixelToHiMetric(pixel, dpi) 1009 | { 1010 | var himetric = (pixel * 2540) / dpi; 1011 | return himetric; 1012 | } 1013 | 1014 | function HiMetricToPixel(himetric, dpi) 1015 | { 1016 | var pixel = (himetric * dpi) / 2540; 1017 | return pixel; 1018 | } 1019 | -------------------------------------------------------------------------------- /InkMLjs/svg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/InkMLjs/b4f5de01955ced9fe79d43ddc4bb46cbbdd24885/InkMLjs/svg.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # InkMLjs 2 | 3 | ## Project Description 4 | The InkMLjs JavaScript library allows InkML digital ink to be referenced within web pages and rendered directly into HTML5 `` tags. Ink Markup Language (InkML) is a W3C standard for encoding digital ink ([http://www.w3.org/tr/inkml](http://www.w3.org/tr/inkml)).  5 | The Ink Markup Language serves as the data format for representing ink entered with an electronic pen or stylus.   Products such as Microsoft Office 2010 allow users to draw ink directly into Office documents, and the ink is persisted within the documents as InkML.   The InkMLjs library allows a web page to render InkML generated by Microsoft Office or any other InkML compliant application. 6 | Below are examples of the same InkML rendered within PowerPoint 2010 and within a web page using the InkMLjs library. 7 | 8 | ### InkML rendered in PowerPoint 2010 9 | ![InkML rendered in PowerPoint 2010](/InkMLjs/ink.png) 10 | 11 | ### InkML rendered by InkMLjs Library 12 | |![InkML rendered by InkMLjs Library](/InkMLjs/svg.png)| 13 | |---| 14 | 15 | ## Usage 16 | To use InkMLjs on an HTML page, the page must reference both the JQuery 1.5 library and a copy of the InkMLjs library.   For example: 17 | ```html 18 | 19 | 20 | 21 | ... 22 | 23 | ``` 24 | Then, create an HTML5 `` element where you would like Ink to be rendered on the page.   The `` element must have a `data-inkml-src` attribute which references the inkml file you wish to be rendered.   For example: 25 | ```html 26 | 27 | 28 | ``` 29 | Optionally, you may also specify the `data-inkml-ignorepressure` attribute.   If the value of this attribute is `true`, then and Force channels present in the InkML will be ignored. Without pressure enabled, each continuous stroke within the InkML will be rendered with a single stroke thickness, but it will be drawn using antialiasing.   With pressure enabled, strokes will be rendered with variable widths depending on the pressure applied by the stylus when the ink was original captured, but since SVG and HTML5 Canvases don’t natively support variable width strokes, the variability is approximated by rendering each segment of the stroke separately. This technique makes it possible to approximate variable width strokes, but it destroys antialiasing. Below is an example of a canvas using the `data-inkml-ignorepressure` attribute: 30 | ```html 31 | 32 | 33 | ``` 34 | 35 | | `data-inkml-ignorepressure="true"` | `data-inkml-ignorepressure="false"` (default) | 36 | | --- | --- | 37 | |![ignorepressure true](/nopressure.png)|![ignorepressure false](/pressure.png)| 38 | 39 | The InkMLjs library can also be driven using your own JavaScript code.   Below is an example of JavaScript code loading an inkml file into an `Ink()` object: 40 | ```javascript 41 | $(this).ready(function () { 42 |        $.get("ink1.xml", {}, function (xml, textStatus, jqXHR) { 43 |               var ink = new Ink(xml); 44 |               ... 45 | ``` 46 | Once you have an `Ink()` object, you can resave the object back to InkML XML; 47 | ```javascript 48 |               var inkml = ink.toInkML(); 49 | ``` 50 | Or you can render the `Ink()` into a canvas: 51 | ```javascript 52 |               ink.draw(canvas, ignorePressure); 53 | ``` 54 | Or you can walk the InkML DOM by manipulating its fields such as `.contexts`, `.brushes`, etc. 55 | 56 | ## Not Yet Implemented Features 57 | * InkML `` elements are read, but are not round-tripped via the `toInkML()` method. 58 | * The `traceRef` attribute is not yet implemented. 59 | * Not all brush properties are supported, most notably alpha and brush tip shapes. 60 | * Traces that contain a single point (like a dotted ‘i’ or ‘j’) are not currently supported. 61 | * Named channel types are not currently supported. X and Y are of course supported, but if a third channel is present it assume to always be Force. Any additional channels are ignored. 62 | * An Ink Capture Mode is partially implemented, but it is not complete. 63 | * The `inkSourceRef` attribute is not supported. 64 | * Channel properties for X and Y are assumed to be present (defaults are not provided if they are absent from the InkML) 65 | * First and second order derivative channel values are supported, but the algorithm needs to be refactored to be a single pass. 66 | * First and second order derivate channel values are round-tripped as absolute values via the `toInkML()` method. 67 | * InkML ``'s are not implemented 68 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /nopressure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/InkMLjs/b4f5de01955ced9fe79d43ddc4bb46cbbdd24885/nopressure.png -------------------------------------------------------------------------------- /pressure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/InkMLjs/b4f5de01955ced9fe79d43ddc4bb46cbbdd24885/pressure.png --------------------------------------------------------------------------------