summaryrefslogtreecommitdiffstats
path: root/doc/coordsys.doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc/coordsys.doc')
-rw-r--r--doc/coordsys.doc262
1 files changed, 262 insertions, 0 deletions
diff --git a/doc/coordsys.doc b/doc/coordsys.doc
new file mode 100644
index 000000000..f614116a3
--- /dev/null
+++ b/doc/coordsys.doc
@@ -0,0 +1,262 @@
+/****************************************************************************
+**
+** Qt Coordinate System Documentation
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of the Qt GUI Toolkit.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing retquirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** This file may be used under the terms of the Q Public License as
+** defined by Trolltech ASA and appearing in the file LICENSE.QPL
+** included in the packaging of this file. Licensees holding valid Qt
+** Commercial licenses may use this file in accordance with the Qt
+** Commercial License Agreement provided with the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+/*!
+\page coordsys.html
+
+\title The Coordinate System
+
+A \link QPaintDevice paint device\endlink in Qt is a drawable 2D
+surface. \l QWidget, \l QPixmap, \l QPicture and \l QPrinter are all
+paint devices. A \l QPainter is an object which can draw on such
+devices.
+
+The default coordinate system of a paint device has its origin at the
+top left corner. X increases to the right and Y increases downwards.
+The unit is one pixel on pixel-based devices and one point on
+printers.
+
+\section1 An Example
+
+The illustration below shows a highly magnified portion of the top
+left corner of a paint device.
+
+\img coordsys.png
+
+The rectangle and the line were drawn by this code (with the grid
+added and colors touched up in the illustration):
+
+\code
+ void MyWidget::paintEvent( QPaintEvent * )
+ {
+ QPainter p( this );
+ p.setPen( darkGray );
+ p.drawRect( 1,2, 5,4 );
+ p.setPen( lightGray );
+ p.drawLine( 9,2, 7,7 );
+ }
+\endcode
+
+Note that all of the pixels drawn by drawRect() are inside the size
+specified (5*4 pixels). This is different from some toolkits; in Qt
+the size you specify exactly encompasses the pixels drawn. This
+applies to all the relevant functions in QPainter.
+
+Similarly, the drawLine() call draws both endpoints of the line, not
+just one.
+
+Here are the classes that relate most closely to the coordinate
+system:
+
+\table
+
+\row \i \l QPoint
+ \i A single 2D point in the coordinate system. Most functions in
+ Qt that deal with points can accept either a QPoint argument
+ or two ints, for example \l QPainter::drawPoint().
+\row \i \l QSize
+ \i A single 2D vector. Internally, QPoint and QSize are the same,
+ but a point is not the same as a size, so both classes exist.
+ Again, most functions accept either a QSize or two ints, for
+ example \l QWidget::resize().
+\row \i \l QRect
+ \i A 2D rectangle. Most functions accept either a QRect or four
+ ints, for example \l QWidget::setGeometry().
+\row \i \l QRegion
+ \i An arbitrary set of points, including all the normal set
+ operations, e.g. \l QRegion::intersect(), and also a less
+ usual function to return a list of rectangles whose union is
+ equal to the region. QRegion is used e.g. by \l
+ QPainter::setClipRegion(), \l QWidget::repaint() and \l
+ QPaintEvent::region().
+\row \i \l QPainter
+ \i The class that paints. It can paint on any device with the
+ same code. There are differences between devices, \l
+ QPrinter::newPage() is a good example, but QPainter works the
+ same way on all devices.
+\row \i \l QPaintDevice
+ \i A device on which QPainter can paint. There are two internal
+ devices, both pixel-based, and two external devices, \l
+ QPrinter and \l QPicture (which records QPainter commands to a
+ file or other \l QIODevice, and plays them back). Other
+ devices can be defined.
+\endtable
+
+\section1 Transformations
+
+Although Qt's default coordinate system works as described above, \l
+QPainter also supports arbitrary transformations.
+
+This transformation engine is a three-step pipeline, closely following
+the model outlined in books such as
+\link http://www.amazon.com/exec/obidos/ASIN/0201848406/trolltech/t
+Foley \& Van Dam \endlink and the
+\link http://www.amazon.com/exec/obidos/ASIN/0201604582/trolltech/t
+OpenGL Programming Guide.\endlink Refer to those for in-depth
+coverage; here we give just a brief overview and an example.
+
+The first step uses the world transformation matrix. Use this matrix
+to orient and position your objects in your model. Qt provides
+methods such as \l QPainter::rotate(), \l QPainter::scale(), \l
+QPainter::translate() and so on to operate on this matrix.
+
+\l QPainter::save() and \l QPainter::restore() save and restore this
+matrix. You can also use \l QWMatrix objects, \l
+QPainter::worldMatrix() and \l QPainter::setWorldMatrix() to store and
+use named matrices.
+
+The second step uses the window. The window describes the view
+boundaries in model coordinates. The matrix positions the \e objects
+and \l QPainter::setWindow() positions the \e window, deciding what
+coordinates will be visible. (If you have 3D experience, the window
+is what's usually called projection in 3D.)
+
+The third step uses the viewport. The viewport too, describes the view
+boundaries, but in device coordinates. The viewport and the windows
+describe the same rectangle, but in different coordinate systems.
+
+On-screen, the default is the entire \l QWidget or \l QPixmap where
+you are drawing, which is usually appropriate. For printing this
+function is vital, since very few printers can print over the entire
+physical page.
+
+So each object to be drawn is transformed into model
+coordinates using \l QPainter::worldMatrix(), then positioned
+on the drawing device using \l QPainter::window() and
+\l QPainter::viewport().
+
+It is perfectly possible to do without one or two of the stages. If,
+for example, your goal is to draw something scaled, then just using \l
+QPainter::scale() makes perfect sense. If your goal is to use a
+fixed-size coordinate system, \l QPainter::setWindow() is
+ideal. And so on.
+
+Here is a short example that uses all three mechanisms: the function
+that draws the clock face in the \l aclock/aclock.cpp example. We
+recommend compiling and running the example before you read any
+further. In particular, try resizing the window to different sizes.
+
+\quotefile aclock/aclock.cpp
+\skipto ::drawClock
+\printline ::drawClock
+\printline {
+\printline save
+
+Firstly, we save the painter's state, so that the calling function
+is guaranteed not to be disturbed by the transformations we're going
+to use.
+
+\printline setWindow
+
+We set the model coordinate system we want a 1000*1000 window where
+0,0 is in the middle.
+
+\printline viewport
+\printline QMIN
+
+The device may not be square and we want the clock to be, so we find
+its current viewport and compute its shortest side.
+
+\printline setViewport
+\printline height
+
+Then we set a new square viewport, centered in the old one.
+
+We're now done with our view. From this point on, when we draw in a
+1000*1000 area around 0,0, what we draw will show up in the largest
+possible square that'll fit in the output device.
+
+Time to start drawing.
+
+\skipto pts
+\printline pts
+
+\e pts is just a temporary variable to hold some points.
+
+Next come three drawing blocks, one for the hour hand, one for the
+minute hand and finally one for the clock face itself. First we draw
+the hour hand:
+
+\skipto save
+\printline save
+\printline rotate
+
+We save the painter and then rotate it so that one axis points along
+the hour hand.
+
+\printline setPoints
+\printline drawConvexPolygon
+
+We set \e pts to a four-point polygon that looks like the hour hand at
+three o'clock, and draw it. Because of the rotation, it's drawn
+pointed in the right direction.
+
+\printline restore
+
+We restore the saved painter, undoing the rotation. We could also
+call rotate( -30 ) but that might introduce rounding errors, so it's
+better to use save() and restore(). Next, the minute hand, drawn
+almost the same way:
+
+\printline save
+\printline rotate
+\printline setPoints
+\printline drawConvexPolygon
+\printline restore
+
+The only differences are how the rotation angle is computed and the
+shape of the polygon.
+
+The last part to be drawn is the clock face itself.
+
+\printline for
+\printline drawLine
+\printline rotate
+\printline }
+
+Twelve short hour lines at thirty-degree intervals. At the end of
+that, the painter is rotated in a way which isn't very useful, but
+we're done with painting so that doesn't matter.
+
+\printline restore
+\printline }
+
+The final line of the function restores the painter, so that the
+caller won't be affected by all the transformations we've done.
+
+*/