// Aseprite UI Library // Copyright (C) 2019-2022 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This file is released under the terms of the MIT license. // Read LICENSE.txt for more information. #ifndef UI_GRAPHICS_H_INCLUDED #define UI_GRAPHICS_H_INCLUDED #pragma once #include "base/disable_copying.h" #include "base/string.h" #include "gfx/color.h" #include "gfx/point.h" #include "gfx/rect.h" #include "gfx/size.h" #include "os/font.h" #include "os/surface.h" #include "ui/paint.h" #include #include namespace gfx { class Matrix; class Path; class Region; } namespace os { class DrawTextDelegate; struct Sampling; } namespace ui { class Display; // Class to render a widget in the screen. class Graphics { public: Graphics(Display* display, const os::SurfaceRef& surface, int dx, int dy); ~Graphics(); int width() const; int height() const; os::Surface* getInternalSurface() { return m_surface.get(); } int getInternalDeltaX() { return m_dx; } int getInternalDeltaY() { return m_dy; } int getSaveCount() const; gfx::Rect getClipBounds() const; void saveClip(); void restoreClip(); bool clipRect(const gfx::Rect& rc); void save(); void concat(const gfx::Matrix& matrix); void setMatrix(const gfx::Matrix& matrix); void resetMatrix(); void restore(); gfx::Matrix matrix() const; gfx::Color getPixel(int x, int y); void putPixel(gfx::Color color, int x, int y); void drawHLine(int x, int y, int w, const Paint& paint); void drawHLine(gfx::Color color, int x, int y, int w); void drawVLine(int x, int y, int h, const Paint& paint); void drawVLine(gfx::Color color, int x, int y, int h); void drawLine(gfx::Color color, const gfx::Point& a, const gfx::Point& b); void drawPath(gfx::Path& path, const Paint& paint); void drawRect(const gfx::Rect& rc, const Paint& paint); void drawRect(gfx::Color color, const gfx::Rect& rc); void fillRect(gfx::Color color, const gfx::Rect& rc); void fillRegion(gfx::Color color, const gfx::Region& rgn); void fillAreaBetweenRects(gfx::Color color, const gfx::Rect& outer, const gfx::Rect& inner); void drawSurface(os::Surface* surface, int x, int y); void drawSurface(os::Surface* surface, const gfx::Rect& srcRect, const gfx::Rect& dstRect, const os::Sampling& sampling, const Paint* paint); void drawRgbaSurface(os::Surface* surface, int x, int y); void drawRgbaSurface(os::Surface* surface, int srcx, int srcy, int dstx, int dsty, int w, int h); void drawColoredRgbaSurface(os::Surface* surface, gfx::Color color, int x, int y); void drawColoredRgbaSurface(os::Surface* surface, gfx::Color color, int srcx, int srcy, int dstx, int dsty, int w, int h); void drawSurfaceNine(os::Surface* surface, const gfx::Rect& src, const gfx::Rect& center, const gfx::Rect& dst, const bool drawCenter, const Paint* paint = nullptr); void blit(os::Surface* src, int srcx, int srcy, int dstx, int dsty, int w, int h); // ====================================================================== // FONT & TEXT // ====================================================================== os::Font* font() { return m_font.get(); } void setFont(const os::FontRef& font); void drawText(const std::string& str, gfx::Color fg, gfx::Color bg, const gfx::Point& pt, os::DrawTextDelegate* delegate = nullptr); void drawUIText(const std::string& str, gfx::Color fg, gfx::Color bg, const gfx::Point& pt, const int mnemonic); void drawAlignedUIText(const std::string& str, gfx::Color fg, gfx::Color bg, const gfx::Rect& rc, const int align); gfx::Size measureUIText(const std::string& str); static int measureUITextLength(const std::string& str, os::Font* font); gfx::Size fitString(const std::string& str, int maxWidth, int align); private: gfx::Size doUIStringAlgorithm(const std::string& str, gfx::Color fg, gfx::Color bg, const gfx::Rect& rc, int align, bool draw); void dirty(const gfx::Rect& bounds); Display* m_display; os::SurfaceRef m_surface; int m_dx; int m_dy; gfx::Rect m_clipBounds; os::FontRef m_font; gfx::Rect m_dirtyBounds; }; // Class to draw directly in the screen. class ScreenGraphics : public Graphics { public: ScreenGraphics(Display* display); virtual ~ScreenGraphics(); }; // Class to temporary set the Graphics' clip region to the full // extend. class SetClip { public: SetClip(Graphics* g) : m_graphics(g) , m_oldClip(g->getClipBounds()) , m_oldCount(g->getSaveCount()) { if (m_oldCount > 1) m_graphics->restoreClip(); } ~SetClip() { if (m_oldCount > 1) { m_graphics->saveClip(); m_graphics->clipRect(m_oldClip); } } private: Graphics* m_graphics; gfx::Rect m_oldClip; int m_oldCount; DISABLE_COPYING(SetClip); }; // Class to temporary set the Graphics' clip region to a sub-rectangle // (in the life-time of the IntersectClip instance). class IntersectClip { public: IntersectClip(Graphics* g, const gfx::Rect& rc) : m_graphics(g) { m_graphics->saveClip(); m_notEmpty = m_graphics->clipRect(rc); } ~IntersectClip() { m_graphics->restoreClip(); } operator bool() const { return m_notEmpty; } private: Graphics* m_graphics; bool m_notEmpty; DISABLE_COPYING(IntersectClip); }; typedef std::shared_ptr GraphicsPtr; } // namespace ui #endif