-
Notifications
You must be signed in to change notification settings - Fork 88
/
inkstore.h
1844 lines (1604 loc) · 77.1 KB
/
inkstore.h
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
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
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*--------------------------------------------------------------------------
** File: inkstore.h
**
** Copyright 1993, Slate Corporation, All Rights Reserved.
**
** This document is part of the Jot specification for the storage and
** interchange of electronic ink data. This specification is the joint work
** of representatives of Slate Corporation, Lotus Development Corporation,
** GO, Microsoft, Apple, General Magic, and others.
**
** This document and the accompanying code samples on disk comprise Version
** 1.0 of the Jot specification for the storage and interchange of electronic
** ink data. Permission is granted to incorporate and otherwise use any
** portion of the specification. You may make copies of the specification
** for distribution to others, provided you include the notice "Copyright
** 1993, Slate Corporation. All Rights Reserved" on both the document and
** the disk label. You may not modify this specification without written
** permission from Slate Corporation.
**
** The specification is provided "as is" without warranty of any kind. Slate
** further disclaims all implied warranties of merchantability or of fitness
** for a particular purpose. The entire risk arising out of the use or
** performance of the specification remains with you.
**
**--------------------------------------------------------------------------
**
** This is the main body of definitions for the ink storage specification.
** See reference section 1.0 for revision history.
**
**------------------------------------------------------------------------*/
#ifndef INKSTORE_INCLUDED
#define INKSTORE_INCLUDED
/*************************/
/* REFERENCE SECTION 0.0 */
/*************************/
/*--------------------------------------------------------------------------
** "Rationale for the ink specification"
**
** This document defines a storage and interchange format for embedded ink
** data. The format is device- and platform-independent. The goal is to
** provide application programs on the same and different platforms and
** operating systems a way to store and exchange ink data. Thus a PenPoint
** user might scribble a note and send the untranslated ink as part of an
** e-mail message to a colleague's pen computer running Windows for Pen
** Computing using Magic Mail.
**
** This specification is for a publicly-defined, external format for
** electronic ink data interchange, and neither assumes nor dictates the
** nature of how the application deals with ink data internally. The format
** is not intended to be the "internal" ink format of an application, though
** there is no reason why it could not serve such a purpose.
**
** The scope and goals of this format design are limited to the represent-
** ation of electronic ink data embedded in some other electronic document,
** not to the larger document itself (such as an e-mail or enhanced word-
** processing data file).
**
** The approach taken is to capture the complete user input for the
** electronic ink, including not just X/Y coordinates, but also a large set
** of current drawing attributes such as nib type and ink color. This
** differs from other possible approaches, such as those based on certain
** recognition models for handwritten text, which require decomposing the
** handwritten ink data first into a set of pre-defined approximation curves
** or sub-strokes, and then storing a list of encodings of these sub-strokes.
** In other words, Jot preserves all information about the original input as
** opposed attempting any sort of abstract characterization of the input.
**
** The storage format has a number of properties:
**
** * Simple. Typical operations on the ink data are easy. If you only wish
** to read stroke coordinates and bounding information from the data,
** complex information that might be present will not hinder the process.
** Likewise, it is easy to write out just simple information. The
** complex information is all optional.
**
** * Compact. The storage format is intended to be as compact as possible
** without sacrificing simplicity or fidelity. Optional information such
** as time stamps or color specifications occupy space only when they are
** present. Specifications that apply to many strokes (such as line width
** or color) are represented just once.
**
** * Compression. The stroke information that describes the ink can
** optionally be represented in a compressed format. Compression
** techniques include both compression and reduction of the ink data.
**
** * Inclusive. The format is capable of storing every property of ink
** conceivable as of today.
**
** * Expandable and Compatible. The format is expandable, so as developers
** discover new information that should be recorded in an ink storage
** format, these new features can be added without changing the behavior of
** existing application programs working with an older version of the
** format. In general, new features can generally be ignored by
** applications reading older versions of the format. Likewise, new
** application programs can handle previous versions of the format without
** special work.
**
** The format is not designed to easily support lots of in-memory
** manipulation of the ink data, such as deleting strokes, changing line
** widths, and so on. A format supporting these types of manipulations would
** be at odds with the above goals. All the information needed to perform
** these manipulations is present in this data format, so an application
** might augment this format to facilitate manipulation of the ink data.
**
** Applications are likely to use some other format internally for real-time
** ink manipulation. Many operating environments provide some internal means
** for storing and manipulating ink data, the details of which may be hidden
** to some extent from the application designer. Many such real-time data
** structures store fewer types of and/or less information (such as not
** preserving information about the tablet point data rate) than are covered
** in this definition.
**
**------------------------------------------------------------------------*/
/*************************/
/* REFERENCE SECTION 1.0 */
/*************************/
/*-------------------------------------------------------------------------
** Jot Ink Specification
** ---------------------
**
** Revision History:
**
** March 16, 1992 - First public draft.
** July 13, 1992 - Major rewrite to put data into a series of records.
** July 19, 1992 - Inclusion of ink-compacting definitions.
** July 30, 1992 - Change of target rect to offset.
** December 28, 1992 - Changes incorporated from August 1992 review meeting.
** February 12, 1993 - Incremental fixes due to coding experience.
** March 13, 1993 - Revised definition of a "group".
** April 12, 1993 - Release of version 0.99 of the specification. Moved
** reference sections 28 and 29 to a separate file called
** sample.h
** May 01, 1993 - Release of version 1.00 of the specification.
** Changed INK_OFFSET_RECORD units from twips to pen
** units for consistency and ease of implementation.
** Fixed a typo in reference section 26.0 in the diagram.
** The text accompanying the diagram was correct.
** Fixed a typo in reference section 27.0. The old text
** "delta-X == 0 or 1" was replaced with the correct text
** "delta-X == 2". The accompanying diagram was correct.
** Removed all sizeof() constructs and replaced with
** appropriate #defines to reduce compiler dependencies.
** Tagged all struct definitions with tag_ prefix.
** Added comments and reordered some existing comments.
** May 17, 1993 - Added a few more _SIZE #defines, clarified reserved
** values.
**
**
** GENERAL NOTES
** -------------
**
**
** Record Structure
** ----------------
**
** If not otherwise specified, all words are stored in Intel order: low-order
** word first, then high-order word, and inside of a word, low-order byte,
** then high-order byte. For example, a 32 bit quantity 0x12345678 would be
** written to the file as 0x78 0x56 0x34 0x12. The notable exception is the
** storage of point data in "standard compression" format. Sign bits are
** used to indicate item types, so the bytes are stored high-order to low-
** order (exactly opposite). See the sample code and reference section 23.0
** for more information on the compressed format. Uncompressed data is
** written in Intel order.
**
** All structures are packed for the purposes of writing to a stream.
**
** Signed integer values are two's-complement. Rectangles are stored
** x,y,w,h.
**
** These definitions are intended to insulate the sample ink compaction and
** storage code from any possible variation in item alignment or structure
** packing across architectures. The only possible area of portability
** concern lies in the use of unions in colors (see 11.0) and pen tips (see
** 14.0).
**
** Any use of units of mass to denote units of force ("grams of force"), or
** similar common misuses of physical units, are noted here with an apology
** to any purists, and should be interpreted in the common way by assuming
** one standard gravity.
**
** Record Sequence
** ---------------
**
** In this document, one piece of ink data is called an ink bundle.
** Typically this might correspond to the strokes that make up the ink from
** the time when the pen touches down until the user finishes writing
** (usually determined by a timeout or the pen leaving proximity). Thus an
** ink bundle usually contains many ink strokes, and the strokes do not have
** to describe a continuous line of ink.
**
** As stated in reference section 5.0, all data conforming to this
** specification appears as a stream of ink bundles each of which must begin
** with an INK_BUNDLE_RECORD and end with an INK_END_RECORD. There may be
** more than one INK_BUNDLE_RECORD/INK_END_RECORD pair in a given stream.
** A record stream might look something like this:
**
** INK_BUNDLE_RECORD required // for bundle number one
** INK_SCALE_RECORD optional // sets the scale for rendering
** INK_OFFSET_RECORD optional // sets the offset for rendering
** INK_COLOR_RECORD optional // sets the color for rendering
** INK_START_TIME_RECORD optional // sets the relative start time
** INK_PENTIP_RECORD optional // sets the pentip for rendering
** INK_GROUP_RECORD optional // tags the following PENDATA
** INK_PENDATA_RECORD recommended // actual points
** INK_GROUP_RECORD optional // tags the following PENDATA
** INK_PENDATA_RECORD recommended // actual points
** INK_PENDATA_RECORD recommended // more points in same group
** INK_SCALE_RESET_RECORD optional // resets to default scaling/offset
** INK_PENDATA_RECORD recommended // actual points
** INK_END_TIME_RECORD optional // relative time inking ended
** INK_END_RECORD required // end of bundle number one
**
** It is perfectly reasonable to write out only the following (though doing
** so will cause the ink to be rendered in a completely default manner --
** black hairline width at 1:1 scaling with offset 0):
**
** INK_BUNDLE_RECORD
** INK_PENDATA_RECORD
** INK_END_RECORD
**
**
** Specification Revisions
** -----------------------
**
** Future enhancements to this specification may modify certain record types.
** It is guaranteed that any record modified in a subsequent revision of the
** specification will be a strict superset of that record's definition in any
** previous revision of the specification. That is, modified record types
** will only be lengthened, not shortened. If a particular record type must
** be extended such that it would not be a superset of the original, a new
** record type would be added to cover that particular extension.
**
** This extension strategy has two important ramifications:
**
** 1) A reading application should *ALWAYS* use the size of a record as
** recorded in the record structure itself (i.e., the recordLength field
** of the INK_RECORD_HEADERx structure) rather than the sizeof() or any
** other size determined at compile time to determine how may bytes to
** read as the data structures are parsed. This is due to the fact that
** a record may grow in a future revision of the standard. The only
** exception to this rule is the INK_BUNDLE_RECORD which contains a
** version number that will be modified with each change to that record.
** If an INK_BUNDLE_RECORD is encountered and its version matches the
** version used at compile time, the size of the record should exactly
** match the #define of inkRecordBundleSize.
**
** 2) Any particular record may be read into a target data structure up to
** the size of the target data structure and the rest may be ignored.
** This is due to the 'strict superset' rule which means that any
** extension of any record type must leave the meaning, content, and size
** of any existing fields as is. So, for example, if an INK_SCALE_RECORD
** was modified by adding 2 bytes, the reading application can safely read
** the data into the INK_SCALE_RECORD known at compile time and throw
** away the extra two bytes: the header, x, and y will be in the same
** place and will have the same meaning.
**
**
** Files of Ink
** ------------
**
** It is a recommended practice on DOS and UNIX style file systems to use the
** extension ".JOT" for files consisting solely of ink recorded according to
** this specification. The specification is designed such that ink data can
** be embedded inside any file format and if such a file contains more than
** strictly ink data, it should not use the .JOT extension.
**
**------------------------------------------------------------------------*/
/*************************/
/* REFERENCE SECTION 2.0 */
/*************************/
/*-------------------------------------------------------------------------
** Definitions used in this header.
**
** These definitions must be defined appropriately to the target environment
** and compiler.
**
** For example, on some compilers for environments using segmented addressing
** and 64K segments sizes, the correct definition of FAR would be "_huge",
** rather than "_far", because the objects pointed to may be larger than 64K.
**
** In particular, check the definitions of FAR, U32, and S32 for
** compatibility with your compiler, environment, and memory model.
**
**------------------------------------------------------------------------*/
#ifndef FAR
#define FAR
#endif
/* useful constants */
#define flag0 (0x0001)
#define flag1 (0x0002)
#define flag2 (0x0004)
#define flag3 (0x0008)
#define flag4 (0x0010)
#define flag5 (0x0020)
#define flag6 (0x0040)
#define flag7 (0x0080)
#define flag8 (0x0100)
#define flag9 (0x0200)
#define flag10 (0x0400)
#define flag11 (0x0800)
#define flag12 (0x1000)
#define flag13 (0x2000)
#define flag14 (0x4000)
#define flag15 (0x8000)
#define flag16 (0x00010000L)
#define flag17 (0x00020000L)
#define flag18 (0x00040000L)
#define flag19 (0x00080000L)
#define flag20 (0x00100000L)
#define flag21 (0x00200000L)
#define flag22 (0x00400000L)
#define flag23 (0x00800000L)
#define flag24 (0x01000000L)
#define flag25 (0x02000000L)
#define flag26 (0x04000000L)
#define flag27 (0x08000000L)
#define flag28 (0x10000000L)
#define flag29 (0x20000000L)
#define flag30 (0x40000000L)
#define flag31 (0x80000000L)
#define TRUE 1
#define FALSE 0
/* void pointers */
typedef void FAR *P_UNKNOWN;
typedef P_UNKNOWN FAR *PP_UNKNOWN;
#define pNull ((P_UNKNOWN)0)
/* Unsigned integers */
typedef unsigned char U8, FAR *P_U8;
#define U8_SIZE 1
typedef unsigned short U16, FAR *P_U16;
#define U16_SIZE 2
typedef unsigned long U32, FAR *P_U32;
#define U32_SIZE 4
/* Signed integers */
typedef char S8, FAR *P_S8;
#define S8_SIZE 1
typedef short S16, FAR *P_S16;
#define S16_SIZE 2
typedef long S32, FAR *P_S32;
#define S32_SIZE 4
/*
typedef signed char S8, FAR *P_S8;
#define S8_SIZE 1
typedef signed short S16, FAR *P_S16;
#define S16_SIZE 2
typedef signed long S32, FAR *P_S32;
#define S32_SIZE 4
*/
/* geometry structures */
typedef struct tag_XY32 {
S32 x;
S32 y;
} XY32, FAR *P_XY32;
#define XY32_SIZE (S32_SIZE+S32_SIZE)
typedef struct tag_XY16 {
S16 x;
S16 y;
} XY16, FAR *P_XY16;
/*-------------------------------------------------------------------------
** Note:
** Angles from vertical can exceed +-90 degrees: in this case, the "back" end
** of the stylus is nearer the tablet surface than the "front" end.
**-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------
** Note:
** Standard compaction will normally store angles in nibbles, or single
** bytes, rather than in four-byte records.
**-------------------------------------------------------------------------*/
typedef struct tag_ANGLE16 {
S16 theta; /* "X" angle of the stylus, degrees from vertical, */
/* increasing in the positive "X" direction. */
S16 phi; /* "Y" angle of the stylus. */
} ANGLE16, FAR *P_ANGLE16;
#define ANGLE16_SIZE (S16_SIZE+S16_SIZE)
typedef struct tag_SIZE32 {
S32 w;
S32 h;
} SIZE32, FAR *P_SIZE32;
#define SIZE32_SIZE (S32_SIZE+S32_SIZE)
typedef struct tag_SIZE16 {
S16 w;
S16 h;
} SIZE16, FAR *P_SIZE16;
#define SIZE16_SIZE (S16_SIZE+S16_SIZE)
/*-------------------------------------------------------------------------
** Note:
** A rect where xmin==xmax and ymin==ymax has a size of zero:
** size.w and size.h are both zero.
**-------------------------------------------------------------------------*/
typedef struct tag_RECT32 {
XY32 origin;
SIZE32 size;
} RECT32, FAR *P_RECT32;
#define RECT32_SIZE (XY32_SIZE+SIZE32_SIZE)
typedef U32 FIXED_FRACTION; /* fixed point value, unity = 0x00010000 */
#define FIXED_FRACTION_SIZE U32_SIZE
#define INK_UNITY_SCALE ((U32) 0x00010000L)
/*************************/
/* REFERENCE SECTION 3.0 */
/*************************/
/*-------------------------------------------------------------------------
** A block of ink data is called an ink bundle. Each ink bundle consists of
** a series of n records. Each record has a common header that indicates the
** record type and the record length. An ink bundle always starts with an
** INK_BUNDLE_RECORD and always ends with an INK_END_RECORD.
**
** Any records of unknown type can be skipped by simply reading the length of
** the record.
**
** Note:
** Within an ink bundle, time increases. This implies a drawing order of
** back-to-front. Between adjacent sequential bundles, the implicit drawing
** is also back-to-front.
**
** A number of record types are defined. The most common is the
** inkRecordPenData which contains the actual pen data. Other records are
** mostly attributes of the pen data and are optional. They will, in
** general, only be present when a given attribute changes to something
** different than the default value for that attribute.
**
** In order to have the most compact format and also allow large records,
** several different record headers are defined, each with a different
** length.
**
** The top two bits of the record type indicate what kind of record length
** follows:
**
** The record length can be:
**
** - non-existent (the entire record consists of just the recordType)
** - An 8 bit length (one byte) for records up to 255 bytes
** - A 16 bit length (two bytes) for records up to 64k
** - A 32 bit length (four bytes) for really big records
**
**------------------------------------------------------------------------*/
#define inkRecordNoLength 0 /* no length, just recordType */
#define inkRecordLength8 flag14 /* 8 bit length */
#define inkRecordLength16 flag15 /* 16 bit length */
#define inkRecordLength32 (flag15 | flag14) /* 32 bit length */
/* useful defines for isolating or clearing the length type bits */
#define inkRecordLengthMask (flag15 | flag14) /* mask for length bits */
#define inkRecordLengthClearMask (~inkRecordLengthMask)
/* some useful macros for declaring the various types of record types */
#define MakeRec0(recType) (recType | inkRecordNoLength) /* no rec length */
#define MakeRec8(recType) (recType | inkRecordLength8) /* 8 bit length */
#define MakeRec16(recType) (recType | inkRecordLength16) /* 16 bit length */
#define MakeRec32(recType) (recType | inkRecordLength32) /* 32 bit length */
typedef U16 INK_RECORD_TYPE, FAR *P_INK_RECORD_TYPE;
#define INK_RECORD_TYPE_SIZE U16_SIZE
#define inkRecordHeaderLength(record_type) \
( (((record_type) & inkRecordLength32) == inkRecordNoLength) ?\
INK_RECORD_TYPE_SIZE \
: (((record_type) & inkRecordLength32) == inkRecordLength8) ?\
INK_RECORD_TYPE_SIZE+U8_SIZE \
: (((record_type) & inkRecordLength32) == inkRecordLength16) ?\
INK_RECORD_TYPE_SIZE+U16_SIZE \
: INK_RECORD_TYPE_SIZE+U32_SIZE \
)
/*-------------------------------------------------------------------------
** Note: most compilers will not generate code for the above macro but will
** determine the proper value at compile time.
**-------------------------------------------------------------------------*/
/*************************/
/* REFERENCE SECTION 4.0 */
/*************************/
/*-------------------------------------------------------------------------
** These are all the currently defined record types. The macro MakeRecX()
** encodes the right bits in with the record Id to define its recordLength.
**
** For simplicity, recType values may not be repeated for different
** INK_RECORD_TYPEs. Use of a record type defined as MakeRec32(63) thus
** forbids the use of a record type defined as MakeRec16(63), MakeRec8(63),
** or MakeRec0(63).
**
** Record type 63 is reserved explicitly for possible future extension beyond
** 63 record types.
**
**------------------------------------------------------------------------*/
#define inkRecordEnd MakeRec0( 0) /* end of bundle */
#define inkRecordBundle MakeRec8( 1)
#define inkRecordPenData MakeRec32( 2)
#define inkRecordScale MakeRec8( 3)
#define inkRecordScaleReset MakeRec0( 4)
#define inkRecordColor MakeRec8( 5)
#define inkRecordTip MakeRec8( 6)
#define inkRecordGroup MakeRec8( 7)
#define inkRecordOffset MakeRec8( 8)
#define inkRecordStartTime MakeRec8( 9)
#define inkRecordEndTime MakeRec8( 10)
#define inkRecordPointsPerSecond MakeRec8( 11)
#define inkRecordUnitsPerZ MakeRec8( 12)
#define inkRecordUnitsPerForce MakeRec8( 13)
/* Record types 14 .. 61 are reserved for future definition. */
#define inkRecordApp MakeRec32(62) /* application-specific records*/
#define inkRecordExt MakeRec32(63) /* reserved for extension */
/*-------------------------------------------------------------------------
** Every record starts with a header that contains the recordType and the
** recordLength. The recordType indicates the type of data here. The
** recordLength indicates the total length of all the data for the record
** (including the size of the header).
**-------------------------------------------------------------------------*/
/* no recordLength */
typedef struct tag_INK_RECORD_HEADER0 {
INK_RECORD_TYPE recordType;
} INK_RECORD_HEADER0, FAR *P_INK_RECORD_HEADER0;
/* 8 bit recordLength */
typedef struct tag_INK_RECORD_HEADER8 {
INK_RECORD_TYPE recordType;
U8 recordLength;
} INK_RECORD_HEADER8, FAR *P_INK_RECORD_HEADER8;
/* 16 bit recordLength */
typedef struct tag_INK_RECORD_HEADER16 {
INK_RECORD_TYPE recordType;
U16 recordLength;
} INK_RECORD_HEADER16, FAR *P_INK_RECORD_HEADER16;
/* 32 bit recordLength */
typedef struct tag_INK_RECORD_HEADER32 {
INK_RECORD_TYPE recordType;
U32 recordLength;
} INK_RECORD_HEADER32, FAR *P_INK_RECORD_HEADER32;
/*************************/
/* REFERENCE SECTION 5.0 */
/*************************/
/*-------------------------------------------------------------------------
** A bundle of ink consists of an INK_BUNDLE_RECORD, a series of records,
** terminated with an INK_END_RECORD.
**
** An INK_BUNDLE_RECORD, along with a matching INK_END_RECORD, are the
** mandatory records in the format. The ink data must start with an
** INK_BUNDLE_RECORD.
**
** It is suggested that anyone reading this format do a number of validity
** checks on the first record in any ink data. The first record should meet
** the following minimum requirements:
**
** 1) header.recordType == INK_RECORD_BUNDLE
** 2) header.recordLength >= inkRecordBundleSize (See general notes in
** reference section 1.0 for important information about record sizes.)
** 3) compactionType is an expected and supported value
** 4) penUnitsPerX and penUnitsPerY seem reasonable and expected:
** greater than, say, 1000 units per meter (25.4/inch), less than, say,
** 400,000 (~10,000 units per inch)
**
**------------------------------------------------------------------------*/
typedef struct tag_INK_END_RECORD {
INK_RECORD_HEADER0 header; /* value is inkRecordEnd */
} INK_END_RECORD, FAR *P_INK_END_RECORD;
#define inkRecordEndSize (inkRecordHeaderLength(inkRecordEnd))
/*************************/
/* REFERENCE SECTION 6.0 */
/*************************/
/*-------------------------------------------------------------------------
** The terms compression and compaction are used somewhat interchangeably
** in this specification but they actually have slightly different meanings
** and are both supported to a certain extent by Jot.
**
** Compression refers to a technique of encoding data such that the resuling
** data, while smaller, is still whole. That is, compression under Jot is
** loss-less. Compaction refers to a process where certain pieces of less
** important data are actually omitted from the stream and are possibly
** reconstructed by the reader of the data.
**
** Using Jot, a writing application may choose to compress only, compact only
** or use some combination. The standard compression mechanism defined here
** and implemented in the sample code supports both notions.
**
**------------------------------------------------------------------------*/
typedef U8 INK_COMPACTION_TYPE, FAR *P_INK_COMPACTION_TYPE;
#define INK_COMPACTION_TYPE_SIZE U8_SIZE
#define inkNoCompression (0)
#define inkStdCompression (1)
/*-------------------------------------------------------------------------
** Other compression schemes may be adopted in future revisions of this
** specification.
**-------------------------------------------------------------------------*/
/*************************/
/* REFERENCE SECTION 7.0 */
/*************************/
/*-------------------------------------------------------------------------
** The INK_BUNDLE_FLAGS contain some flags that apply to an entire bundle.
** If you wanted to store several pieces of ink that had different
** INK_BUNDLE_FLAGS, you would do it by storing several different bundles.
**
** Advisory flags:
**
** inkPointsRemoved
** Indicates whether all original points are still present or whether
** some points were removed to save space. For applications that are
** only interested in the visual aspects of ink, many points can be
** removed that do not affect the appearance (i.e. duplicate points,
** collinear points, points which deviate less than some screen
** resolution, etc..). Some other types of applications must know that
** points are present at some consistent sampling rate (i.e. some forms
** of handwriting translation). This flag indicates whether all
** original points are still there.
**
** Note:
** The purpose of "inkPointsRemoved" is to indicate that the timing
** information cannot be accurately derived by counting points:
** replacing individual points with an "elided point" item does not
** constitute removing points. ("Elided" means omitted or skipped).
**
** inkProxDataRemoved
** Indicates that the original points between strokes (proximity) were
** removed to save space. An out-of-prox point should be stored between
** strokes to delimit them. Some applications depend on knowing the
** time between strokes or at the ends of strokes for certain
** functions.
**
** Note:
** "Proximity" is defined as the stylus being close enough to the tablet
** for the tablet to report the stylus position, although perhaps at
** lower accuracy and perhaps at a lower number of points per second. A
** recommended practice is to include "out of proximity" points in the
** recorded ink data when they are used as part of determining the
** amount of time a stylus was out of contact with the tablet, or for
** triggering the completion of an action such as a "gesture".
**
** inkStrokeLimitsPresent
** Indicates that INK_BUTTONS items are also present, and that they
** indicate what the storing app decided the stroke start/end points
** were. (Note: the reading application may otherwise use a different
** algorithm for using tip force values to delimit strokes.)
**
** Note:
** If inkStrokeLimitsPresent is set, then inkButtonDataPresent must also
** be set.
**
** Data flags:
**
** inkAngleDataPresent indicates angle data is present.
** inkForceDataPresent indicates force data is present.
** inkProxDataPresent indicates points are present when pen is lifted
** up (i.e. the force drops below some threshold).
** inkRotationDataPresent indicates pen rotation data is present.
** inkHeightDataPresent indicates pen height data is present.
** inkButtonDataPresent indicates "button state" information is present.
** inkPreMultiplyScale indicates that scaling should be applied before
** the offset value is added ("pre-multiply")
** rather than after ("post-multiply")
**
** Note:
** A previous draft version included a provision for compacting data to an
** approximation based on Bezier curves. Initial results did not show
** promise in terms of efficiency and performance.
**
** "inkBezierRepresentation" would have indicated that the X/Y ordinates
** reflected a Bezier approximation to the original tablet data. This would
** have meant that the ordinate data represented aggregates of anchor points
** and control points for each piece wise approximation, and therefore could
** not be used directly to render the data. The definition of these anchor
** and control points, and the example code for the approximation and
** regeneration of the "true" coordinates could not be worked out at this
** time.
**
** Some standard values for pen units per meter follow:
**
** 1000 points per inch digitizer == 39370 pen units per meter
** 500 points per inch digitizer == 19685 pen units per meter
** 200 points per inch digitizer == 7874 pen units per meter
** 254 points per inch (1/10 mm) == 10000 pen units per meter
**
** 1000 pen units per meter is a reasonable minimum; 400,000 is a reasonable
** maximum value.
**
** The specific format for each of these types of data is described in the
** INK_PENDATA_RECORD documentation (reference section 8.0).
**
** Note:
** The order in which these flags are defined has nothing to do with the
** order in which the data appears in the INK_POINT structure when reading
** or writing point data. For more information, see reference section 21.0.
**
**------------------------------------------------------------------------*/
typedef U16 INK_BUNDLE_FLAGS, FAR *P_INK_BUNDLE_FLAGS;
#define INK_BUNDLE_FLAGS_SIZE U16_SIZE
#define inkPointsRemoved (flag0)
#define inkProxDataRemoved (flag1)
#define inkAngleDataPresent (flag2)
#define inkForceDataPresent (flag3)
#define inkRotationDataPresent (flag4)
#define inkHeightDataPresent (flag5)
#define inkButtonDataPresent (flag6)
#define inkStrokeLimitsPresent (flag7)
#define inkPreMultiplyScale (flag8)
/*-------------------------------------------------------------------------
** Reserved: flag9, flag10, flag11, flag12, flag13, flag14, flag15.
** More flags beyond flag15 can be added in a new record type
** in a later revision to this specification.
**-------------------------------------------------------------------------*/
typedef struct tag_INK_BUNDLE_RECORD {
INK_RECORD_HEADER8 header; /* value is inkRecordBundle */
U8 version; /* Value for release 1.0 is 1 */
INK_COMPACTION_TYPE compactionType;
INK_BUNDLE_FLAGS flags; /* flags for the whole bundle */
U32 penUnitsPerX; /* pen units per meter (x dir) */
U32 penUnitsPerY; /* pen units per meter (y dir) */
} INK_BUNDLE_RECORD, FAR *P_INK_BUNDLE_RECORD;
#define inkPointDefaultVersion (1)
#define inkPointDefaultCompactionType (inkStdCompression)
#define inkPointDefaultBundleFlags (0)
#define inkPointDefaultPenUnitsPerX (1000)
#define inkPointDefaultPenUnitsPerY (1000)
#define inkRecordBundleSize \
(inkRecordHeaderLength(inkRecordBundle) + U8_SIZE + \
INK_COMPACTION_TYPE_SIZE + INK_BUNDLE_FLAGS_SIZE + \
U32_SIZE + U32_SIZE)
/*************************/
/* REFERENCE SECTION 8.0 */
/*************************/
/*-------------------------------------------------------------------------
** A penData record contains the actual pen data for one or more pen strokes.
** The bounds applies to all the strokes contained within this record.
** Multiple strokes are typically grouped into one record to increase the
** efficiency of the compression algorithm, though strokes may be stored
** individually, if desired.
**
** The bounds is the pure mathematical bounds of the raw pen points and does
** not take into account any rendering information such as the pen tip or the
** line width. All points in the INK_PENDATA have been normalized relative
** to the lower bounds in the INK_PENDATA header.
**
** Some applications will prefer to know the bounds of individual strokes.
** This can be accomplished in two ways.
**
** 1) The bounds for a given stroke can be computed when reading the file
** by decompressing an INK_PENDATA_RECORD into its strokes and then
** traversing the points in each stroke to build the bounds for each
** stroke.
**
** 2) An application can decide to store only one stroke per
** INK_PENDATA_RECORD (and thus the bounds of the PENDATA_RECORD is
** already the bounds of one stroke). The sacrifice here is in
** compression efficiency and the need to still support reading files
** written by other applications that might group multiple strokes
** into a single INK_PENDATA_RECORD.
**
** Note:
** In practice, our experience is that unpacking the data in order to compute
** the bounds for each stroke to check for strokes that intrude into a given
** region is not an excessive burden. The checks that would have been done
** on the bounds of each stroke can be done on the builds for each penData
** group, and not all strokes must be checked individually.
**
** The format of the pen data is determined by the settings for
** compactionType and flags in the INK_BUNDLE_RECORD structure, and
** is described later in this file. Two formats are currently defined:
** an uncompacted format and a delta-encoded compacted format, both with
** optional components present or absent depending on the state of the flags
** in the INK_BUNDLE_RECORD.
**
**------------------------------------------------------------------------*/
typedef struct tag_INK_PENDATA_RECORD {
INK_RECORD_HEADER32 header; /* value is inkRecordPenData */
RECT32 bounds;
U8 inkData[1]; /* ink data goes here: definitions */
/* follow later in this file. */
} INK_PENDATA_RECORD, FAR *P_INK_PENDATA_RECORD;
#define inkRecordPenDataSize(data_length) \
(inkRecordHeaderLength(inkRecordPenData) + RECT32_SIZE + (data_length))
/*************************/
/* REFERENCE SECTION 9.0 */
/*************************/
/*-------------------------------------------------------------------------
** Ink scale is recorded in two fixed point values. A unity scale (scale
** of one) is represented as 0x00010000, a scale of 0.5 as 0x00008000.
**
** Note:
** All ink is located relative to the lower-left (0,0) corner of a logical
** page or window. Scale and offset operations are cumulative, much in the
** same way as in PostScript. One begins with a normalized graphics state
** and sequentially applies the scale and offset operations to that matrix.
** The INK_SCALE_RESET record returns the graphics state to its default state
** (i.e., the transformation matrix is set to an identity matrix and the
** offset is reset to the default of 0). By default, scaling is applied
** after adding in any offset specified in an INK_OFFSET_RECORD. If the ink
** bundle has the inkPreMultiplyScale bit set, for all ink in that bundle
** scaling is applied before adding in any offset.
**
** As used in this format, ink scale and offset values are set by the storing
** application, to be applied by the rendering application. If the storing
** application collected the ink at scales of (2.0,2.0), the storing
** application should insert an INK_SCALE_RECORD with a scale of (0.5,0.5)
** for the rendering application to multiply all ink X and Y coordinates by.
**
** It is the responsibility of the storing application to deal with any
** effects from round-off or truncation error due to the limits of precision
** in the FIXED_FRACTION values used in INK_SCALE_RECORDs.
**
** An ink scale record indicates a scale change that stays in effect until
** another ink scale record is encountered. Ink scale values compound: if
** the current scale is (2.0,2.0) and an INK_SCALE_RECORD is encountered with
** scale of (2.0,3.0), the scale to be applied to ink then becomes(4.0,6.0).
** In absence of any ink scale record, the default ink scale is unity. In
** general, a typical usage pattern for an application that supports drawing
** ink while zoomed at scale is to record a number of strokes at a given
** scale, reset the scale with an INK_SCALE_RESET_RECORD (which resets both
** the scale and the offset to the default values), then switch to another
** scale, then record a number more strokes, and so on.
**
** Note:
** The extension scaling and offset to the Z ordinate value is not defined in
** this version of the specification. The extension to Z scaling and offset
** in a "standard" record type (i.e. not an application-specific record) may
** be addressed in the future.
**
**------------------------------------------------------------------------*/
typedef struct tag_INK_SCALE {
FIXED_FRACTION x; /* scale in the x direction */
FIXED_FRACTION y; /* scale in the y direction */
} INK_SCALE, FAR *P_INK_SCALE;
#define INK_SCALE_SIZE (FIXED_FRACTION_SIZE+FIXED_FRACTION_SIZE)
#define inkPointDefaultScale (INK_UNITY_SCALE) /* Unity. */
typedef struct tag_INK_SCALE_RECORD {
INK_RECORD_HEADER8 header; /* value is inkRecordScale */
INK_SCALE scale;
} INK_SCALE_RECORD, FAR *P_INK_SCALE_RECORD;
#define inkRecordScaleSize \
(inkRecordHeaderLength(inkRecordScale) + \
FIXED_FRACTION_SIZE + FIXED_FRACTION_SIZE)
/**************************/
/* REFERENCE SECTION 10.0 */
/**************************/
/*-------------------------------------------------------------------------
** The offset position is used to relocate ink data, after scaling. For
** example, in a forms application, ink in a sketch field is drawn relative
** to a given sketch field in the form. The location of this original field
** is important to know so we know how the ink in this bundle relates to its
** original field. If we wanted to move this ink to another field (i.e.
** cut/paste or move), we would need to know the location of the original
** field so we could render the ink in the new field in a manner consistent
** with how it was drawn relative to its original field (i.e. a similar
** baseline for a hand-written signature).
**
** This record is optional. If it exists, it will then apply to all
** following pen data in the file. If it is not present it is assumed that
** no information of this type is relevant. For example, while field ink
** would have an offset position, markup ink over an entire form would not
** have a offset position (or would have an offset position of (0,0) and a
** scale of (1,1)) because it is relative to the entire form coordinate
** system, not relative to some piece in the form.
**
** Note:
** This approach allows a reader to "blindly" apply the scale and offset
** values specified to ink data, and puts the burden for computing
** compounding of multiple zoom levels, etc., on the writing application.
**
**------------------------------------------------------------------------*/
typedef struct tag_INK_OFFSET_RECORD {
INK_RECORD_HEADER8 header; /* value is inkRecordOffset */
XY32 positionOffset; /* values are in pen units */
} INK_OFFSET_RECORD, FAR *P_INK_OFFSET_RECORD;
#define inkRecordOffsetSize \
(inkRecordHeaderLength(inkRecordOffset) + XY32_SIZE)
#define inkPointDefaultOffset ((S32) 0) /* No offset. */
typedef struct tag_INK_SCALE_RESET_RECORD {
INK_RECORD_HEADER0 header; /* value is inkRecordScaleReset */
} INK_SCALE_RESET_RECORD, FAR *P_INK_SCALE_RESET_RECORD;
#define inkRecordScaleResetSize (inkRecordHeaderLength(inkRecordScaleReset))
/**************************/
/* REFERENCE SECTION 11.0 */
/**************************/
/*-------------------------------------------------------------------------
** Ink color is represented as an rgb value, plus opacity.
**
** The default color is black (r,g,b,o) = (0,0,0,255). A color change
** present in the file remains in effect until another color change.
** Typically, the color will stay the same for many ink strokes and thus
** a color record will only be used occasionally when the color changes.
**
** "Opacity" is rather vaguely understood, especially in color environments.
** In this context, opacity means the degree to which the display underneath
** the ink shows through. An opacity value of 255 means that nothing under
** the ink shows through; 0 means that everything shows through (the ink
** is transparent). It is up to the reading application to define the
** implementation of opacity on the reading platform.
**
** The color/opacity value of (255,255,255,0), or "transparent white" is
** defined as an "erase" color. In inking applications that support a true
** "erase" function, such as the ability to erase annotation ink on an
** "original" document (perhaps a FAX image) the "erase" color restores the
** background image where painted. The "background image" is defined by the
** rendering application.
**
** Applications which do not support a true "erase" function may interpret
** this as some other drawing function, such as drawing the "background"
** color.