Skip to content

Instantly share code, notes, and snippets.

@X547
Created May 18, 2025 23:55
Show Gist options
  • Save X547/1ce273adfee14ba6f4a67406b9906720 to your computer and use it in GitHub Desktop.
Save X547/1ce273adfee14ba6f4a67406b9906720 to your computer and use it in GitHub Desktop.
app_server_neo Canvas interface
#pragma once
#include <string_view>
#include <optional>
#include <Point.h>
#include <Rect.h>
#include <Region.h>
#include <Shape.h>
#include <Font.h>
#include <View.h>
#include <AffineTransform.h>
#include <Gradient.h>
#include <InterfaceDefs.h>
#include <app_server/generated/ProtocolTypes.h>
#include <app_server/Typeface.h>
namespace AppServer {
class Picture;
class Bitmap;
class Window;
struct CanvasFontState {
set_font_mask dirty = (set_font_mask)0;
BReference<Typeface> typeface;
float size = 12.0f;
float shear = 90.0f;
float rotation = 0.0f;
float falseBoldWidth = 0.0f;
int8 spacing = B_BITMAP_SPACING; // B_*_SPACING
int8 encoding = B_UNICODE_UTF8; // B_UNICODE_UTF8, ...
int16 face = B_REGULAR_FACE; // B_*_FACE
int32 flags = 0; // B_DISABLE_ANTIALIASING, B_FORCE_ANTIALIASING
};
enum CanvasStateField {
CanvasState_penLocation,
CanvasState_penSize,
CanvasState_highColor,
CanvasState_lowColor,
CanvasState_whichHighColor,
CanvasState_whichLowColor,
CanvasState_pattern,
CanvasState_drawingMode,
CanvasState_origin,
CanvasState_scale,
CanvasState_lineMode,
CanvasState_fillRule,
CanvasState_blendingMode,
CanvasState_fontAntialiasing,
CanvasState_transform,
CanvasState_clipRegion,
CanvasState_font,
CanvasGlobalState_origin,
CanvasGlobalState_clipRegion,
CanvasGlobalState_subpixelPrecise,
};
struct CanvasGlobalState {
uint32 dirty = 0;
BPoint origin;
BRegion* clipRegion {};
bool subpixelPrecise: 1 = false;
};
struct CanvasState {
uint32 dirty = 0;
BPoint penLocation;
float penSize = 1.0f;
rgb_color highColor = {0, 0, 0, 255};
rgb_color lowColor = {255, 255, 255, 255};
color_which whichHighColor = B_NO_COLOR;
color_which whichLowColor = B_NO_COLOR;
float whichHighColorTint = B_NO_TINT;
float whichLowColorTint = B_NO_TINT;
::pattern pattern = B_SOLID_HIGH;
drawing_mode drawingMode = B_OP_COPY;
BPoint origin;
float scale = 1.0f;
join_mode lineJoin = B_MITER_JOIN;
cap_mode lineCap = B_BUTT_CAP;
float miterLimit = B_DEFAULT_MITER_LIMIT;
int32 fillRule = B_NONZERO;
source_alpha alphaSourceMode = B_PIXEL_ALPHA;
alpha_function alphaFunctionMode = B_ALPHA_OVERLAY;
bool subpixelPrecise: 1 = false;
bool fontAntialiasing: 1 = false;
BAffineTransform baseTransform;
BAffineTransform transform;
std::optional<BRegion> clipRegion;
CanvasFontState font;
inline void MovePenTo(BPoint val);
inline void SetPenSize(float val);
inline void SetHighColor(rgb_color val);
inline void SetHighUIColor(color_which which, float tint = B_NO_TINT);
inline void SetLowColor(rgb_color val);
inline void SetLowUIColor(color_which which, float tint = B_NO_TINT);
inline void SetPattern(::pattern val);
inline void SetDrawingMode(drawing_mode val);
inline void SetOrigin(BPoint val);
inline void SetScale(float val);
inline void SetLineMode(cap_mode lineCap, join_mode lineJoin, float miterLimit);
inline void SetFillRule(int32 val);
inline void SetBlendingMode(source_alpha srcAlpha, alpha_function alphaFunc);
inline void ForceFontAliasing(bool enable);
inline void SetTransform(const BAffineTransform& val);
inline BRegion& SetClipRegion();
inline void ClearClipRegion();
inline BAffineTransform CombinedTransform();
};
class Canvas {
public:
class GlobalStateHandler {
public:
virtual void Fetch() = 0;
};
public:
virtual ~Canvas() = default;
virtual CanvasState& State() = 0;
virtual CanvasGlobalState& GlobalState() = 0;
virtual void SetGlobalStateHandler(GlobalStateHandler* handler) = 0;
virtual void Flush() = 0;
// state
virtual void PushState() = 0;
virtual void PopState() = 0;
virtual void BeginLayer(uint8 opacity) = 0;
virtual void EndLayer() = 0;
virtual void TranslateBy(double x, double y) = 0;
virtual void ScaleBy(double x, double y) = 0;
virtual void RotateBy(double angleRadians) = 0;
// clipping
virtual void ConstrainClippingRegion(const BRegion* region) = 0;
virtual void GetClippingRegion(BRegion* region) = 0;
virtual void ClipToPicture(Picture* picture, BPoint where, bool invert) = 0;
virtual void ClipToRect(bool inverse, BRect rect) = 0;
virtual void ClipToShape(bool inverse, const BShape& shape) = 0;
// drawing
virtual void CopyBits(BRect src, BRect dst) = 0;
virtual void StrokeLine(BPoint startPoint, BPoint endPoint) = 0;
virtual void InvertRect(BRect rect) = 0;
virtual void StrokeRect(BRect rect) = 0;
virtual void FillRect(BRect rect) = 0;
virtual void FillRect(BRect rect, const BGradient& gradient) = 0;
virtual void DrawBitmap(Bitmap* bitmap, bitmap_drawing_options options, BRect viewRect, BRect bitmapRect) = 0;
virtual void StrokeArc(BRect rect, float startAngle, float arcAngle) = 0;
virtual void FillArc(BRect rect, float startAngle, float arcAngle) = 0;
virtual void FillArc(BRect rect, float startAngle, float arcAngle, const BGradient& gradient) = 0;
virtual void StrokeBezier(const BPoint controlPoints[4]) = 0;
virtual void FillBezier(const BPoint controlPoints[4]) = 0;
virtual void FillBezier(const BPoint controlPoints[4], const BGradient& gradient) = 0;
virtual void StrokeEllipse(BRect rect) = 0;
virtual void FillEllipse(BRect rect) = 0;
virtual void FillEllipse(BRect rect, const BGradient& gradient) = 0;
virtual void StrokeRoundRect(BRect rect, float xRadius, float yRadius) = 0;
virtual void FillRoundRect(BRect rect, float xRadius, float yRadius) = 0;
virtual void FillRoundRect(BRect rect, float xRadius, float yRadius, const BGradient& gradient) = 0;
virtual void StrokeTriangle(const BPoint points[3], BRect bounds) = 0;
virtual void FillTriangle(const BPoint points[3], BRect bounds) = 0;
virtual void FillTriangle(const BPoint points[3], BRect bounds, const BGradient& gradient) = 0;
virtual void StrokePolygon(BRect bounds, bool closed, int32 count, const BPoint* points) = 0;
virtual void FillPolygon(BRect bounds, int32 count, const BPoint* points) = 0;
virtual void FillPolygon(BRect bounds, int32 count, const BPoint* points, const BGradient& gradient) = 0;
virtual void StrokeShape(const BShape& shape) = 0;
virtual void FillShape(const BShape& shape) = 0;
virtual void FillShape(const BShape& shape, const BGradient& gradient) = 0;
virtual void FillRegion(const BRegion& region) = 0;
virtual void FillRegion(const BRegion& region, const BGradient& gradient) = 0;
virtual void StrokeLineArray(int32 count, const ViewLineArrayInfo* array) = 0;
virtual void DrawString(std::string_view string, BPoint location, const escapement_delta* delta) = 0;
virtual void DrawStringWithOffsets(std::string_view string, int32 locationCount, const BPoint* locations) = 0;
virtual void DrawPicture(Picture* picture, BPoint where) = 0;
protected:
};
class UpdateTrackingCanvas final: public Canvas {
public:
class Handler {
public:
virtual void Update() = 0;
virtual void Update(const BRect& dirty) = 0;
virtual void Update(const BRegion& dirty) = 0;
};
virtual ~UpdateTrackingCanvas() = default;
UpdateTrackingCanvas(Canvas* base): fBase(base) {}
void SetHandler(Handler* handler) {fHandler = handler;}
CanvasState& State() final;
CanvasGlobalState& GlobalState() final;
void SetGlobalStateHandler(GlobalStateHandler* handler) final;
void Flush() final;
// state
void PushState() final;
void PopState() final;
void BeginLayer(uint8 opacity) final;
void EndLayer() final;
void TranslateBy(double x, double y) final;
void ScaleBy(double x, double y) final;
void RotateBy(double angleRadians) final;
// clipping
void ConstrainClippingRegion(const BRegion* region) final;
void GetClippingRegion(BRegion* region) final;
void ClipToPicture(Picture* picture, BPoint where, bool invert) final;
void ClipToRect(bool inverse, BRect rect) final;
void ClipToShape(bool inverse, const BShape& shape) final;
// drawing
void CopyBits(BRect src, BRect dst) final;
void StrokeLine(BPoint startPoint, BPoint endPoint) final;
void InvertRect(BRect rect) final;
void StrokeRect(BRect rect) final;
void FillRect(BRect rect) final;
void FillRect(BRect rect, const BGradient& gradient) final;
void DrawBitmap(Bitmap* bitmap, bitmap_drawing_options options, BRect viewRect, BRect bitmapRect) final;
void StrokeArc(BRect rect, float startAngle, float arcAngle) final;
void FillArc(BRect rect, float startAngle, float arcAngle) final;
void FillArc(BRect rect, float startAngle, float arcAngle, const BGradient& gradient) final;
void StrokeBezier(const BPoint controlPoints[4]) final;
void FillBezier(const BPoint controlPoints[4]) final;
void FillBezier(const BPoint controlPoints[4], const BGradient& gradient) final;
void StrokeEllipse(BRect rect) final;
void FillEllipse(BRect rect) final;
void FillEllipse(BRect rect, const BGradient& gradient) final;
void StrokeRoundRect(BRect rect, float xRadius, float yRadius) final;
void FillRoundRect(BRect rect, float xRadius, float yRadius) final;
void FillRoundRect(BRect rect, float xRadius, float yRadius, const BGradient& gradient) final;
void StrokeTriangle(const BPoint points[3], BRect bounds) final;
void FillTriangle(const BPoint points[3], BRect bounds) final;
void FillTriangle(const BPoint points[3], BRect bounds, const BGradient& gradient) final;
void StrokePolygon(BRect bounds, bool closed, int32 count, const BPoint* points) final;
void FillPolygon(BRect bounds, int32 count, const BPoint* points) final;
void FillPolygon(BRect bounds, int32 count, const BPoint* points, const BGradient& gradient) final;
void StrokeShape(const BShape& shape) final;
void FillShape(const BShape& shape) final;
void FillShape(const BShape& shape, const BGradient& gradient) final;
void FillRegion(const BRegion& region) final;
void FillRegion(const BRegion& region, const BGradient& gradient) final;
void StrokeLineArray(int32 count, const ViewLineArrayInfo* array) final;
void DrawString(std::string_view string, BPoint location, const escapement_delta* delta) final;
void DrawStringWithOffsets(std::string_view string, int32 locationCount, const BPoint* locations) final;
void DrawPicture(Picture* picture, BPoint where) final;
protected:
Canvas* fBase;
Handler* fHandler {};
};
class CanvasRoster {
public:
virtual ~CanvasRoster() = default;
virtual Canvas* NewWindowCanvas(Window* window) = 0;
virtual Canvas* NewBitmapCanvas(Bitmap* bitmap) = 0;
};
extern CanvasRoster* gCanvasRoster;
// #pragma mark -
void
CanvasState::MovePenTo(BPoint val)
{
penLocation = val;
dirty |= 1U << CanvasState_penLocation;
}
void
CanvasState::SetPenSize(float val)
{
penSize = val;
dirty |= 1U << CanvasState_penSize;
}
void
CanvasState::SetHighColor(rgb_color val)
{
highColor = val;
whichHighColor = B_NO_COLOR;
dirty |= (1U << CanvasState_highColor) | (1U << CanvasState_whichHighColor);
}
void
CanvasState::SetHighUIColor(color_which which, float tint)
{
whichHighColor = which;
whichHighColorTint = tint;
dirty |= 1U << CanvasState_whichHighColor;
}
void
CanvasState::SetLowColor(rgb_color val)
{
lowColor = val;
whichLowColor = B_NO_COLOR;
dirty |= (1U << CanvasState_lowColor) | (1U << CanvasState_whichLowColor);
}
void
CanvasState::SetLowUIColor(color_which which, float tint)
{
whichLowColor = which;
whichLowColorTint = tint;
dirty |= 1U << CanvasState_whichLowColor;
}
void
CanvasState::SetPattern(::pattern val)
{
pattern = val;
dirty |= 1U << CanvasState_pattern;
}
void
CanvasState::SetDrawingMode(drawing_mode val)
{
drawingMode = val;
dirty |= 1U << CanvasState_drawingMode;
}
void
CanvasState::SetOrigin(BPoint val)
{
origin = val;
dirty |= 1U << CanvasState_origin;
}
void
CanvasState::SetScale(float val)
{
scale = val;
dirty |= 1U << CanvasState_scale;
}
void
CanvasState::SetLineMode(cap_mode lineCap, join_mode lineJoin, float miterLimit)
{
this->lineCap = lineCap;
this->lineJoin = lineJoin;
this->miterLimit = miterLimit;
dirty |= 1U << CanvasState_lineMode;
}
void
CanvasState::SetFillRule(int32 val)
{
fillRule = val;
dirty |= 1U << CanvasState_fillRule;
}
void
CanvasState::SetBlendingMode(source_alpha srcAlpha, alpha_function alphaFunc)
{
this->alphaSourceMode = srcAlpha;
this->alphaFunctionMode = alphaFunc;
dirty |= 1U << CanvasState_blendingMode;
}
void
CanvasState::ForceFontAliasing(bool enable)
{
fontAntialiasing = enable;
dirty |= 1U << CanvasState_fontAntialiasing;
}
void
CanvasState::SetTransform(const BAffineTransform& val)
{
transform = val;
dirty |= 1U << CanvasState_transform;
}
inline BRegion&
CanvasState::SetClipRegion()
{
dirty |= 1U << CanvasState_clipRegion;
return clipRegion.emplace();
}
inline void
CanvasState::ClearClipRegion()
{
clipRegion.reset();
dirty |= 1U << CanvasState_clipRegion;
}
BAffineTransform
CanvasState::CombinedTransform()
{
BAffineTransform res;
res.TranslateBy(origin);
res.ScaleBy(scale);
res.Multiply(transform);
return res;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment