Files
MagicSetEditor2/src/util/rotation.hpp
T

222 lines
9.3 KiB
C++

//+----------------------------------------------------------------------------+
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
//| Copyright: (C) 2001 - 2017 Twan van Laarhoven and Sean Hunt |
//| License: GNU General Public License 2 or later (see file COPYING) |
//+----------------------------------------------------------------------------+
#ifndef HEADER_UTIL_ROTATION
#define HEADER_UTIL_ROTATION
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <util/real_point.hpp>
#include <gfx/gfx.hpp>
class Font;
// ----------------------------------------------------------------------------- : Rotation
enum RotationFlags
{ ROTATION_NORMAL
, ROTATION_ATTACH_TOP_LEFT
};
/// An object that can rotate coordinates inside a specified rectangle
/** This class has lots of tr*** functions, they convert
* internal coordinates to external/screen coordinates.
* tr***inv do the opposite.
*/
class Rotation {
public:
/// Construct a rotation object
/** with the given rectangle of external coordinates and a given rotation angle and zoom factor.
* if is_internal then the rect gives the internal coordinates, its origin should be (0,0)
*/
Rotation(Radians angle = 0, const RealRect& rect = RealRect(0,0,0,0), double zoom = 1.0, double strectch = 1.0, RotationFlags flags = ROTATION_NORMAL);
/// Change the zoom factor
inline void setZoom(double z) { zoomX = zoomY = z; }
/// Retrieve the zoom factor
inline double getZoom() const { return zoomY; }
/// Change the stretch factor
void setStretch(double s);
/// Stretch factor
inline double getStretch() const { return zoomX / zoomY; }
/// Get the angle
inline Radians getAngle() const { return angle; }
/// Change the origin
inline void setOrigin(const RealPoint& o) { origin = o; }
/// The internal size
inline RealSize getInternalSize() const { return size; }
inline double getWidth() const { return size.width; }
inline double getHeight() const { return size.height; }
/// The intarnal rectangle (origin at (0,0))
inline RealRect getInternalRect() const { return RealRect(RealPoint(0,0), size); }
/// The size of the external rectangle (as passed to the constructor) == trNoNeg(getInternalSize())
inline RealSize getExternalSize() const { return trSizeToBB(size); }
/// The external rectangle (as passed to the constructor) == trNoNeg(getInternalRect())
inline RealRect getExternalRect() const { return trRectToBB(getInternalRect()); }
/// Translate a size or length
inline double trS(double s) const { return s * zoomY; }
inline double trX(double s) const { return s * zoomX; }
inline double trY(double s) const { return s * zoomY; }
inline RealSize trS(const RealSize& s) const { return RealSize(s.width * zoomX, s.height * zoomY); }
/// Translate an angle
inline Radians trAngle(Radians a) { return constrain_radians(angle + a); }
/// Translate a single point
RealPoint tr(const RealPoint& p) const;
/// Translate a single point, but don't zoom
RealPoint trNoZoom(const RealPoint& p) const;
/// Translate a 'pixel'. A pixel has size 1*1
RealPoint trPixel(const RealPoint& p) const;
/// Translate a 'pixel', but don't zoom
RealPoint trPixelNoZoom(const RealPoint& p) const;
/// Translate a single size
RealSize trSize(const RealSize& s) const;
/// Translate a single size, returns the bounding box size (non-negative)
RealSize trSizeToBB(const RealSize& s) const;
/// Translate a rectangle, returns the bounding box, the size will be non-negative
RealRect trRectToBB(const RealRect& r) const;
/// Translate a rectangle into a region (supports rotation)
wxRegion trRectToRegion(const RealRect& rect) const;
/// Translate a size or length back to internal 'coordinates'
inline double trInvS(double s) const { return s / zoomY; }
inline double trInvX(double s) const { return s / zoomX; }
inline double trInvY(double s) const { return s / zoomY; }
/// Translate a size back to internal 'coordinates', doesn't rotate
inline RealSize trInvS(const RealSize& s) const { return RealSize(s.width / zoomX, s.height / zoomY); }
/// Translate a point back to internal coordinates
RealPoint trInv(const RealPoint& p) const;
/// Translate a size back to internal coordinates
RealSize trInv(const RealSize& p) const;
protected:
Radians angle; ///< The angle of rotation in radians (counterclockwise)
RealSize size; ///< Size of the rectangle, in internal coordinates
RealPoint origin; ///< tr(0,0)
double zoomX; ///< Zoom factor, zoom = 2.0 means that 1 internal = 2 external
double zoomY;
friend class Rotater;
/// Determine the top-left corner of the bounding box around the rotated box s (in external coordinates)
RealPoint boundingBoxCorner(const RealSize& s) const;
};
// ----------------------------------------------------------------------------- : Rotater
/// An object that changes a rotation RIIA style
/** Usage:
* @code
* Rotation a, b;
* Rotater(a,b);
* a.tr(x) // now acts as a.tr(b.tr(x))
* @endcode
*/
class Rotater {
public:
/// Compose a rotation by onto the rotation rot
/** rot is restored when this object is destructed
*/
Rotater(Rotation& rot, const Rotation& by);
~Rotater();
private:
Rotation old;
Rotation& rot;
};
// ----------------------------------------------------------------------------- : RotatedDC
/// Render quality of text
enum RenderQuality {
QUALITY_LOW, ///< Normal
QUALITY_SUB_PIXEL, ///< Sub-pixel positioning
QUALITY_AA, ///< Our own anti aliassing
};
#if wxVERSION_NUMBER < 2900
// argument type to SetLogicalFunction
typedef int wxRasterOperationMode;
#endif
/// A DC with rotation applied
/** All draw** functions take internal coordinates.
*/
class RotatedDC : public Rotation {
public:
RotatedDC(DC& dc, Radians angle, const RealRect& rect, double zoom, RenderQuality quality, RotationFlags flags = ROTATION_NORMAL);
RotatedDC(DC& dc, const Rotation& rotation, RenderQuality quality);
// --------------------------------------------------- : Drawing
/// Draw text
void DrawText (const String& text, const RealPoint& pos, int blur_radius = 0, int boldness = 1, double stretch = 1.0);
void DrawText (const String& text, const RealPoint& pos, Color color, int blur_radius = 0, int boldness = 1, double stretch = 1.0);
/// Draw text with the shadow and color settings of the given font
void DrawTextWithShadow(const String& text, const Font& font, const RealPoint& pos, double scale = 1.0, double stretch = 1.0);
/// Draw abitmap, it must already be zoomed!
void DrawBitmap(const Bitmap& bitmap, const RealPoint& pos);
/// Draw an image using the given combining mode, the image must already be zoomed!
void DrawImage (const Image& image, const RealPoint& pos, ImageCombine combine = COMBINE_DEFAULT);
/// Draw a bitmap that is already zoomed and rotated.
/** The rectangle the position in internal coordinates, and the size before rotating and zooming */
void DrawPreRotatedBitmap(const Bitmap& bitmap, const RealRect& rect);
/// Draw an image that is already zoomed and rotated
void DrawPreRotatedImage(const Image& image, const RealRect& rect, ImageCombine combine = COMBINE_DEFAULT);
void DrawLine (const RealPoint& p1, const RealPoint& p2);
void DrawRectangle(const RealRect& r);
void DrawRoundedRectangle(const RealRect& r, double radius);
void DrawCircle(const RealPoint& center, double radius);
void DrawEllipse(const RealPoint& center, const RealSize& size);
/// Draw an arc of an ellipse, angles are in radians
void DrawEllipticArc(const RealPoint& center, const RealSize& size, Radians start, Radians end);
/// Draw spokes of an ellipse
void DrawEllipticSpoke(const RealPoint& center, const RealSize& size, Radians start);
// Fill the dc with the color of the current brush
void Fill();
// --------------------------------------------------- : Properties
/// Sets the pen for the dc, does not scale the line width
void SetPen(const wxPen&);
void SetBrush(const wxBrush&);
void SetTextForeground(const Color&);
void SetLogicalFunction(wxRasterOperationMode function);
void SetFont(const wxFont& font);
/// Set the font, scales for zoom and high_quality
/** The font size will be multiplied by 'scale' */
void SetFont(const Font& font, double scale);
/// Steps to use when decrementing font size
double getFontSizeStep() const;
RealSize GetTextExtent(const String& text) const;
double GetCharHeight() const;
void SetClippingRegion(const RealRect& rect);
void DestroyClippingRegion();
// --------------------------------------------------- : Other
/// Get the current contents of the given ractangle, for later restoring
Bitmap GetBackground(const RealRect& r);
inline wxDC& getDC() { return dc; }
private:
wxDC& dc; ///< The actual dc
RenderQuality quality; ///< Quality of the text
};
// ----------------------------------------------------------------------------- : EOF
#endif