Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 1 | <section id="selection-api"> |
| 2 | |
| 3 | <title>Experimental API for cropping, composing and scaling</title> |
| 4 | |
| 5 | <note> |
| 6 | <title>Experimental</title> |
| 7 | |
| 8 | <para>This is an <link linkend="experimental">experimental</link> |
| 9 | interface and may change in the future.</para> |
| 10 | </note> |
| 11 | |
| 12 | <section> |
| 13 | <title>Introduction</title> |
| 14 | |
| 15 | <para>Some video capture devices can sample a subsection of a picture and |
| 16 | shrink or enlarge it to an image of arbitrary size. Next, the devices can |
| 17 | insert the image into larger one. Some video output devices can crop part of an |
| 18 | input image, scale it up or down and insert it at an arbitrary scan line and |
| 19 | horizontal offset into a video signal. We call these abilities cropping, |
| 20 | scaling and composing.</para> |
| 21 | |
| 22 | <para>On a video <emphasis>capture</emphasis> device the source is a video |
| 23 | signal, and the cropping target determine the area actually sampled. The sink |
| 24 | is an image stored in a memory buffer. The composing area specifies which part |
| 25 | of the buffer is actually written to by the hardware. </para> |
| 26 | |
| 27 | <para>On a video <emphasis>output</emphasis> device the source is an image in a |
| 28 | memory buffer, and the cropping target is a part of an image to be shown on a |
| 29 | display. The sink is the display or the graphics screen. The application may |
| 30 | select the part of display where the image should be displayed. The size and |
| 31 | position of such a window is controlled by the compose target.</para> |
| 32 | |
| 33 | <para>Rectangles for all cropping and composing targets are defined even if the |
| 34 | device does supports neither cropping nor composing. Their size and position |
| 35 | will be fixed in such a case. If the device does not support scaling then the |
| 36 | cropping and composing rectangles have the same size.</para> |
| 37 | |
| 38 | </section> |
| 39 | |
| 40 | <section> |
| 41 | <title>Selection targets</title> |
| 42 | |
Hans Verkuil | 071408b | 2012-08-14 06:10:01 -0300 | [diff] [blame] | 43 | <para> |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 44 | <figure id="sel-targets-capture"> |
| 45 | <title>Cropping and composing targets</title> |
| 46 | <mediaobject> |
| 47 | <imageobject> |
| 48 | <imagedata fileref="selection.png" format="PNG" /> |
| 49 | </imageobject> |
| 50 | <textobject> |
| 51 | <phrase>Targets used by a cropping, composing and scaling |
| 52 | process</phrase> |
| 53 | </textobject> |
| 54 | </mediaobject> |
| 55 | </figure> |
Hans Verkuil | 071408b | 2012-08-14 06:10:01 -0300 | [diff] [blame] | 56 | </para> |
Sylwester Nawrocki | 9080d5d | 2012-03-09 06:46:28 -0300 | [diff] [blame] | 57 | |
Hans Verkuil | 071408b | 2012-08-14 06:10:01 -0300 | [diff] [blame] | 58 | <para>See <xref linkend="v4l2-selection-targets" /> for more |
| 59 | information.</para> |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 60 | </section> |
| 61 | |
| 62 | <section> |
| 63 | |
| 64 | <title>Configuration</title> |
| 65 | |
| 66 | <para>Applications can use the <link linkend="vidioc-g-selection">selection |
| 67 | API</link> to select an area in a video signal or a buffer, and to query for |
| 68 | default settings and hardware limits.</para> |
| 69 | |
| 70 | <para>Video hardware can have various cropping, composing and scaling |
| 71 | limitations. It may only scale up or down, support only discrete scaling |
| 72 | factors, or have different scaling abilities in the horizontal and vertical |
| 73 | directions. Also it may not support scaling at all. At the same time the |
| 74 | cropping/composing rectangles may have to be aligned, and both the source and |
| 75 | the sink may have arbitrary upper and lower size limits. Therefore, as usual, |
| 76 | drivers are expected to adjust the requested parameters and return the actual |
| 77 | values selected. An application can control the rounding behaviour using <link |
Sakari Ailus | 9fe75aa | 2012-06-13 16:01:10 -0300 | [diff] [blame] | 78 | linkend="v4l2-selection-flags"> constraint flags </link>.</para> |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 79 | |
| 80 | <section> |
| 81 | |
| 82 | <title>Configuration of video capture</title> |
| 83 | |
| 84 | <para>See figure <xref linkend="sel-targets-capture" /> for examples of the |
| 85 | selection targets available for a video capture device. It is recommended to |
| 86 | configure the cropping targets before to the composing targets.</para> |
| 87 | |
| 88 | <para>The range of coordinates of the top left corner, width and height of |
Hans Verkuil | d2dbd9d | 2014-06-13 04:47:37 -0300 | [diff] [blame] | 89 | areas that can be sampled is given by the <constant>V4L2_SEL_TGT_CROP_BOUNDS</constant> |
| 90 | target. It is recommended for the driver developers to put the |
| 91 | top/left corner at position <constant>(0,0)</constant>. The rectangle's |
Tomasz Stanislawski | aa73ab9 | 2011-12-09 13:45:47 -0300 | [diff] [blame] | 92 | coordinates are expressed in pixels.</para> |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 93 | |
| 94 | <para>The top left corner, width and height of the source rectangle, that is |
Hans Verkuil | d2dbd9d | 2014-06-13 04:47:37 -0300 | [diff] [blame] | 95 | the area actually sampled, is given by the <constant>V4L2_SEL_TGT_CROP</constant> |
| 96 | target. It uses the same coordinate system as <constant>V4L2_SEL_TGT_CROP_BOUNDS</constant>. |
| 97 | The active cropping area must lie completely inside the capture boundaries. The |
| 98 | driver may further adjust the requested size and/or position according to hardware |
| 99 | limitations.</para> |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 100 | |
| 101 | <para>Each capture device has a default source rectangle, given by the |
Hans Verkuil | d2dbd9d | 2014-06-13 04:47:37 -0300 | [diff] [blame] | 102 | <constant>V4L2_SEL_TGT_CROP_DEFAULT</constant> target. This rectangle shall |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 103 | over what the driver writer considers the complete picture. Drivers shall set |
| 104 | the active crop rectangle to the default when the driver is first loaded, but |
| 105 | not later.</para> |
| 106 | |
| 107 | <para>The composing targets refer to a memory buffer. The limits of composing |
Hans Verkuil | d2dbd9d | 2014-06-13 04:47:37 -0300 | [diff] [blame] | 108 | coordinates are obtained using <constant>V4L2_SEL_TGT_COMPOSE_BOUNDS</constant>. |
| 109 | All coordinates are expressed in pixels. The rectangle's top/left |
| 110 | corner must be located at position <constant>(0,0)</constant>. The width and |
| 111 | height are equal to the image size set by <constant>VIDIOC_S_FMT</constant>. |
Tomasz Stanislawski | aa73ab9 | 2011-12-09 13:45:47 -0300 | [diff] [blame] | 112 | </para> |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 113 | |
| 114 | <para>The part of a buffer into which the image is inserted by the hardware is |
Hans Verkuil | d2dbd9d | 2014-06-13 04:47:37 -0300 | [diff] [blame] | 115 | controlled by the <constant>V4L2_SEL_TGT_COMPOSE</constant> target. |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 116 | The rectangle's coordinates are also expressed in the same coordinate system as |
| 117 | the bounds rectangle. The composing rectangle must lie completely inside bounds |
| 118 | rectangle. The driver must adjust the composing rectangle to fit to the |
| 119 | bounding limits. Moreover, the driver can perform other adjustments according |
| 120 | to hardware limitations. The application can control rounding behaviour using |
Hans Verkuil | d2dbd9d | 2014-06-13 04:47:37 -0300 | [diff] [blame] | 121 | <link linkend="v4l2-selection-flags"> constraint flags</link>.</para> |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 122 | |
| 123 | <para>For capture devices the default composing rectangle is queried using |
Hans Verkuil | d2dbd9d | 2014-06-13 04:47:37 -0300 | [diff] [blame] | 124 | <constant>V4L2_SEL_TGT_COMPOSE_DEFAULT</constant>. It is usually equal to the |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 125 | bounding rectangle.</para> |
| 126 | |
| 127 | <para>The part of a buffer that is modified by the hardware is given by |
Hans Verkuil | d2dbd9d | 2014-06-13 04:47:37 -0300 | [diff] [blame] | 128 | <constant>V4L2_SEL_TGT_COMPOSE_PADDED</constant>. It contains all pixels |
| 129 | defined using <constant>V4L2_SEL_TGT_COMPOSE</constant> plus all |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 130 | padding data modified by hardware during insertion process. All pixels outside |
| 131 | this rectangle <emphasis>must not</emphasis> be changed by the hardware. The |
| 132 | content of pixels that lie inside the padded area but outside active area is |
| 133 | undefined. The application can use the padded and active rectangles to detect |
| 134 | where the rubbish pixels are located and remove them if needed.</para> |
| 135 | |
| 136 | </section> |
| 137 | |
| 138 | <section> |
| 139 | |
| 140 | <title>Configuration of video output</title> |
| 141 | |
| 142 | <para>For output devices targets and ioctls are used similarly to the video |
Hans Verkuil | d2dbd9d | 2014-06-13 04:47:37 -0300 | [diff] [blame] | 143 | capture case. The <emphasis>composing</emphasis> rectangle refers to the |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 144 | insertion of an image into a video signal. The cropping rectangles refer to a |
| 145 | memory buffer. It is recommended to configure the composing targets before to |
| 146 | the cropping targets.</para> |
| 147 | |
| 148 | <para>The cropping targets refer to the memory buffer that contains an image to |
| 149 | be inserted into a video signal or graphical screen. The limits of cropping |
Hans Verkuil | d2dbd9d | 2014-06-13 04:47:37 -0300 | [diff] [blame] | 150 | coordinates are obtained using <constant>V4L2_SEL_TGT_CROP_BOUNDS</constant>. |
Tomasz Stanislawski | aa73ab9 | 2011-12-09 13:45:47 -0300 | [diff] [blame] | 151 | All coordinates are expressed in pixels. The top/left corner is always point |
Hans Verkuil | d2dbd9d | 2014-06-13 04:47:37 -0300 | [diff] [blame] | 152 | <constant>(0,0)</constant>. The width and height is equal to the image size |
| 153 | specified using <constant>VIDIOC_S_FMT</constant> ioctl.</para> |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 154 | |
| 155 | <para>The top left corner, width and height of the source rectangle, that is |
| 156 | the area from which image date are processed by the hardware, is given by the |
Hans Verkuil | d2dbd9d | 2014-06-13 04:47:37 -0300 | [diff] [blame] | 157 | <constant>V4L2_SEL_TGT_CROP</constant>. Its coordinates are expressed |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 158 | in in the same coordinate system as the bounds rectangle. The active cropping |
| 159 | area must lie completely inside the crop boundaries and the driver may further |
| 160 | adjust the requested size and/or position according to hardware |
| 161 | limitations.</para> |
| 162 | |
| 163 | <para>For output devices the default cropping rectangle is queried using |
Hans Verkuil | d2dbd9d | 2014-06-13 04:47:37 -0300 | [diff] [blame] | 164 | <constant>V4L2_SEL_TGT_CROP_DEFAULT</constant>. It is usually equal to the |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 165 | bounding rectangle.</para> |
| 166 | |
| 167 | <para>The part of a video signal or graphics display where the image is |
Hans Verkuil | d2dbd9d | 2014-06-13 04:47:37 -0300 | [diff] [blame] | 168 | inserted by the hardware is controlled by <constant>V4L2_SEL_TGT_COMPOSE</constant> |
| 169 | target. The rectangle's coordinates are expressed in pixels. The composing |
| 170 | rectangle must lie completely inside the bounds rectangle. The driver must |
| 171 | adjust the area to fit to the bounding limits. Moreover, the driver can |
| 172 | perform other adjustments according to hardware limitations.</para> |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 173 | |
Hans Verkuil | d2dbd9d | 2014-06-13 04:47:37 -0300 | [diff] [blame] | 174 | <para>The device has a default composing rectangle, given by the |
| 175 | <constant>V4L2_SEL_TGT_COMPOSE_DEFAULT</constant> target. This rectangle shall cover what |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 176 | the driver writer considers the complete picture. It is recommended for the |
Hans Verkuil | d2dbd9d | 2014-06-13 04:47:37 -0300 | [diff] [blame] | 177 | driver developers to put the top/left corner at position <constant>(0,0)</constant>. |
| 178 | Drivers shall set the active composing rectangle to the default |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 179 | one when the driver is first loaded.</para> |
| 180 | |
| 181 | <para>The devices may introduce additional content to video signal other than |
| 182 | an image from memory buffers. It includes borders around an image. However, |
| 183 | such a padded area is driver-dependent feature not covered by this document. |
| 184 | Driver developers are encouraged to keep padded rectangle equal to active one. |
Hans Verkuil | d2dbd9d | 2014-06-13 04:47:37 -0300 | [diff] [blame] | 185 | The padded target is accessed by the <constant>V4L2_SEL_TGT_COMPOSE_PADDED</constant> |
| 186 | identifier. It must contain all pixels from the <constant>V4L2_SEL_TGT_COMPOSE</constant> |
| 187 | target.</para> |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 188 | |
| 189 | </section> |
| 190 | |
| 191 | <section> |
| 192 | |
Sylwester Nawrocki | 9080d5d | 2012-03-09 06:46:28 -0300 | [diff] [blame] | 193 | <title>Scaling control</title> |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 194 | |
| 195 | <para>An application can detect if scaling is performed by comparing the width |
Hans Verkuil | d2dbd9d | 2014-06-13 04:47:37 -0300 | [diff] [blame] | 196 | and the height of rectangles obtained using <constant>V4L2_SEL_TGT_CROP</constant> |
| 197 | and <constant>V4L2_SEL_TGT_COMPOSE</constant> targets. If |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 198 | these are not equal then the scaling is applied. The application can compute |
| 199 | the scaling ratios using these values.</para> |
| 200 | |
| 201 | </section> |
| 202 | |
| 203 | </section> |
| 204 | |
| 205 | <section> |
| 206 | |
Sylwester Nawrocki | 9080d5d | 2012-03-09 06:46:28 -0300 | [diff] [blame] | 207 | <title>Comparison with old cropping API</title> |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 208 | |
| 209 | <para>The selection API was introduced to cope with deficiencies of previous |
Hans Verkuil | d2dbd9d | 2014-06-13 04:47:37 -0300 | [diff] [blame] | 210 | <link linkend="crop"> API</link>, that was designed to control simple capture |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 211 | devices. Later the cropping API was adopted by video output drivers. The ioctls |
| 212 | are used to select a part of the display were the video signal is inserted. It |
| 213 | should be considered as an API abuse because the described operation is |
| 214 | actually the composing. The selection API makes a clear distinction between |
| 215 | composing and cropping operations by setting the appropriate targets. The V4L2 |
| 216 | API lacks any support for composing to and cropping from an image inside a |
| 217 | memory buffer. The application could configure a capture device to fill only a |
| 218 | part of an image by abusing V4L2 API. Cropping a smaller image from a larger |
Hans Verkuil | 071408b | 2012-08-14 06:10:01 -0300 | [diff] [blame] | 219 | one is achieved by setting the field |
| 220 | &v4l2-pix-format;<structfield>::bytesperline</structfield>. Introducing an image offsets |
| 221 | could be done by modifying field &v4l2-buffer;<structfield>::m_userptr</structfield> |
Hans Verkuil | d2dbd9d | 2014-06-13 04:47:37 -0300 | [diff] [blame] | 222 | before calling <constant>VIDIOC_QBUF</constant>. Those |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 223 | operations should be avoided because they are not portable (endianness), and do |
| 224 | not work for macroblock and Bayer formats and mmap buffers. The selection API |
| 225 | deals with configuration of buffer cropping/composing in a clear, intuitive and |
| 226 | portable way. Next, with the selection API the concepts of the padded target |
Hans Verkuil | 071408b | 2012-08-14 06:10:01 -0300 | [diff] [blame] | 227 | and constraints flags are introduced. Finally, &v4l2-crop; and &v4l2-cropcap; |
| 228 | have no reserved fields. Therefore there is no way to extend their functionality. |
| 229 | The new &v4l2-selection; provides a lot of place for future |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 230 | extensions. Driver developers are encouraged to implement only selection API. |
Hans Verkuil | d2dbd9d | 2014-06-13 04:47:37 -0300 | [diff] [blame] | 231 | The former cropping API would be simulated using the new one.</para> |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 232 | |
| 233 | </section> |
| 234 | |
| 235 | <section> |
| 236 | <title>Examples</title> |
| 237 | <example> |
| 238 | <title>Resetting the cropping parameters</title> |
| 239 | |
Hans Verkuil | d2dbd9d | 2014-06-13 04:47:37 -0300 | [diff] [blame] | 240 | <para>(A video capture device is assumed; change |
| 241 | <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant> for other devices; change target to |
| 242 | <constant>V4L2_SEL_TGT_COMPOSE_*</constant> family to configure composing |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 243 | area)</para> |
| 244 | |
| 245 | <programlisting> |
| 246 | |
| 247 | &v4l2-selection; sel = { |
| 248 | .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, |
| 249 | .target = V4L2_SEL_TGT_CROP_DEFAULT, |
| 250 | }; |
| 251 | ret = ioctl(fd, &VIDIOC-G-SELECTION;, &sel); |
| 252 | if (ret) |
| 253 | exit(-1); |
Sylwester Nawrocki | c133482 | 2012-05-20 11:17:12 -0300 | [diff] [blame] | 254 | sel.target = V4L2_SEL_TGT_CROP; |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 255 | ret = ioctl(fd, &VIDIOC-S-SELECTION;, &sel); |
| 256 | if (ret) |
| 257 | exit(-1); |
| 258 | |
| 259 | </programlisting> |
| 260 | </example> |
| 261 | |
| 262 | <example> |
| 263 | <title>Simple downscaling</title> |
| 264 | <para>Setting a composing area on output of size of <emphasis> at most |
| 265 | </emphasis> half of limit placed at a center of a display.</para> |
| 266 | <programlisting> |
| 267 | |
| 268 | &v4l2-selection; sel = { |
| 269 | .type = V4L2_BUF_TYPE_VIDEO_OUTPUT, |
| 270 | .target = V4L2_SEL_TGT_COMPOSE_BOUNDS, |
| 271 | }; |
| 272 | struct v4l2_rect r; |
| 273 | |
| 274 | ret = ioctl(fd, &VIDIOC-G-SELECTION;, &sel); |
| 275 | if (ret) |
| 276 | exit(-1); |
| 277 | /* setting smaller compose rectangle */ |
| 278 | r.width = sel.r.width / 2; |
| 279 | r.height = sel.r.height / 2; |
| 280 | r.left = sel.r.width / 4; |
| 281 | r.top = sel.r.height / 4; |
| 282 | sel.r = r; |
Sylwester Nawrocki | c133482 | 2012-05-20 11:17:12 -0300 | [diff] [blame] | 283 | sel.target = V4L2_SEL_TGT_COMPOSE; |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 284 | sel.flags = V4L2_SEL_FLAG_LE; |
| 285 | ret = ioctl(fd, &VIDIOC-S-SELECTION;, &sel); |
| 286 | if (ret) |
| 287 | exit(-1); |
| 288 | |
| 289 | </programlisting> |
| 290 | </example> |
| 291 | |
| 292 | <example> |
| 293 | <title>Querying for scaling factors</title> |
Hans Verkuil | d2dbd9d | 2014-06-13 04:47:37 -0300 | [diff] [blame] | 294 | <para>A video output device is assumed; change |
| 295 | <constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> for other devices</para> |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 296 | <programlisting> |
| 297 | |
| 298 | &v4l2-selection; compose = { |
| 299 | .type = V4L2_BUF_TYPE_VIDEO_OUTPUT, |
Sylwester Nawrocki | c133482 | 2012-05-20 11:17:12 -0300 | [diff] [blame] | 300 | .target = V4L2_SEL_TGT_COMPOSE, |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 301 | }; |
| 302 | &v4l2-selection; crop = { |
| 303 | .type = V4L2_BUF_TYPE_VIDEO_OUTPUT, |
Sylwester Nawrocki | c133482 | 2012-05-20 11:17:12 -0300 | [diff] [blame] | 304 | .target = V4L2_SEL_TGT_CROP, |
Tomasz Stanislawski | 8af4922 | 2011-08-19 07:00:04 -0300 | [diff] [blame] | 305 | }; |
| 306 | double hscale, vscale; |
| 307 | |
| 308 | ret = ioctl(fd, &VIDIOC-G-SELECTION;, &compose); |
| 309 | if (ret) |
| 310 | exit(-1); |
| 311 | ret = ioctl(fd, &VIDIOC-G-SELECTION;, &crop); |
| 312 | if (ret) |
| 313 | exit(-1); |
| 314 | |
| 315 | /* computing scaling factors */ |
| 316 | hscale = (double)compose.r.width / crop.r.width; |
| 317 | vscale = (double)compose.r.height / crop.r.height; |
| 318 | |
| 319 | </programlisting> |
| 320 | </example> |
| 321 | |
| 322 | </section> |
| 323 | |
| 324 | </section> |