Check-in [9ded1921bb]

Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Define the C API for TIP 164
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 9ded1921bbad7519169807950234f47d1b45ef3c8262da7b840b3daeb1bcb70e
User & Date: dkf 2019-03-15 09:49:25.249
Context
2019-03-16
14:14
TIP #535 now in voting state check-in: 1f3769a7f4 user: fvogel tags: trunk
2019-03-15
09:49
Define the C API for TIP 164 check-in: 9ded1921bb user: dkf tags: trunk
2019-03-11
09:48
Make links work in TIP 535 check-in: 2a3fca6a1a user: dkf tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to tip/164.md.
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

This TIP proposes to add a **rotate** subcommand to the **canvas** widget
to facilitate rotating items in very much the same way as is now
possible with scaling and moving.

# Rationale

The canvas currently allows a programmer to scale and move items, but
the third common affine transformation, rotation, is not supported.
This can in itself be simulated by a script \(simply get the
coordinates of all items involved, transform them and set the new
coordinates\), but if you have several hundreds or even thousands of
items this gets very slow.

Rotation is easy for polygons and lines: simply transform the
coordinates.  For circles and circular arcs new bounding boxes must be
calculated and in addition for arcs the starting angle must be
changed.

Implementing rotation should consider what to do with items that can
not \(easily\) be rotated: text items, rectangles, non-circular ovals
and arcs, widgets and images.  Currently, text can not be drawn at an
arbitrary angle, so I propose to only transform the coordinates at
which the text is "anchored".  A similar strategy can be used for
widgets and images.



For rectangles and general ovals and arcs there are two choices:

 * Transforming the item into a polygon would solve the definition
   problem \(these items are defined by a bounding box and the
   orientation is implicitly assumed\), but might break scripts that
   look for a particular type of item.

 * Therefore we will simply calculate a new bounding box and _ignore
   changes in orientation_.
















# Proposal

Canvases will have a new subcommand, **rotate**, which will rotate the coordinates of chosen items by a specified angle about a specified point.

 > _canvas_ **rotate** _itemOrTag_ _x_ _y_ _angle_

Note that most of the arguments are very similar to the canvas's **scale** subcommand.  _Angle_ is measured in degrees, with positive values indicating anti-clockwise rotation.



## Canvas Item C API Alterations







[These are required for this TIP, but are not yet done.]














# Reference Implementation

See the `tip-164` branch.

# Future Work








|
|
|
|
<
|

|
<
<
<

|
|
|
|
<
<
>
>



|
|
|
|

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|

|
>
>



>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>







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

This TIP proposes to add a **rotate** subcommand to the **canvas** widget
to facilitate rotating items in very much the same way as is now
possible with scaling and moving.

# Rationale

The canvas currently allows a programmer to scale and move items, but the
third common affine transformation, rotation, is not supported.  This can in
itself be simulated by a script \(simply get the coordinates of all items
involved, transform them and set the new coordinates\), but if you have

several hundreds or even thousands of items this gets very slow.

Rotation is easy for polygons and lines: simply transform the coordinates.




Implementing rotation should consider what to do with items that can not
\(easily\) be rotated: rectangles, non-circular ovals and arcs, widgets,
bitmaps and images. For the items that only define a single coordinate, the
anchor point, we just transform that anchor point. (It would require major


work to Tk's rendering engine to allow rotated embedded images, and rotated
windows would be even more complex than that.)

For rectangles and general ovals and arcs there are two choices:

 * Transforming the item into a polygon would solve the definition problem
   \(these items are defined by a bounding box and the orientation is
   implicitly assumed\), but might break scripts that look for a particular
   type of item. This is best left to user code.

 * Therefore we will simply calculate a new bounding box and _ignore changes
   in orientation_. However, this cannot be done by just applying the general
   rotation transformation to the bounding box definition coordinates because
   this radically transforms the shape of the item, in some cases in ways that
   are highly surprising.  Instead, we compute a virtual anchor point for the
   item (arbitrarily chosen to be its center), rotate that about the origin
   point, and then update the item bounding box to be the same shape as before
   in the same orientation as before but now centered on the new virtual
   anchor point.

Text items can be rotated, but they are often used with rectangles to make
labelled boxes so the rotation of them with respect to their anchor is left
for user code. Similarly, arc items have angles associated with them for where
they start and end, but it isn't clear how those should be rotated when the
item itself cannot be rotated (since we don't allow choosing angles for the
major and minor axes of the underlying ellipse). Circular arcs could be
handled simply, but we do not detect that case.

# Proposal

Canvases will have a new subcommand, **rotate**, which will rotate the coordinates of chosen items by a specified angle about a specified point.

 > _canvas_ **rotate** _itemOrTag x y angle_

Note that most of the arguments are very similar to the canvas's **scale**
subcommand.  The _angle_ is measured in degrees, with positive values
indicating anti-clockwise rotation.

## Canvas Item C API Alterations

The `Tk_ItemType` structure gains a new field, `Tk_ItemRotateProc
*rotateProc`, which comes after the `nextPtr` field. This field allows the
creator of the item type to define a callback that handles rotation; if
defined as `NULL`, which it is by default in most existing code, then the
default rotation algorithm is applied, which simply rotates the coordinate
list using the `coordProc`.

The definition of `Tk_ItemRotateProc` is:

    typedef void (Tk_ItemRotateProc)(
        Tk_Canvas canvas,
        Tk_Item *itemPtr,
        double originX,
        double originY,
        double angleRadians);

The `canvas` and `itemPtr` are the usual arguments for these item
callbacks. The `originX` and `originY` describe the point about which rotation
is to be done. The `angleRadians` is the amount to rotate, _in radians_ (i.e.,
suitable for directly using with `sin()` and `cos()`).

# Reference Implementation

See the `tip-164` branch.

# Future Work