#pragma once
#include "Widget.h"
#include "Graphics.h"
#include "Common.h"
BEGIN_NAMESPACE
class Pixmap : public PaintTargetInterface
{
public:
Pixmap(unsigned char* a_memoryBuffer, int a_width, int a_height, int a_depth);
Pixmap(const char* a_fileName);
~Pixmap();
const uint32_t* bits() const;
uint32_t width() const;
uint32_t height() const;
Size size() const { return (Size){ (int)width(), (int)height() }; }
PixelBuffer& targetBuffer() override;
float targetScale() override { return 1.0f; }
private:
struct PixmapData* m_data;
};
enum FontStyle
{
FS_Normal = 0,
FS_Italic = 1<<0,
FS_Oblique = 1<<1,
FS_StrikeOut = 1<<2,
FS_UnderLine = 1<<3,
FS_OverLine = 1<<4,
FS_FixedPitch = 1<<5
};
/*
class FontMetrics
{
public:
Property<int> ascent;
Property<int> descent;
Property<int> xHeight;
Property<int> capHeight;
Property<int> lineGap;
};
*/
class Font
{
public:
Font() { Init(); }
Font(const Font& a_other) { Init(a_other.family.value(), a_other.pointSize.value(),
a_other.weight.value(), a_other.style.value(),
a_other.stretch.value()); }
Font& operator=(const Font& a_other) { Init(a_other.family.value(), a_other.pointSize.value(),
a_other.weight.value(), a_other.style.value(),
a_other.stretch.value());
return *this; }
Font(const char* a_family) { Init(a_family); }
Font(int a_pointSize) { Init(Font::Helvetica, a_pointSize); }
Font(FontStyle a_style) { Init(Font::Helvetica, 12, 50, a_style); }
Font(const char* a_family,
int a_pointSize,
int a_weight = 50,
FontStyle a_style = FS_Normal,
int a_stretch = 100) { Init(a_family, a_pointSize, a_weight, a_style, a_stretch); }
Property<String> family;
Property<int> pointSize;
Property<int> weight; // 25 light 50 normal 75 bold
Property<FontStyle> style;
Property<int> stretch; // 50 very condensed 75 condensed 100 normal 125 expanded 200 very expanded
//FontMetrics fontMetrics();
Property<FontMetrics> metrics;
//FontMetrics metrics;
/*
// Idea for a more cross-platform / generic specification:
static const char* DefaultFamily;
static const char* SansFamily;
static const char* SerifFamily;
static const char* MonoFamily;
*/
static const char* Helvetica;
static const char* Times;
static const char* Courier;
static const char* OldEnglish;
static const char* Monospace;
static const char* Fantasy;
static const char* Cursive;
static const char* UIFont;
private:
void Init(const char* a_family = Font::Helvetica, int a_pointSize = 12,
int a_weight = 50, FontStyle a_style = FS_Normal, int a_stretch = 100)
{
family = a_family;
pointSize = a_pointSize;
weight = a_weight;
style = a_style;
stretch = a_stretch;
}
};
enum BrushStyle
{
BS_None,
BS_SolidColor,
BS_Pixmap,
BS_Gradient
};
class Brush
{
public:
Brush() { Init(); }
Brush(const Brush& a_other) { Init(a_other.style.value(), a_other.color.value(),
a_other.pixmap.value(), a_other.origin.value()); }
Brush& operator=(const Brush& a_other) { Init(a_other.style.value(), a_other.color.value(),
a_other.pixmap.value(), a_other.origin.value());
return *this; }
Brush(uint32_t a_color) { Init(BS_SolidColor, a_color); }
Brush(Pixmap* a_pixmap) { Init(BS_Pixmap, 0, a_pixmap); }
Brush(Pixmap* a_pixmap, Point a_origin) { Init(BS_Pixmap, 0, a_pixmap, a_origin); }
Brush(Gradient a_gradient) { } // TODO: gradient brush not fully implemented - some gradient support
Property<BrushStyle> style;
Property<uint32_t> color;
Property<Pixmap*> pixmap;
Property<Point> origin;
private:
void Init(BrushStyle a_style = BS_None, uint32_t a_color = 0, Pixmap* a_pixmap = 0, Point a_origin = {})
{
style = a_style;
color = a_color;
pixmap = a_pixmap;
origin = a_origin;
}
};
enum class PenStyle
{
None,
Solid,
Dotted,
Dashed,
DotDashed
};
class Pen
{
public:
Pen() { Init(); }
Pen(const Pen& a_other) { Init(a_other.style.value(),
a_other.color.value(),
a_other.width.value()); }
Pen& operator=(const Pen& a_other) { Init(a_other.style.value(),
a_other.color.value(),
a_other.width.value());
return *this; }
Pen(PenStyle a_style) { Init(a_style); }
Pen(uint32_t a_color) { Init(PenStyle::Solid, a_color); }
Property<PenStyle> style;
Property<uint32_t> color;
Property<uint32_t> width;
private:
void Init(PenStyle a_style = PenStyle::None, uint32_t a_color = 0, uint32_t a_width = 1)
{
style = a_style;
color = a_color;
width = a_width;
}
};
class Painter
{
public:
Painter();
Painter(PaintTargetInterface* a_window);
~Painter();
// setPen with a Pen
// setBrush with a Brush
// setFont with a Font
void setPen(Pen a_pen);
void setBrush(Brush a_brush);
void setFont(Font a_font);
void setPen(uint32_t a_color);
void setBrush(uint32_t a_color); // brush can be color or pattern / pixmap with some origin
void setFontFamily(const char* a_fontName);
void setFontSize(uint32_t a_size);
// drawArc drawChord drawPie drawPolygon drawPolyline
void drawEllipse(int a_x, int a_y, int a_width, int a_height);
void drawGradient(int a_x, int a_y, Gradient a_gradient, int a_width, int a_height);
void drawLine(int a_x, int a_y, int a_x2, int a_y2);
// drawLines
// drawPoint
// drawPoints
// drawPath
// drawImage
void drawPixmap(int a_x, int a_y, const Pixmap& pixmap, int a_x1 = 0, int a_y1 = 0, int a_x2 = -1, int a_y2 = -1, bool a_alphaMask = false);
void drawPixmapAlphaBlended(int a_x, int a_y, const Pixmap& pixmap, int a_x1 = 0, int a_y1 = 0, int a_x2 = -1, int a_y2 = -1, int a_alpha = 0);
void drawPixelBuffer(int a_x, int a_y, const uint8_t* a_pixels, int a_pixelsWidth, int a_pixelsHeight, int a_pixelsDepth);
// drawRect
// drawRects
// drawRoundedRect
// drawStaticText // optimization which caches things
// drawTiledPixmap
// fillRect // like drawRect, but passing in the brush and no-pen
void drawRectangle(int a_x, int a_y, int a_width, int a_height, bool a_alphaBlending = false);
void drawFocusRectangle(int a_x, int a_y, int a_width, int a_height);
void drawText(int a_x, int a_y, const String& a_formattedUtf8String, int a_flags = 0);
Size textExtents(const char* a_formattedUtf8String);
// Helpers to wrap the above
void drawRectangle(Rectangle a_rectangle, bool a_alphaBlending = false)
{
drawRectangle(a_rectangle.m_x, a_rectangle.m_y, a_rectangle.m_width, a_rectangle.m_height, a_alphaBlending);
}
void drawFocusRectangle(Rectangle a_rectangle)
{
drawFocusRectangle(a_rectangle.m_x, a_rectangle.m_y, a_rectangle.m_width, a_rectangle.m_height);
}
template <typename ...Ts>
void drawText(int a_x, int a_y, const char* a_utf8String, Ts ...args)
{
drawText(a_x, a_y, String(a_utf8String, args...));
}
template <typename ...Ts>
Size textExtents(const char* a_utf8String, Ts ...args)
{
return textExtents(String(a_utf8String, args...));
}
FontMetrics fontMetrics();
GlyphMetrics glyphMetrics(uint32_t a_unicodeCharacter); // technically unicode code-points do not map one-to-one with glyphs,
// API would need to expose a lot of complexity for this
// Clear the target buffer ready for drawing to
void reset();
private:
void scaleArguments(int& a_x, int& a_y, int& a_width, int& a_height);
struct PainterData* m_data;
};
END_NAMESPACE