⛏️ index : haiku.git

author X512 <danger_mail@list.ru> 2025-09-13 8:25:49.0 +09:00:00
committer waddlesplash <waddlesplash@gmail.com> 2026-01-04 22:56:43.0 +00:00:00
commit
2a4448e03333a62bf19cfa90846ea599a58938eb [patch]
tree
0e8e2145684cee811463e97da4da37d2d6fe4fad
parent
ceaf2dd2d619abb4069b96f6f07bf1038862fd9e
download
2a4448e03333a62bf19cfa90846ea599a58938eb.tar.gz

PicturePlayer: Use C++ virtual interface instead of C function table

Also use C function table instead of `void*` table function casts.

Improve type safety and readability.

Change-Id: Ie5f544b5c2bb9f2333fe3353462325dbfb4453ec
Reviewed-on: https://review.haiku-os.org/c/haiku/+/9656
Reviewed-by: Adrien Destugues <pulkomandy@pulkomandy.tk>
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
Reviewed-by: waddlesplash <waddlesplash@gmail.com>

Diff

 headers/private/interface/PicturePlayer.h    | 253 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 src/kits/interface/PicturePlayer.cpp         | 932 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
 src/servers/app/PictureBoundingBoxPlayer.cpp | 538 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
 src/servers/app/ServerPicture.cpp            | 704 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
 4 files changed, 1159 insertions(+), 1268 deletions(-)

diff --git a/headers/private/interface/PicturePlayer.h b/headers/private/interface/PicturePlayer.h
index 9cffa7b..73ef0c0 100644
--- a/headers/private/interface/PicturePlayer.h
+++ b/headers/private/interface/PicturePlayer.h
@@ -32,78 +32,184 @@
namespace BPrivate {


struct picture_player_callbacks {
	void (*move_pen_by)(void* userData, const BPoint& where);
	void (*stroke_line)(void* userData, const BPoint& start, const BPoint& end);
	void (*draw_rect)(void* userData, const BRect& rect, bool fill);
	void (*draw_round_rect)(void* userData, const BRect& rect,
		const BPoint& radii, bool fill);
	void (*draw_bezier)(void* userData, const BPoint controlPoints[4], bool fill);
	void (*draw_arc)(void* userData, const BPoint& center, const BPoint& radii,
		float startTheta, float arcTheta, bool fill);
	void (*draw_ellipse)(void* userData, const BRect& rect, bool fill);
	void (*draw_polygon)(void* userData, size_t numPoints,
		const BPoint points[], bool isClosed, bool fill);
	void (*draw_shape)(void* userData, const BShape& shape, bool fill);
	void (*draw_string)(void* userData, const char* string, size_t length,
		float spaceEscapement, float nonSpaceEscapement);
	void (*draw_pixels)(void* userData, const BRect& source,
		const BRect& destination, uint32 width, uint32 height,
		size_t bytesPerRow, color_space pixelFormat, uint32 flags,
		const void* data, size_t length);
	void (*draw_picture)(void* userData, const BPoint& where, int32 token);
	void (*set_clipping_rects)(void* userData, size_t numRects,
		const clipping_rect rects[]);
	void (*clip_to_picture)(void* userData, int32 token,
		const BPoint& where, bool clipToInverse);
	void (*push_state)(void* userData);
	void (*pop_state)(void* userData);
	void (*enter_state_change)(void* userData);
	void (*exit_state_change)(void* userData);
	void (*enter_font_state)(void* userData);
	void (*exit_font_state)(void* userData);
	void (*set_origin)(void* userData, const BPoint& origin);
	void (*set_pen_location)(void* userData, const BPoint& location);
	void (*set_drawing_mode)(void* userData, drawing_mode mode);
	void (*set_line_mode)(void* userData, cap_mode capMode, join_mode joinMode,
struct picture_player_callbacks_compat {
	/*  0 */ void (*nop)(void* user);
	/*  1 */ void (*move_pen_by)(void* user, BPoint delta);
	/*  2 */ void (*stroke_line)(void* user, BPoint start, BPoint end);
	/*  3 */ void (*stroke_rect)(void* user, BRect rect);
	/*  4 */ void (*fill_rect)(void* user, BRect rect);
	/*  5 */ void (*stroke_round_rect)(void* user, BRect rect, BPoint radii);
	/*  6 */ void (*fill_round_rect)(void* user, BRect rect, BPoint radii);
	/*  7 */ void (*stroke_bezier)(void* user, BPoint* control);
	/*  8 */ void (*fill_bezier)(void* user, BPoint* control);
	/*  9 */ void (*stroke_arc)(void* user, BPoint center, BPoint radii, float startTheta,
		float arcTheta);
	/* 10 */ void (*fill_arc)(void* user, BPoint center, BPoint radii, float startTheta,
		float arcTheta);
	/* 11 */ void (*stroke_ellipse)(void* user, BPoint center, BPoint radii);
	/* 12 */ void (*fill_ellipse)(void* user, BPoint center, BPoint radii);
	/* 13 */ void (*stroke_polygon)(void* user, int32 numPoints, const BPoint* points,
		bool isClosed);
	/* 14 */ void (*fill_polygon)(void* user, int32 numPoints, const BPoint* points,
		bool isClosed);
	// Called "Reserved" in BeBook
	/* 15 */ void (*stroke_shape)(void* user, const BShape *shape);
	// Called "Reserved" in BeBook
	/* 16 */ void (*fill_shape)(void* user, const BShape *shape);
	/* 17 */ void (*draw_string)(void* user, const char* string, float deltax, float deltay);
	/* 18 */ void (*draw_pixels)(void* user, BRect src, BRect dest, int32 width, int32 height,
		int32 bytesPerRow, int32 pixelFormat, int32 flags, const void* data);
	// Called "Reserved" in BeBook
	/* 19 */ void (*draw_picture)(void* user, BPoint where, int32 token);
	/* 20 */ void (*set_clipping_rects)(void* user, const BRect* rects, uint32 numRects);
	// Called "Reserved" in BeBook
	/* 21 */ void (*clip_to_picture)(void* user, int32 token, BPoint point,
		bool clip_to_inverse_picture);
	/* 22 */ void (*push_state)(void* user);
	/* 23 */ void (*pop_state)(void* user);
	/* 24 */ void (*enter_state_change)(void* user);
	/* 25 */ void (*exit_state_change)(void* user);
	/* 26 */ void (*enter_font_state)(void* user);
	/* 27 */ void (*exit_font_state)(void* user);
	/* 28 */ void (*set_origin)(void* user, BPoint pt);
	/* 29 */ void (*set_pen_location)(void* user, BPoint pt);
	/* 30 */ void (*set_drawing_mode)(void* user, drawing_mode mode);
	/* 31 */ void (*set_line_mode)(void* user, cap_mode capMode, join_mode joinMode,
		float miterLimit);
	void (*set_pen_size)(void* userData, float size);
	void (*set_fore_color)(void* userData, const rgb_color& color);
	void (*set_back_color)(void* userData, const rgb_color& color);
	void (*set_stipple_pattern)(void* userData, const pattern& patter);
	void (*set_scale)(void* userData, float scale);
	void (*set_font_family)(void* userData, const char* familyName,
		size_t length);
	void (*set_font_style)(void* userData, const char* styleName,
		size_t length);
	void (*set_font_spacing)(void* userData, uint8 spacing);
	void (*set_font_size)(void* userData, float size);
	void (*set_font_rotation)(void* userData, float rotation);
	void (*set_font_encoding)(void* userData, uint8 encoding);
	void (*set_font_flags)(void* userData, uint32 flags);
	void (*set_font_shear)(void* userData, float shear);
	void (*set_font_face)(void* userData, uint16 face);
	void (*set_blending_mode)(void* userData, source_alpha alphaSourceMode,
		alpha_function alphaFunctionMode);
	void (*set_transform)(void* userData, const BAffineTransform& transform);
	void (*translate_by)(void* userData, double x, double y);
	void (*scale_by)(void* userData, double x, double y);
	void (*rotate_by)(void* userData, double angleRadians);
	void (*blend_layer)(void* userData, Layer* layer);
	void (*clip_to_rect)(void* userData, const BRect& rect, bool inverse);
	void (*clip_to_shape)(void* userData, int32 opCount, const uint32 opList[],
		int32 ptCount, const BPoint ptList[], bool inverse);
	void (*draw_string_locations)(void* userData, const char* string,
		size_t length, const BPoint locations[], size_t locationCount);
	void (*draw_rect_gradient)(void* userData, const BRect& rect, BGradient& gradient, bool fill);
	void (*draw_round_rect_gradient)(void* userData, const BRect& rect, const BPoint& radii, BGradient& gradient, bool fill);
	void (*draw_bezier_gradient)(void* userData, const BPoint controlPoints[4], BGradient& gradient, bool fill);
	void (*draw_arc_gradient)(void* userData, const BPoint& center, const BPoint& radii, float startTheta, float arcTheta, BGradient& gradient, bool fill);
	void (*draw_ellipse_gradient)(void* userData, const BRect& rect, BGradient& gradient, bool fill);
	void (*draw_polygon_gradient)(void* userData, size_t numPoints, const BPoint points[], bool isClosed, BGradient& gradient, bool fill);
	void (*draw_shape_gradient)(void* userData, const BShape& shape, BGradient& gradient, bool fill);
	void (*set_fill_rule)(void* userData, int32 fillRule);
	void (*stroke_line_gradient)(void* userData, const BPoint& start, const BPoint& end, const BGradient& gradient);
	/* 32 */ void (*set_pen_size)(void* user, float size);
	/* 33 */ void (*set_fore_color)(void* user, rgb_color color);
	/* 34 */ void (*set_back_color)(void* user, rgb_color color);
	/* 35 */ void (*set_stipple_pattern)(void* user, pattern p);
	/* 36 */ void (*set_scale)(void* user, float scale);
	/* 37 */ void (*set_font_family)(void* user, const char* family);
	/* 38 */ void (*set_font_style)(void* user, const char* style);
	/* 39 */ void (*set_font_spacing)(void* user, int32 spacing);
	/* 40 */ void (*set_font_size)(void* user, float size);
	/* 41 */ void (*set_font_rotate)(void* user, float rotation);
	/* 42 */ void (*set_font_encoding)(void* user, int32 encoding);
	/* 43 */ void (*set_font_flags)(void* user, int32 flags);
	/* 44 */ void (*set_font_shear)(void* user, float shear);
	// Called "Reserved" in BeBook
	/* 45 */ void (*set_font_bpp)(void* user, int32 bpp);
	/* 46 */ void (*set_font_face)(void* user, int32 flags);

	// New in Haiku
	/* 47 */ void (*set_blending_mode)(void* user, source_alpha alphaSrcMode,
		alpha_function alphaFncMode);
	/* 48 */ void (*set_transform)(void* user, const BAffineTransform& transform);
	/* 49 */ void (*translate_by)(void* user, double x, double y);
	/* 50 */ void (*scale_by)(void* user, double x, double y);
	/* 51 */ void (*rotate_by)(void* user, double angleRadians);
	// Broken when saved to file
	/* 52 */ void (*blend_layer)(void* user, class Layer* layer);
	/* 53 */ void (*clip_to_rect)(void* user, const BRect& rect, bool inverse);
	// Why not BShape?
	/* 54 */ void (*clip_to_shape)(void* user, int32 opCount, const uint32 opList[], int32 ptCount,
		const BPoint ptList[], bool inverse);
	/* 55 */ void (*draw_string_locations)(void* user, const char* string, const BPoint* locations,
		size_t locationCount);

	/* 56 */ void (*fill_rect_gradient)(void* user, BRect rect, const BGradient& gradient);
	/* 57 */ void (*stroke_rect_gradient)(void* user, BRect rect, const BGradient& gradient);
	/* 58 */ void (*fill_round_rect_gradient)(void* user, BRect rect, BPoint radii,
		const BGradient& gradient);
	/* 59 */ void (*stroke_round_rect_gradient)(void* user, BRect rect, BPoint radii,
		const BGradient& gradient);
	/* 60 */ void (*fill_bezier_gradient)(void* user, const BPoint* points,
		const BGradient& gradient);
	/* 61 */ void (*stroke_bezier_gradient)(void* user, const BPoint* points,
		const BGradient& gradient);
	/* 62 */ void (*fill_arc_gradient)(void* user, BPoint center, BPoint radii, float startTheta,
		float arcTheta, const BGradient& gradient);
	/* 63 */ void (*stroke_arc_gradient)(void* user, BPoint center, BPoint radii, float startTheta,
		float arcTheta, const BGradient& gradient);
	/* 64 */ void (*fill_ellipse_gradient)(void* user, BPoint center, BPoint radii,
		const BGradient& gradient);
	/* 65 */ void (*stroke_ellipse_gradient)(void* user, BPoint center, BPoint radii,
		const BGradient& gradient);
	/* 66 */ void (*fill_polygon_gradient)(void* user, int32 numPoints, const BPoint* points,
		bool isClosed, const BGradient& gradient);
	/* 67 */ void (*stroke_polygon_gradient)(void* user, int32 numPoints, const BPoint* points,
		bool isClosed, const BGradient& gradient);
	/* 68 */ void (*fill_shape_gradient)(void* user, BShape shape, const BGradient& gradient);
	/* 69 */ void (*stroke_shape_gradient)(void* user, BShape shape, const BGradient& gradient);

	/* 70 */ void (*set_fill_rule)(void* user, int32 fillRule);

	/* 71 */ void (*stroke_line_gradient)(void* user, BPoint start, BPoint end,
		const BGradient& gradient);
};


class PicturePlayerCallbacks {
public:
	virtual void MovePenBy(const BPoint& where) {}
	virtual void StrokeLine(const BPoint& start, const BPoint& end) {}
	virtual void DrawRect(const BRect& rect, bool fill) {}
	virtual void DrawRoundRect(const BRect& rect, const BPoint& radii, bool fill) {}
	virtual void DrawBezier(const BPoint controlPoints[4], bool fill) {}
	virtual void DrawArc(const BPoint& center, const BPoint& radii, float startTheta,
		float arcTheta, bool fill) {}
	virtual void DrawEllipse(const BRect& rect, bool fill) {}
	virtual void DrawPolygon(size_t numPoints, const BPoint points[], bool isClosed, bool fill) {}
	virtual void DrawShape(const BShape& shape, bool fill) {}
	virtual void DrawString(const char* string, size_t length, float spaceEscapement,
		float nonSpaceEscapement) {}
	virtual void DrawPixels(const BRect& source, const BRect& destination, uint32 width,
		uint32 height, size_t bytesPerRow, color_space pixelFormat, uint32 flags, const void* data,
		size_t length) {}
	virtual void DrawPicture(const BPoint& where, int32 token) {}
	virtual void SetClippingRects(size_t numRects, const clipping_rect rects[]) {}
	virtual void ClipToPicture(int32 token, const BPoint& where, bool clipToInverse) {}
	virtual void PushState() {}
	virtual void PopState() {}
	virtual void EnterStateChange() {}
	virtual void ExitStateChange() {}
	virtual void EnterFontState() {}
	virtual void ExitFontState() {}
	virtual void SetOrigin(const BPoint& origin) {}
	virtual void SetPenLocation(const BPoint& location) {}
	virtual void SetDrawingMode(drawing_mode mode) {}
	virtual void SetLineMode(cap_mode capMode, join_mode joinMode, float miterLimit) {}
	virtual void SetPenSize(float size) {}
	virtual void SetForeColor(const rgb_color& color) {}
	virtual void SetBackColor(const rgb_color& color) {}
	virtual void SetStipplePattern(const pattern& patter) {}
	virtual void SetScale(float scale) {}
	virtual void SetFontFamily(const char* familyName, size_t length) {}
	virtual void SetFontStyle(const char* styleName, size_t length) {}
	virtual void SetFontSpacing(uint8 spacing) {}
	virtual void SetFontSize(float size) {}
	virtual void SetFontRotation(float rotation) {}
	virtual void SetFontEncoding(uint8 encoding) {}
	virtual void SetFontFlags(uint32 flags) {}
	virtual void SetFontShear(float shear) {}
	virtual void SetFontFace(uint16 face) {}
	virtual void SetBlendingMode(source_alpha alphaSourceMode, alpha_function alphaFunctionMode) {}
	virtual void SetTransform(const BAffineTransform& transform) {}
	virtual void TranslateBy(double x, double y) {}
	virtual void ScaleBy(double x, double y) {}
	virtual void RotateBy(double angleRadians) {}
	virtual void BlendLayer(Layer* layer) {}
	virtual void ClipToRect(const BRect& rect, bool inverse) {}
	virtual void ClipToShape(int32 opCount, const uint32 opList[], int32 ptCount,
		const BPoint ptList[], bool inverse) {}
	virtual void DrawStringLocations(const char* string, size_t length, const BPoint locations[],
		size_t locationCount) {}
	virtual void DrawRectGradient(const BRect& rect, BGradient& gradient, bool fill) {}
	virtual void DrawRoundRectGradient(const BRect& rect, const BPoint& radii, BGradient& gradient,
		bool fill) {}
	virtual void DrawBezierGradient(const BPoint controlPoints[4], BGradient& gradient, bool fill)
		{}
	virtual void DrawArcGradient(const BPoint& center, const BPoint& radii, float startTheta,
		float arcTheta, BGradient& gradient, bool fill) {}
	virtual void DrawEllipseGradient(const BRect& rect, BGradient& gradient, bool fill) {}
	virtual void DrawPolygonGradient(size_t numPoints, const BPoint points[], bool isClosed,
		BGradient& gradient, bool fill) {}
	virtual void DrawShapeGradient(const BShape& shape, BGradient& gradient, bool fill) {}
	virtual void SetFillRule(int32 fillRule) {}
	virtual void StrokeLineGradient(const BPoint& start, const BPoint& end,
		const BGradient& gradient) {}
};


@@ -115,11 +221,10 @@

	status_t	Play(void** callbacks, int32 tableEntries,
					void* userData);
	status_t	Play(const picture_player_callbacks& callbacks,
					size_t callbacksSize, void* userData);
	status_t	Play(PicturePlayerCallbacks& callbacks);

private:
	status_t	_Play(const picture_player_callbacks& callbacks, void* userData,
	status_t	_Play(PicturePlayerCallbacks& callbacks,
					const void* data, size_t length, uint16 parentOp);

	const void*	fData;
diff --git a/src/kits/interface/PicturePlayer.cpp b/src/kits/interface/PicturePlayer.cpp
index 80479db..3538ac4 100644
--- a/src/kits/interface/PicturePlayer.cpp
+++ b/src/kits/interface/PicturePlayer.cpp
@@ -29,11 +29,84 @@


using BPrivate::PicturePlayer;
using BPrivate::PicturePlayerCallbacks;
using BPrivate::picture_player_callbacks_compat;


struct adapter_context {
	void* user_data;
	void** function_table;
class CallbackAdapterPlayer : public PicturePlayerCallbacks {
public:
	CallbackAdapterPlayer(void* userData, void** functionTable);

	virtual void MovePenBy(const BPoint& where);
	virtual void StrokeLine(const BPoint& start, const BPoint& end);
	virtual void DrawRect(const BRect& rect, bool fill);
	virtual void DrawRoundRect(const BRect& rect, const BPoint& radii, bool fill);
	virtual void DrawBezier(const BPoint controlPoints[4], bool fill);
	virtual void DrawArc(const BPoint& center, const BPoint& radii, float startTheta,
		float arcTheta, bool fill);
	virtual void DrawEllipse(const BRect& rect, bool fill);
	virtual void DrawPolygon(size_t numPoints, const BPoint points[], bool isClosed, bool fill);
	virtual void DrawShape(const BShape& shape, bool fill);
	virtual void DrawString(const char* string, size_t length, float spaceEscapement,
		float nonSpaceEscapement);
	virtual void DrawPixels(const BRect& source, const BRect& destination, uint32 width,
		uint32 height, size_t bytesPerRow, color_space pixelFormat, uint32 flags, const void* data,
		size_t length);
	virtual void DrawPicture(const BPoint& where, int32 token);
	virtual void SetClippingRects(size_t numRects, const clipping_rect rects[]);
	virtual void ClipToPicture(int32 token, const BPoint& where, bool clipToInverse);
	virtual void PushState();
	virtual void PopState();
	virtual void EnterStateChange();
	virtual void ExitStateChange();
	virtual void EnterFontState();
	virtual void ExitFontState();
	virtual void SetOrigin(const BPoint& origin);
	virtual void SetPenLocation(const BPoint& location);
	virtual void SetDrawingMode(drawing_mode mode);
	virtual void SetLineMode(cap_mode capMode, join_mode joinMode, float miterLimit);
	virtual void SetPenSize(float size);
	virtual void SetForeColor(const rgb_color& color);
	virtual void SetBackColor(const rgb_color& color);
	virtual void SetStipplePattern(const pattern& patter);
	virtual void SetScale(float scale);
	virtual void SetFontFamily(const char* familyName, size_t length);
	virtual void SetFontStyle(const char* styleName, size_t length);
	virtual void SetFontSpacing(uint8 spacing);
	virtual void SetFontSize(float size);
	virtual void SetFontRotation(float rotation);
	virtual void SetFontEncoding(uint8 encoding);
	virtual void SetFontFlags(uint32 flags);
	virtual void SetFontShear(float shear);
	virtual void SetFontFace(uint16 face);
	virtual void SetBlendingMode(source_alpha alphaSourceMode, alpha_function alphaFunctionMode);
	virtual void SetTransform(const BAffineTransform& transform);
	virtual void TranslateBy(double x, double y);
	virtual void ScaleBy(double x, double y);
	virtual void RotateBy(double angleRadians);
	virtual void BlendLayer(Layer* layer);
	virtual void ClipToRect(const BRect& rect, bool inverse);
	virtual void ClipToShape(int32 opCount, const uint32 opList[], int32 ptCount,
		const BPoint ptList[], bool inverse);
	virtual void DrawStringLocations(const char* string, size_t length, const BPoint locations[],
		size_t locationCount);
	virtual void DrawRectGradient(const BRect& rect, BGradient& gradient, bool fill);
	virtual void DrawRoundRectGradient(const BRect& rect, const BPoint& radii, BGradient& gradient,
		bool fill);
	virtual void DrawBezierGradient(const BPoint controlPoints[4], BGradient& gradient, bool fill);
	virtual void DrawArcGradient(const BPoint& center, const BPoint& radii, float startTheta,
		float arcTheta, BGradient& gradient, bool fill);
	virtual void DrawEllipseGradient(const BRect& rect, BGradient& gradient, bool fill);
	virtual void DrawPolygonGradient(size_t numPoints, const BPoint points[], bool isClosed,
		BGradient& gradient, bool fill);
	virtual void DrawShapeGradient(const BShape& shape, BGradient& gradient, bool fill);
	virtual void SetFillRule(int32 fillRule);
	virtual void StrokeLineGradient(const BPoint& start, const BPoint& end,
		const BGradient& gradient);

private:
	void* fUserData;
	picture_player_callbacks_compat* fCallbacks;
};


@@ -43,82 +116,89 @@
}


static void
move_pen_by(void* _context, const BPoint& delta)
CallbackAdapterPlayer::CallbackAdapterPlayer(void* userData, void** functionTable)
	:
	fUserData(userData),
	fCallbacks((picture_player_callbacks_compat*)functionTable)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, BPoint))context->function_table[1])(context->user_data,
		delta);
}


static void
stroke_line(void* _context, const BPoint& start, const BPoint& end)
void
CallbackAdapterPlayer::MovePenBy(const BPoint& delta)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, BPoint, BPoint))context->function_table[2])(
		context->user_data, start, end);
	fCallbacks->move_pen_by(fUserData, delta);
}


static void
draw_rect(void* _context, const BRect& rect, bool fill)
void
CallbackAdapterPlayer::StrokeLine(const BPoint& start, const BPoint& end)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, BRect))context->function_table[fill ? 4 : 3])(
		context->user_data, rect);
	fCallbacks->stroke_line(fUserData, start, end);
}


static void
draw_round_rect(void* _context, const BRect& rect, const BPoint& radii,
	bool fill)
void
CallbackAdapterPlayer::DrawRect(const BRect& rect, bool fill)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, BRect, BPoint))context->function_table[fill ? 6 : 5])(
		context->user_data, rect, radii);
	if (fill)
		fCallbacks->fill_rect(fUserData, rect);
	else
		fCallbacks->stroke_rect(fUserData, rect);
}


static void
draw_bezier(void* _context, const BPoint _points[4], bool fill)
void
CallbackAdapterPlayer::DrawRoundRect(const BRect& rect, const BPoint& radii,
	bool fill)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	if (fill)
		fCallbacks->fill_round_rect(fUserData, rect, radii);
	else
		fCallbacks->stroke_round_rect(fUserData, rect, radii);
}


void
CallbackAdapterPlayer::DrawBezier(const BPoint _points[4], bool fill)
{
	BPoint points[4] = { _points[0], _points[1], _points[2], _points[3] };
	((void (*)(void*, BPoint*))context->function_table[fill ? 8 : 7])(
		context->user_data, points);

	if (fill)
		fCallbacks->fill_bezier(fUserData, points);
	else
		fCallbacks->stroke_bezier(fUserData, points);
}


static void
draw_arc(void* _context, const BPoint& center, const BPoint& radii,
void
CallbackAdapterPlayer::DrawArc(const BPoint& center, const BPoint& radii,
	float startTheta, float arcTheta, bool fill)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, BPoint, BPoint, float, float))
		context->function_table[fill ? 10 : 9])(context->user_data, center,
			radii, startTheta, arcTheta);
	if (fill)
		fCallbacks->fill_arc(fUserData, center, radii, startTheta, arcTheta);
	else
		fCallbacks->stroke_arc(fUserData, center, radii, startTheta, arcTheta);
}


static void
draw_ellipse(void* _context, const BRect& rect, bool fill)
void
CallbackAdapterPlayer::DrawEllipse(const BRect& rect, bool fill)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	BPoint radii((rect.Width() + 1) / 2.0f, (rect.Height() + 1) / 2.0f);
	BPoint center = rect.LeftTop() + radii;
	((void (*)(void*, BPoint, BPoint))
		context->function_table[fill ? 12 : 11])(context->user_data, center,
			radii);

	if (fill)
		fCallbacks->fill_ellipse(fUserData, center, radii);
	else
		fCallbacks->stroke_ellipse(fUserData, center, radii);
}


static void
draw_polygon(void* _context, size_t numPoints, const BPoint _points[],
void
CallbackAdapterPlayer::DrawPolygon(size_t numPoints, const BPoint _points[],
	bool isClosed, bool fill)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);

	BStackOrHeapArray<BPoint, 200> points(numPoints);
	if (!points.IsValid())
@@ -126,70 +206,63 @@

	memcpy((void*)points, _points, numPoints * sizeof(BPoint));

	((void (*)(void*, int32, BPoint*, bool))
		context->function_table[fill ? 14 : 13])(context->user_data, numPoints,
			points, isClosed);
	if (fill)
		fCallbacks->fill_polygon(fUserData, numPoints, points, isClosed);
	else
		fCallbacks->stroke_polygon(fUserData, numPoints, points, isClosed);
}


static void
draw_shape(void* _context, const BShape& shape, bool fill)
void
CallbackAdapterPlayer::DrawShape(const BShape& shape, bool fill)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, BShape))context->function_table[fill ? 16 : 15])(
		context->user_data, shape);
	if (fill)
		fCallbacks->fill_shape(fUserData, &shape);
	else
		fCallbacks->stroke_shape(fUserData, &shape);
}


static void
draw_string(void* _context, const char* _string, size_t length,
void
CallbackAdapterPlayer::DrawString(const char* _string, size_t length,
	float deltaSpace, float deltaNonSpace)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	char* string = strndup(_string, length);

	((void (*)(void*, char*, float, float))
		context->function_table[17])(context->user_data, string, deltaSpace,
			deltaNonSpace);
	fCallbacks->draw_string(fUserData, string, deltaSpace, deltaNonSpace);

	free(string);
}


static void
draw_pixels(void* _context, const BRect& src, const BRect& dest, uint32 width,
void
CallbackAdapterPlayer::DrawPixels(const BRect& src, const BRect& dest, uint32 width,
	uint32 height, size_t bytesPerRow, color_space pixelFormat, uint32 options,
	const void* _data, size_t length)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	void* data = malloc(length);
	if (data == NULL)
		return;

	memcpy(data, _data, length);

	((void (*)(void*, BRect, BRect, int32, int32, int32, int32, int32, void*))
		context->function_table[18])(context->user_data, src, dest, width,
	fCallbacks->draw_pixels(fUserData, src, dest, width,
			height, bytesPerRow, pixelFormat, options, data);

	free(data);
}


static void
draw_picture(void* _context, const BPoint& where, int32 token)
void
CallbackAdapterPlayer::DrawPicture(const BPoint& where, int32 token)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, BPoint, int32))context->function_table[19])(
		context->user_data, where, token);
	fCallbacks->draw_picture(fUserData, where, token);
}


static void
set_clipping_rects(void* _context, size_t numRects, const clipping_rect _rects[])
void
CallbackAdapterPlayer::SetClippingRects(size_t numRects, const clipping_rect _rects[])
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);

	// This is rather ugly but works for such a trivial class.
	BStackOrHeapArray<BRect, 100> rects(numRects);
	if (!rects.IsValid())
@@ -200,426 +273,362 @@
		rects[i] = BRect(srcRect.left, srcRect.top, srcRect.right, srcRect.bottom);
	}

	((void (*)(void*, BRect*, uint32))context->function_table[20])(
		context->user_data, rects, numRects);
	fCallbacks->set_clipping_rects(fUserData, rects, numRects);
}


static void
clip_to_picture(void* _context, int32 token, const BPoint& origin,
void
CallbackAdapterPlayer::ClipToPicture(int32 token, const BPoint& origin,
	bool clipToInverse)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, int32, BPoint, bool))context->function_table[21])(
			context->user_data, token, origin, clipToInverse);
	fCallbacks->clip_to_picture(fUserData, token, origin, clipToInverse);
}


static void
push_state(void* _context)
void
CallbackAdapterPlayer::PushState()
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*))context->function_table[22])(context->user_data);
	fCallbacks->push_state(fUserData);
}


static void
pop_state(void* _context)
void
CallbackAdapterPlayer::PopState()
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*))context->function_table[23])(context->user_data);
	fCallbacks->pop_state(fUserData);
}


static void
enter_state_change(void* _context)
void
CallbackAdapterPlayer::EnterStateChange()
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*))context->function_table[24])(context->user_data);
	fCallbacks->enter_state_change(fUserData);
}


static void
exit_state_change(void* _context)
void
CallbackAdapterPlayer::ExitStateChange()
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*))context->function_table[25])(context->user_data);
	fCallbacks->exit_state_change(fUserData);
}


static void
enter_font_state(void* _context)
void
CallbackAdapterPlayer::EnterFontState()
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*))context->function_table[26])(context->user_data);
	fCallbacks->enter_font_state(fUserData);
}


static void
exit_font_state(void* _context)
void
CallbackAdapterPlayer::ExitFontState()
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*))context->function_table[27])(context->user_data);
	fCallbacks->exit_font_state(fUserData);
}


static void
set_origin(void* _context, const BPoint& origin)
void
CallbackAdapterPlayer::SetOrigin(const BPoint& origin)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, BPoint))context->function_table[28])(context->user_data,
		origin);
	fCallbacks->set_origin(fUserData, origin);
}


static void
set_pen_location(void* _context, const BPoint& penLocation)
void
CallbackAdapterPlayer::SetPenLocation(const BPoint& penLocation)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, BPoint))context->function_table[29])(context->user_data,
		penLocation);
	fCallbacks->set_pen_location(fUserData, penLocation);
}


static void
set_drawing_mode(void* _context, drawing_mode mode)
void
CallbackAdapterPlayer::SetDrawingMode(drawing_mode mode)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, drawing_mode))context->function_table[30])(
		context->user_data, mode);
	fCallbacks->set_drawing_mode(fUserData, mode);
}


static void
set_line_mode(void* _context, cap_mode capMode, join_mode joinMode,
void
CallbackAdapterPlayer::SetLineMode(cap_mode capMode, join_mode joinMode,
	float miterLimit)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, cap_mode, join_mode, float))context->function_table[31])(
		context->user_data, capMode, joinMode, miterLimit);
	fCallbacks->set_line_mode(fUserData, capMode, joinMode, miterLimit);
}


static void
set_pen_size(void* _context, float size)
void
CallbackAdapterPlayer::SetPenSize(float size)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, float))context->function_table[32])(context->user_data,
		size);
	fCallbacks->set_pen_size(fUserData, size);
}


static void
set_fore_color(void* _context, const rgb_color& color)
void
CallbackAdapterPlayer::SetForeColor(const rgb_color& color)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, rgb_color))context->function_table[33])(
		context->user_data, color);
	fCallbacks->set_fore_color(fUserData, color);
}


static void
set_back_color(void* _context, const rgb_color& color)
void
CallbackAdapterPlayer::SetBackColor(const rgb_color& color)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, rgb_color))context->function_table[34])(
		context->user_data, color);
	fCallbacks->set_back_color(fUserData, color);
}


static void
set_stipple_pattern(void* _context, const pattern& stipplePattern)
void
CallbackAdapterPlayer::SetStipplePattern(const pattern& stipplePattern)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, pattern))context->function_table[35])(context->user_data,
		stipplePattern);
	fCallbacks->set_stipple_pattern(fUserData, stipplePattern);
}


static void
set_scale(void* _context, float scale)
void
CallbackAdapterPlayer::SetScale(float scale)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, float))context->function_table[36])(context->user_data,
		scale);
	fCallbacks->set_scale(fUserData, scale);
}


static void
set_font_family(void* _context, const char* _family, size_t length)
void
CallbackAdapterPlayer::SetFontFamily(const char* _family, size_t length)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	char* family = strndup(_family, length);

	((void (*)(void*, char*))context->function_table[37])(context->user_data,
		family);
	fCallbacks->set_font_family(fUserData, family);

	free(family);
}


static void
set_font_style(void* _context, const char* _style, size_t length)
void
CallbackAdapterPlayer::SetFontStyle(const char* _style, size_t length)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	char* style = strndup(_style, length);

	((void (*)(void*, char*))context->function_table[38])(context->user_data,
		style);
	fCallbacks->set_font_style(fUserData, style);

	free(style);
}


static void
set_font_spacing(void* _context, uint8 spacing)
void
CallbackAdapterPlayer::SetFontSpacing(uint8 spacing)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, int32))context->function_table[39])(context->user_data,
		spacing);
	fCallbacks->set_font_spacing(fUserData, spacing);
}


static void
set_font_size(void* _context, float size)
void
CallbackAdapterPlayer::SetFontSize(float size)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, float))context->function_table[40])(context->user_data,
		size);
	fCallbacks->set_font_size(fUserData, size);
}


static void
set_font_rotation(void* _context, float rotation)
void
CallbackAdapterPlayer::SetFontRotation(float rotation)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, float))context->function_table[41])(context->user_data,
		rotation);
	fCallbacks->set_font_rotate(fUserData, rotation);
}


static void
set_font_encoding(void* _context, uint8 encoding)
void
CallbackAdapterPlayer::SetFontEncoding(uint8 encoding)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, int32))context->function_table[42])(context->user_data,
		encoding);
	fCallbacks->set_font_encoding(fUserData, encoding);
}


static void
set_font_flags(void* _context, uint32 flags)
void
CallbackAdapterPlayer::SetFontFlags(uint32 flags)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, int32))context->function_table[43])(context->user_data,
		flags);
	fCallbacks->set_font_flags(fUserData, flags);
}


static void
set_font_shear(void* _context, float shear)
void
CallbackAdapterPlayer::SetFontShear(float shear)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, float))context->function_table[44])(context->user_data,
		shear);
	fCallbacks->set_font_shear(fUserData, shear);
}


static void
set_font_face(void* _context, uint16 face)
void
CallbackAdapterPlayer::SetFontFace(uint16 face)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, int32))context->function_table[46])(context->user_data,
		face);
	fCallbacks->set_font_face(fUserData, face);
}


static void
set_blending_mode(void* _context, source_alpha alphaSrcMode,
void
CallbackAdapterPlayer::SetBlendingMode(source_alpha alphaSrcMode,
	alpha_function alphaFncMode)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, source_alpha, alpha_function))
		context->function_table[47])(context->user_data, alphaSrcMode,
			alphaFncMode);
	fCallbacks->set_blending_mode(fUserData, alphaSrcMode, alphaFncMode);
}


static void
set_transform(void* _context, const BAffineTransform& transform)
void
CallbackAdapterPlayer::SetTransform(const BAffineTransform& transform)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, const BAffineTransform&))
		context->function_table[48])(context->user_data, transform);
	fCallbacks->set_transform(fUserData, transform);
}


static void
translate_by(void* _context, double x, double y)
void
CallbackAdapterPlayer::TranslateBy(double x, double y)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, double, double))
		context->function_table[49])(context->user_data, x, y);
	fCallbacks->translate_by(fUserData, x, y);
}


static void
scale_by(void* _context, double x, double y)
void
CallbackAdapterPlayer::ScaleBy(double x, double y)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, double, double))
		context->function_table[50])(context->user_data, x, y);
	fCallbacks->scale_by(fUserData, x, y);
}


static void
rotate_by(void* _context, double angleRadians)
void
CallbackAdapterPlayer::RotateBy(double angleRadians)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, double))
		context->function_table[51])(context->user_data, angleRadians);
	fCallbacks->rotate_by(fUserData, angleRadians);
}


static void
blend_layer(void* _context, Layer* layer)
void
CallbackAdapterPlayer::BlendLayer(Layer* layer)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, Layer*))
		context->function_table[52])(context->user_data, layer);
	fCallbacks->blend_layer(fUserData, layer);
}


static void
clip_to_rect(void* _context, const BRect& rect, bool inverse)
void
CallbackAdapterPlayer::ClipToRect(const BRect& rect, bool inverse)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, const BRect&, bool))
		context->function_table[53])(context->user_data, rect, inverse);
	fCallbacks->clip_to_rect(fUserData, rect, inverse);
}


static void
clip_to_shape(void* _context, int32 opCount, const uint32 opList[],
void
CallbackAdapterPlayer::ClipToShape(int32 opCount, const uint32 opList[],
	int32 ptCount, const BPoint ptList[], bool inverse)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, int32, const uint32*, int32, const BPoint*, bool))
		context->function_table[54])(context->user_data, opCount, opList,
	fCallbacks->clip_to_shape(fUserData, opCount, opList,
			ptCount, ptList, inverse);
}


static void
draw_string_locations(void* _context, const char* _string, size_t length,
void
CallbackAdapterPlayer::DrawStringLocations(const char* _string, size_t length,
	const BPoint* locations, size_t locationCount)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	char* string = strndup(_string, length);

	((void (*)(void*, char*, const BPoint*, size_t))
		context->function_table[55])(context->user_data, string, locations,
	fCallbacks->draw_string_locations(fUserData, string, locations,
			locationCount);

	free(string);
}


static void
draw_rect_gradient(void* _context, const BRect& rect, BGradient& gradient, bool fill)
void
CallbackAdapterPlayer::DrawRectGradient(const BRect& rect, BGradient& gradient, bool fill)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, BRect, BGradient&))context->function_table[fill ? 56 : 57])(
		context->user_data, rect, gradient);
	if (fill)
		fCallbacks->fill_rect_gradient(fUserData, rect, gradient);
	else
		fCallbacks->stroke_rect_gradient(fUserData, rect, gradient);
}


static void
draw_round_rect_gradient(void* _context, const BRect& rect, const BPoint& radii, BGradient& gradient,
void
CallbackAdapterPlayer::DrawRoundRectGradient(const BRect& rect, const BPoint& radii, BGradient& gradient,
	bool fill)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, BRect, BPoint, BGradient&))context->function_table[fill ? 58 : 59])(
		context->user_data, rect, radii, gradient);
	if (fill)
		fCallbacks->fill_round_rect_gradient(fUserData, rect, radii, gradient);
	else
		fCallbacks->stroke_round_rect_gradient(fUserData, rect, radii, gradient);
}


static void
draw_bezier_gradient(void* _context, const BPoint _points[4], BGradient& gradient, bool fill)
void
CallbackAdapterPlayer::DrawBezierGradient(const BPoint _points[4], BGradient& gradient, bool fill)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);

	BPoint points[4] = { _points[0], _points[1], _points[2], _points[3] };
	((void (*)(void*, BPoint*, BGradient&))context->function_table[fill ? 60 : 61])(
		context->user_data, points, gradient);

	if (fill)
		fCallbacks->fill_bezier_gradient(fUserData, points, gradient);
	else
		fCallbacks->stroke_bezier_gradient(fUserData, points, gradient);
}


static void
draw_arc_gradient(void* _context, const BPoint& center, const BPoint& radii,
void
CallbackAdapterPlayer::DrawArcGradient(const BPoint& center, const BPoint& radii,
	float startTheta, float arcTheta, BGradient& gradient, bool fill)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, BPoint, BPoint, float, float, BGradient&))
		context->function_table[fill ? 62 : 63])(context->user_data, center,
			radii, startTheta, arcTheta, gradient);
	if (fill)
		fCallbacks->fill_arc_gradient(fUserData, center, radii, startTheta, arcTheta, gradient);
	else
		fCallbacks->stroke_arc_gradient(fUserData, center, radii, startTheta, arcTheta, gradient);
}


static void
draw_ellipse_gradient(void* _context, const BRect& rect, BGradient& gradient, bool fill)
void
CallbackAdapterPlayer::DrawEllipseGradient(const BRect& rect, BGradient& gradient, bool fill)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	BPoint radii((rect.Width() + 1) / 2.0f, (rect.Height() + 1) / 2.0f);
	BPoint center = rect.LeftTop() + radii;
	((void (*)(void*, BPoint, BPoint, BGradient&))
		context->function_table[fill ? 64 : 65])(context->user_data, center,
			radii, gradient);

	if (fill)
		fCallbacks->fill_ellipse_gradient(fUserData, center, radii, gradient);
	else
		fCallbacks->stroke_ellipse_gradient(fUserData, center, radii, gradient);
}


static void
draw_polygon_gradient(void* _context, size_t numPoints, const BPoint _points[],
void
CallbackAdapterPlayer::DrawPolygonGradient(size_t numPoints, const BPoint _points[],
	bool isClosed, BGradient& gradient, bool fill)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);

	BStackOrHeapArray<BPoint, 200> points(numPoints);
	if (!points.IsValid())
		return;

	memcpy((void*)points, _points, numPoints * sizeof(BPoint));

	((void (*)(void*, int32, BPoint*, bool, BGradient&))
		context->function_table[fill ? 66 : 67])(context->user_data, numPoints,
			points, isClosed, gradient);
	if (fill)
		fCallbacks->fill_polygon_gradient(fUserData, numPoints, points, isClosed, gradient);
	else
		fCallbacks->stroke_polygon_gradient(fUserData, numPoints, points, isClosed, gradient);
}


static void
draw_shape_gradient(void* _context, const BShape& shape, BGradient& gradient, bool fill)
void
CallbackAdapterPlayer::DrawShapeGradient(const BShape& shape, BGradient& gradient, bool fill)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, BShape, BGradient&))context->function_table[fill ? 68 : 69])(
		context->user_data, shape, gradient);
	if (fill)
		fCallbacks->fill_shape_gradient(fUserData, shape, gradient);
	else
		fCallbacks->stroke_shape_gradient(fUserData, shape, gradient);
}


static void
set_fill_rule(void* _context, int32 fillRule)
void
CallbackAdapterPlayer::SetFillRule(int32 fillRule)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, int32))context->function_table[70])(
		context->user_data, fillRule);
	fCallbacks->set_fill_rule(fUserData, fillRule);
}


static void
stroke_line_gradient(void* _context, const BPoint& start, const BPoint& end, const BGradient& gradient)
void
CallbackAdapterPlayer::StrokeLineGradient(const BPoint& start, const BPoint& end, const BGradient& gradient)
{
	adapter_context* context = reinterpret_cast<adapter_context*>(_context);
	((void (*)(void*, BPoint, BPoint, const BGradient&))context->function_table[71])(
		context->user_data, start, end, gradient);
	fCallbacks->stroke_line_gradient(fUserData, start, end, gradient);
}


@@ -728,65 +737,6 @@
status_t
PicturePlayer::Play(void** callBackTable, int32 tableEntries, void* userData)
{
	const BPrivate::picture_player_callbacks kAdapterCallbacks = {
		move_pen_by,
		stroke_line,
		draw_rect,
		draw_round_rect,
		draw_bezier,
		draw_arc,
		draw_ellipse,
		draw_polygon,
		draw_shape,
		draw_string,
		draw_pixels,
		draw_picture,
		set_clipping_rects,
		clip_to_picture,
		push_state,
		pop_state,
		enter_state_change,
		exit_state_change,
		enter_font_state,
		exit_font_state,
		set_origin,
		set_pen_location,
		set_drawing_mode,
		set_line_mode,
		set_pen_size,
		set_fore_color,
		set_back_color,
		set_stipple_pattern,
		set_scale,
		set_font_family,
		set_font_style,
		set_font_spacing,
		set_font_size,
		set_font_rotation,
		set_font_encoding,
		set_font_flags,
		set_font_shear,
		set_font_face,
		set_blending_mode,
		set_transform,
		translate_by,
		scale_by,
		rotate_by,
		blend_layer,
		clip_to_rect,
		clip_to_shape,
		draw_string_locations,
		draw_rect_gradient,
		draw_round_rect_gradient,
		draw_bezier_gradient,
		draw_arc_gradient,
		draw_ellipse_gradient,
		draw_polygon_gradient,
		draw_shape_gradient,
		set_fill_rule,
		stroke_line_gradient
	};

	// We don't check if the functions in the table are NULL, but we
	// check the tableEntries to see if the table is big enough.
	// If an application supplies the wrong size or an invalid pointer,
@@ -796,27 +746,23 @@
	// we use our dummy table, and copy the supported ops from the supplied one.
	void *dummyTable[kOpsTableSize];

	adapter_context adapterContext;
	adapterContext.user_data = userData;
	adapterContext.function_table = callBackTable;

	if ((size_t)tableEntries < kOpsTableSize) {
		memcpy(dummyTable, callBackTable, tableEntries * sizeof(void*));
		for (size_t i = (size_t)tableEntries; i < kOpsTableSize; i++)
			dummyTable[i] = (void*)nop;

		adapterContext.function_table = dummyTable;
		callBackTable = dummyTable;
	}

	return _Play(kAdapterCallbacks, &adapterContext, fData, fSize, 0);
	CallbackAdapterPlayer callbackAdapterPlayer(userData, callBackTable);
	return _Play(callbackAdapterPlayer, fData, fSize, 0);
}


status_t
PicturePlayer::Play(const picture_player_callbacks& callbacks,
	size_t callbacksSize, void* userData)
PicturePlayer::Play(PicturePlayerCallbacks& callbacks)
{
	return _Play(callbacks, userData, fData, fSize, 0);
	return _Play(callbacks, fData, fSize, 0);
}


@@ -888,7 +834,7 @@


status_t
PicturePlayer::_Play(const picture_player_callbacks& callbacks, void* userData,
PicturePlayer::_Play(PicturePlayerCallbacks& callbacks,
	const void* buffer, size_t length, uint16 parentOp)
{
#if DEBUG

@@ -941,10 +887,10 @@
			case B_PIC_MOVE_PEN_BY:
			{
				const BPoint* where;
				if (callbacks.move_pen_by == NULL || !reader.Get(where))
				if (!reader.Get(where))
					break;

				callbacks.move_pen_by(userData, *where);
				callbacks.MovePenBy(*where);
				break;
			}

@@ -952,12 +898,10 @@
			{
				const BPoint* start;
				const BPoint* end;
				if (callbacks.stroke_line == NULL || !reader.Get(start)
					|| !reader.Get(end)) {
				if (!reader.Get(start) || !reader.Get(end))
					break;
				}

				callbacks.stroke_line(userData, *start, *end);
				callbacks.StrokeLine(*start, *end);
				break;
			}

@@ -965,11 +909,10 @@
			case B_PIC_FILL_RECT:
			{
				const BRect* rect;
				if (callbacks.draw_rect == NULL || !reader.Get(rect))
				if (!reader.Get(rect))
					break;

				callbacks.draw_rect(userData, *rect,
					header->op == B_PIC_FILL_RECT);
				callbacks.DrawRect(*rect, header->op == B_PIC_FILL_RECT);
				break;
			}

@@ -978,12 +921,10 @@
			{
				const BRect* rect;
				const BPoint* radii;
				if (callbacks.draw_round_rect == NULL || !reader.Get(rect)
					|| !reader.Get(radii)) {
				if (!reader.Get(rect) || !reader.Get(radii))
					break;
				}

				callbacks.draw_round_rect(userData, *rect, *radii,
				callbacks.DrawRoundRect(*rect, *radii,
					header->op == B_PIC_FILL_ROUND_RECT);
				break;
			}
@@ -993,12 +934,10 @@
			{
				const size_t kNumControlPoints = 4;
				const BPoint* controlPoints;
				if (callbacks.draw_bezier == NULL
					|| !reader.Get(controlPoints, kNumControlPoints)) {
				if (!reader.Get(controlPoints, kNumControlPoints))
					break;
				}

				callbacks.draw_bezier(userData, controlPoints, header->op == B_PIC_FILL_BEZIER);
				callbacks.DrawBezier(controlPoints, header->op == B_PIC_FILL_BEZIER);
				break;
			}

@@ -1009,13 +948,13 @@
				const BPoint* radii;
				const float* startTheta;
				const float* arcTheta;
				if (callbacks.draw_arc == NULL || !reader.Get(center)
				if (!reader.Get(center)
					|| !reader.Get(radii) || !reader.Get(startTheta)
					|| !reader.Get(arcTheta)) {
					break;
				}

				callbacks.draw_arc(userData, *center, *radii, *startTheta,
				callbacks.DrawArc(*center, *radii, *startTheta,
					*arcTheta, header->op == B_PIC_FILL_ARC);
				break;
			}
@@ -1024,10 +963,10 @@
			case B_PIC_FILL_ELLIPSE:
			{
				const BRect* rect;
				if (callbacks.draw_ellipse == NULL || !reader.Get(rect))
				if (!reader.Get(rect))
					break;

				callbacks.draw_ellipse(userData, *rect,
				callbacks.DrawEllipse(*rect,
					header->op == B_PIC_FILL_ELLIPSE);
				break;
			}
@@ -1037,10 +976,8 @@
			{
				const uint32* numPoints;
				const BPoint* points;
				if (callbacks.draw_polygon == NULL || !reader.Get(numPoints)
					|| !reader.Get(points, *numPoints)) {
				if (!reader.Get(numPoints) || !reader.Get(points, *numPoints))
					break;
				}

				bool isClosed = true;
				const bool* closedPointer;
@@ -1051,7 +988,7 @@
					isClosed = *closedPointer;
				}

				callbacks.draw_polygon(userData, *numPoints, points, isClosed,
				callbacks.DrawPolygon(*numPoints, points, isClosed,
					header->op == B_PIC_FILL_POLYGON);
				break;
			}
@@ -1063,7 +1000,7 @@
				const uint32* pointCount;
				const uint32* opList;
				const BPoint* pointList;
				if (callbacks.draw_shape == NULL || !reader.Get(opCount)
				if (!reader.Get(opCount)
					|| !reader.Get(pointCount) || !reader.Get(opList, *opCount)
					|| !reader.Get(pointList, *pointCount)) {
					break;
@@ -1073,8 +1010,7 @@
				BShape shape;
				BShape::Private(shape).SetData(*opCount, *pointCount, opList, pointList);

				callbacks.draw_shape(userData, shape,
					header->op == B_PIC_FILL_SHAPE);
				callbacks.DrawShape(shape, header->op == B_PIC_FILL_SHAPE);
				break;
			}

@@ -1083,11 +1019,11 @@
			{
				const BRect* rect;
				BGradient* gradient;
				if (callbacks.draw_rect_gradient == NULL || !reader.Get(rect) || !reader.GetGradient(gradient))
				if (!reader.Get(rect) || !reader.GetGradient(gradient))
					break;
				ObjectDeleter<BGradient> gradientDeleter(gradient);

				callbacks.draw_rect_gradient(userData, *rect, *gradient,
				callbacks.DrawRectGradient(*rect, *gradient,
					header->op == B_PIC_FILL_RECT_GRADIENT);
				break;
			}
@@ -1098,13 +1034,13 @@
				const BRect* rect;
				const BPoint* radii;
				BGradient* gradient;
				if (callbacks.draw_round_rect_gradient == NULL || !reader.Get(rect)
				if (!reader.Get(rect)
					|| !reader.Get(radii) || !reader.GetGradient(gradient)) {
					break;
				}
				ObjectDeleter<BGradient> gradientDeleter(gradient);

				callbacks.draw_round_rect_gradient(userData, *rect, *radii, *gradient,
				callbacks.DrawRoundRectGradient(*rect, *radii, *gradient,
					header->op == B_PIC_FILL_ROUND_RECT_GRADIENT);
				break;
			}
@@ -1115,13 +1051,11 @@
				const size_t kNumControlPoints = 4;
				const BPoint* controlPoints;
				BGradient* gradient;
				if (callbacks.draw_bezier_gradient == NULL
					|| !reader.Get(controlPoints, kNumControlPoints) || !reader.GetGradient(gradient)) {
				if (!reader.Get(controlPoints, kNumControlPoints) || !reader.GetGradient(gradient))
					break;
				}
				ObjectDeleter<BGradient> gradientDeleter(gradient);

				callbacks.draw_bezier_gradient(userData, controlPoints, *gradient,
				callbacks.DrawBezierGradient(controlPoints, *gradient,
					header->op == B_PIC_FILL_BEZIER_GRADIENT);
				break;
			}
@@ -1132,10 +1066,8 @@
				const uint32* numPoints;
				const BPoint* points;
				BGradient* gradient;
				if (callbacks.draw_polygon_gradient == NULL || !reader.Get(numPoints)
					|| !reader.Get(points, *numPoints)) {
				if (!reader.Get(numPoints) || !reader.Get(points, *numPoints))
					break;
				}

				bool isClosed = true;
				const bool* closedPointer;
@@ -1150,7 +1082,7 @@
					break;
				ObjectDeleter<BGradient> gradientDeleter(gradient);

				callbacks.draw_polygon_gradient(userData, *numPoints, points, isClosed, *gradient,
				callbacks.DrawPolygonGradient(*numPoints, points, isClosed, *gradient,
					header->op == B_PIC_FILL_POLYGON_GRADIENT);
				break;
			}
@@ -1163,7 +1095,7 @@
				const uint32* opList;
				const BPoint* pointList;
				BGradient* gradient;
				if (callbacks.draw_shape_gradient == NULL || !reader.Get(opCount)
				if (!reader.Get(opCount)
					|| !reader.Get(pointCount) || !reader.Get(opList, *opCount)
					|| !reader.Get(pointList, *pointCount) || !reader.GetGradient(gradient)) {
					break;
@@ -1174,7 +1106,7 @@
				BShape shape;
				BShape::Private(shape).SetData(*opCount, *pointCount, opList, pointList);

				callbacks.draw_shape_gradient(userData, shape, *gradient,
				callbacks.DrawShapeGradient(shape, *gradient,
					header->op == B_PIC_FILL_SHAPE_GRADIENT);
				break;
			}
@@ -1187,14 +1119,14 @@
				const float* startTheta;
				const float* arcTheta;
				BGradient* gradient;
				if (callbacks.draw_arc_gradient == NULL || !reader.Get(center)
				if (!reader.Get(center)
					|| !reader.Get(radii) || !reader.Get(startTheta)
					|| !reader.Get(arcTheta) || !reader.GetGradient(gradient)) {
					break;
				}
				ObjectDeleter<BGradient> gradientDeleter(gradient);

				callbacks.draw_arc_gradient(userData, *center, *radii, *startTheta,
				callbacks.DrawArcGradient(*center, *radii, *startTheta,
					*arcTheta, *gradient, header->op == B_PIC_FILL_ARC_GRADIENT);
				break;
			}
@@ -1204,11 +1136,11 @@
			{
				const BRect* rect;
				BGradient* gradient;
				if (callbacks.draw_ellipse_gradient == NULL || !reader.Get(rect) || !reader.GetGradient(gradient))
				if (!reader.Get(rect) || !reader.GetGradient(gradient))
					break;
				ObjectDeleter<BGradient> gradientDeleter(gradient);

				callbacks.draw_ellipse_gradient(userData, *rect, *gradient,
				callbacks.DrawEllipseGradient(*rect, *gradient,
					header->op == B_PIC_FILL_ELLIPSE_GRADIENT);
				break;
			}
@@ -1218,12 +1150,12 @@
				const BPoint* start;
				const BPoint* end;
				BGradient* gradient;
				if (callbacks.stroke_line_gradient == NULL || !reader.Get(start)
				if (!reader.Get(start)
					|| !reader.Get(end) || !reader.GetGradient(gradient)) {
					break;
				}

				callbacks.stroke_line_gradient(userData, *start, *end, *gradient);
				callbacks.StrokeLineGradient(*start, *end, *gradient);
				break;
			}

@@ -1233,15 +1165,14 @@
				const char* string;
				const float* escapementSpace;
				const float* escapementNonSpace;
				if (callbacks.draw_string == NULL
					|| !reader.Get(length)
				if (!reader.Get(length)
					|| !reader.Get(string, *length)
					|| !reader.Get(escapementSpace)
					|| !reader.Get(escapementNonSpace)) {
					break;
				}

				callbacks.draw_string(userData, string, *length,
				callbacks.DrawString(string, *length,
					*escapementSpace, *escapementNonSpace);
				break;
			}
@@ -1252,15 +1183,14 @@
				const BPoint* pointList;
				const int32* length;
				const char* string;
				if (callbacks.draw_string_locations == NULL
					|| !reader.Get(pointCount)
				if (!reader.Get(pointCount)
					|| !reader.Get(pointList, *pointCount)
					|| !reader.Get(length)
					|| !reader.Get(string, *length)) {
					break;
				}

				callbacks.draw_string_locations(userData, string, *length,
				callbacks.DrawStringLocations(string, *length,
					pointList, *pointCount);
				break;
			}
@@ -1276,7 +1206,7 @@
				const uint32* flags;
				const void* data;
				size_t length;
				if (callbacks.draw_pixels == NULL || !reader.Get(sourceRect)
				if (!reader.Get(sourceRect)
					|| !reader.Get(destinationRect) || !reader.Get(width)
					|| !reader.Get(height) || !reader.Get(bytesPerRow)
					|| !reader.Get(colorSpace) || !reader.Get(flags)
@@ -1284,7 +1214,7 @@
					break;
				}

				callbacks.draw_pixels(userData, *sourceRect, *destinationRect,
				callbacks.DrawPixels(*sourceRect, *destinationRect,
					*width, *height, *bytesPerRow, (color_space)*colorSpace,
					*flags, data, length);
				break;
@@ -1294,20 +1224,15 @@
			{
				const BPoint* where;
				const int32* token;
				if (callbacks.draw_picture == NULL || !reader.Get(where)
					|| !reader.Get(token)) {
				if (!reader.Get(where) || !reader.Get(token))
					break;
				}

				callbacks.draw_picture(userData, *where, *token);
				callbacks.DrawPicture(*where, *token);
				break;
			}

			case B_PIC_SET_CLIPPING_RECTS:
			{
				if (callbacks.set_clipping_rects == NULL)
					break;

				const clipping_rect* frame;
				if (!reader.Get(frame))
					break;
@@ -1318,16 +1243,13 @@
				if (!reader.Get(rects, numRects))
					break;

				callbacks.set_clipping_rects(userData, numRects, rects);
				callbacks.SetClippingRects(numRects, rects);
				break;
			}

			case B_PIC_CLEAR_CLIPPING_RECTS:
			{
				if (callbacks.set_clipping_rects == NULL)
					break;

				callbacks.set_clipping_rects(userData, 0, NULL);
				callbacks.SetClippingRects(0, NULL);
				break;
			}

@@ -1336,29 +1258,23 @@
				const int32* token;
				const BPoint* where;
				const bool* inverse;
				if (callbacks.clip_to_picture == NULL || !reader.Get(token)
				if (!reader.Get(token)
					|| !reader.Get(where) || !reader.Get(inverse))
					break;

				callbacks.clip_to_picture(userData, *token, *where, *inverse);
				callbacks.ClipToPicture(*token, *where, *inverse);
				break;
			}

			case B_PIC_PUSH_STATE:
			{
				if (callbacks.push_state == NULL)
					break;

				callbacks.push_state(userData);
				callbacks.PushState();
				break;
			}

			case B_PIC_POP_STATE:
			{
				if (callbacks.pop_state == NULL)
					break;

				callbacks.pop_state(userData);
				callbacks.PopState();
				break;
			}

@@ -1370,22 +1286,20 @@
				if (!reader.GetRemaining(data, length))
					break;

				if (header->op == B_PIC_ENTER_STATE_CHANGE) {
					if (callbacks.enter_state_change != NULL)
						callbacks.enter_state_change(userData);
				} else if (callbacks.enter_font_state != NULL)
					callbacks.enter_font_state(userData);
				if (header->op == B_PIC_ENTER_STATE_CHANGE)
					callbacks.EnterStateChange();
				else
					callbacks.EnterFontState();

				status_t result = _Play(callbacks, userData, data, length,
				status_t result = _Play(callbacks, data, length,
					header->op);
				if (result != B_OK)
					return result;

				if (header->op == B_PIC_ENTER_STATE_CHANGE) {
					if (callbacks.exit_state_change != NULL)
						callbacks.exit_state_change(userData);
				} else if (callbacks.exit_font_state != NULL)
					callbacks.exit_font_state(userData);
				if (header->op == B_PIC_ENTER_STATE_CHANGE)
					callbacks.ExitStateChange();
				else
					callbacks.ExitFontState();

				break;
			}
@@ -1393,30 +1307,30 @@
			case B_PIC_SET_ORIGIN:
			{
				const BPoint* origin;
				if (callbacks.set_origin == NULL || !reader.Get(origin))
				if (!reader.Get(origin))
					break;

				callbacks.set_origin(userData, *origin);
				callbacks.SetOrigin(*origin);
				break;
			}

			case B_PIC_SET_PEN_LOCATION:
			{
				const BPoint* location;
				if (callbacks.set_pen_location == NULL || !reader.Get(location))
				if (!reader.Get(location))
					break;

				callbacks.set_pen_location(userData, *location);
				callbacks.SetPenLocation(*location);
				break;
			}

			case B_PIC_SET_DRAWING_MODE:
			{
				const uint16* mode;
				if (callbacks.set_drawing_mode == NULL || !reader.Get(mode))
				if (!reader.Get(mode))
					break;

				callbacks.set_drawing_mode(userData, (drawing_mode)*mode);
				callbacks.SetDrawingMode((drawing_mode)*mode);
				break;
			}

@@ -1425,12 +1339,12 @@
				const uint16* capMode;
				const uint16* joinMode;
				const float* miterLimit;
				if (callbacks.set_line_mode == NULL || !reader.Get(capMode)
				if (!reader.Get(capMode)
					|| !reader.Get(joinMode) || !reader.Get(miterLimit)) {
					break;
				}

				callbacks.set_line_mode(userData, (cap_mode)*capMode,
				callbacks.SetLineMode((cap_mode)*capMode,
					(join_mode)*joinMode, *miterLimit);
				break;
			}
@@ -1438,52 +1352,51 @@
			case B_PIC_SET_PEN_SIZE:
			{
				const float* penSize;
				if (callbacks.set_pen_size == NULL || !reader.Get(penSize))
				if (!reader.Get(penSize))
					break;

				callbacks.set_pen_size(userData, *penSize);
				callbacks.SetPenSize(*penSize);
				break;
			}

			case B_PIC_SET_FORE_COLOR:
			{
				const rgb_color* color;
				if (callbacks.set_fore_color == NULL || !reader.Get(color))
				if (!reader.Get(color))
					break;

				callbacks.set_fore_color(userData, *color);
				callbacks.SetForeColor(*color);
				break;
			}

			case B_PIC_SET_BACK_COLOR:
			{
				const rgb_color* color;
				if (callbacks.set_back_color == NULL || !reader.Get(color))
				if (!reader.Get(color))
					break;

				callbacks.set_back_color(userData, *color);
				callbacks.SetBackColor(*color);
				break;
			}

			case B_PIC_SET_STIPLE_PATTERN:
			{
				const pattern* stipplePattern;
				if (callbacks.set_stipple_pattern == NULL
					|| !reader.Get(stipplePattern)) {
				if (!reader.Get(stipplePattern)) {
					break;
				}

				callbacks.set_stipple_pattern(userData, *stipplePattern);
				callbacks.SetStipplePattern(*stipplePattern);
				break;
			}

			case B_PIC_SET_SCALE:
			{
				const float* scale;
				if (callbacks.set_scale == NULL || !reader.Get(scale))
				if (!reader.Get(scale))
					break;

				callbacks.set_scale(userData, *scale);
				callbacks.SetScale(*scale);
				break;
			}

@@ -1491,13 +1404,12 @@
			{
				const int32* length;
				const char* family;
				if (callbacks.set_font_family == NULL
					|| !reader.Get(length)
				if (!reader.Get(length)
					|| !reader.Get(family, *length)) {
					break;
				}

				callbacks.set_font_family(userData, family, *length);
				callbacks.SetFontFamily(family, *length);
				break;
			}

@@ -1505,87 +1417,82 @@
			{
				const int32* length;
				const char* style;
				if (callbacks.set_font_style == NULL
					|| !reader.Get(length)
				if (!reader.Get(length)
					|| !reader.Get(style, *length)) {
					break;
				}

				callbacks.set_font_style(userData, style, *length);
				callbacks.SetFontStyle(style, *length);
				break;
			}

			case B_PIC_SET_FONT_SPACING:
			{
				const uint32* spacing;
				if (callbacks.set_font_spacing == NULL || !reader.Get(spacing))
				if (!reader.Get(spacing))
					break;

				callbacks.set_font_spacing(userData, *spacing);
				callbacks.SetFontSpacing(*spacing);
				break;
			}

			case B_PIC_SET_FONT_SIZE:
			{
				const float* size;
				if (callbacks.set_font_size == NULL || !reader.Get(size))
				if (!reader.Get(size))
					break;

				callbacks.set_font_size(userData, *size);
				callbacks.SetFontSize(*size);
				break;
			}

			case B_PIC_SET_FONT_ROTATE:
			{
				const float* rotation;
				if (callbacks.set_font_rotation == NULL
					|| !reader.Get(rotation)) {
				if (!reader.Get(rotation))
					break;
				}

				callbacks.set_font_rotation(userData, *rotation);
				callbacks.SetFontRotation(*rotation);
				break;
			}

			case B_PIC_SET_FONT_ENCODING:
			{
				const uint32* encoding;
				if (callbacks.set_font_encoding == NULL
					|| !reader.Get(encoding)) {
				if (!reader.Get(encoding))
					break;
				}

				callbacks.set_font_encoding(userData, *encoding);
				callbacks.SetFontEncoding(*encoding);
				break;
			}

			case B_PIC_SET_FONT_FLAGS:
			{
				const uint32* flags;
				if (callbacks.set_font_flags == NULL || !reader.Get(flags))
				if (!reader.Get(flags))
					break;

				callbacks.set_font_flags(userData, *flags);
				callbacks.SetFontFlags(*flags);
				break;
			}

			case B_PIC_SET_FONT_SHEAR:
			{
				const float* shear;
				if (callbacks.set_font_shear == NULL || !reader.Get(shear))
				if (!reader.Get(shear))
					break;

				callbacks.set_font_shear(userData, *shear);
				callbacks.SetFontShear(*shear);
				break;
			}

			case B_PIC_SET_FONT_FACE:
			{
				const uint32* face;
				if (callbacks.set_font_face == NULL || !reader.Get(face))
				if (!reader.Get(face))
					break;

				callbacks.set_font_face(userData, *face);
				callbacks.SetFontFace(*face);
				break;
			}

@@ -1593,13 +1500,12 @@
			{
				const uint16* alphaSourceMode;
				const uint16* alphaFunctionMode;
				if (callbacks.set_blending_mode == NULL
					|| !reader.Get(alphaSourceMode)
				if (!reader.Get(alphaSourceMode)
					|| !reader.Get(alphaFunctionMode)) {
					break;
				}

				callbacks.set_blending_mode(userData,
				callbacks.SetBlendingMode(
					(source_alpha)*alphaSourceMode,
					(alpha_function)*alphaFunctionMode);
				break;
@@ -1608,22 +1514,20 @@
			case B_PIC_SET_FILL_RULE:
			{
				const uint32* fillRule;
				if (callbacks.set_fill_rule == NULL
					|| !reader.Get(fillRule)) {
				if (!reader.Get(fillRule))
					break;
				}

				callbacks.set_fill_rule(userData, *fillRule);
				callbacks.SetFillRule(*fillRule);
				break;
			}

			case B_PIC_SET_TRANSFORM:
			{
				const BAffineTransform* transform;
				if (callbacks.set_transform == NULL || !reader.Get(transform))
				if (!reader.Get(transform))
					break;

				callbacks.set_transform(userData, *transform);
				callbacks.SetTransform(*transform);
				break;
			}

@@ -1631,12 +1535,10 @@
			{
				const double* x;
				const double* y;
				if (callbacks.translate_by == NULL || !reader.Get(x)
					|| !reader.Get(y)) {
				if (!reader.Get(x) || !reader.Get(y))
					break;
				}

				callbacks.translate_by(userData, *x, *y);
				callbacks.TranslateBy(*x, *y);
				break;
			}

@@ -1644,32 +1546,30 @@
			{
				const double* x;
				const double* y;
				if (callbacks.scale_by == NULL || !reader.Get(x)
					|| !reader.Get(y)) {
				if (!reader.Get(x) || !reader.Get(y))
					break;
				}

				callbacks.scale_by(userData, *x, *y);
				callbacks.ScaleBy(*x, *y);
				break;
			}

			case B_PIC_AFFINE_ROTATE:
			{
				const double* angleRadians;
				if (callbacks.rotate_by == NULL || !reader.Get(angleRadians))
				if (!reader.Get(angleRadians))
					break;

				callbacks.rotate_by(userData, *angleRadians);
				callbacks.RotateBy(*angleRadians);
				break;
			}

			case B_PIC_BLEND_LAYER:
			{
				Layer* const* layer;
				if (callbacks.blend_layer == NULL || !reader.Get<Layer*>(layer))
				if (!reader.Get<Layer*>(layer))
					break;

				callbacks.blend_layer(userData, *layer);
				callbacks.BlendLayer(*layer);
				break;
			}

@@ -1678,12 +1578,10 @@
				const bool* inverse;
				const BRect* rect;

				if (callbacks.clip_to_rect == NULL || !reader.Get(inverse)
					|| !reader.Get(rect)) {
				if (!reader.Get(inverse) || !reader.Get(rect))
					break;
				}

				callbacks.clip_to_rect(userData, *rect, *inverse);
				callbacks.ClipToRect(*rect, *inverse);
				break;
			}

@@ -1694,14 +1592,14 @@
				const uint32* pointCount;
				const uint32* opList;
				const BPoint* pointList;
				if (callbacks.clip_to_shape == NULL || !reader.Get(inverse)
				if (!reader.Get(inverse)
					|| !reader.Get(opCount) || !reader.Get(pointCount)
					|| !reader.Get(opList, *opCount)
					|| !reader.Get(pointList, *pointCount)) {
					break;
				}

				callbacks.clip_to_shape(userData, *opCount, opList,
				callbacks.ClipToShape(*opCount, opList,
					*pointCount, pointList, *inverse);
				break;
			}
diff --git a/src/servers/app/PictureBoundingBoxPlayer.cpp b/src/servers/app/PictureBoundingBoxPlayer.cpp
index 77d9c33..b3860ac 100644
--- a/src/servers/app/PictureBoundingBoxPlayer.cpp
+++ b/src/servers/app/PictureBoundingBoxPlayer.cpp
@@ -142,6 +142,71 @@
// #pragma mark - Picture playback hooks


class BoundingBoxCallbacks: public BPrivate::PicturePlayerCallbacks {
public:
	BoundingBoxCallbacks(BoundingBoxState* const state);

	virtual void MovePenBy(const BPoint& where);
	virtual void StrokeLine(const BPoint& start, const BPoint& end);
	virtual void DrawRect(const BRect& rect, bool fill);
	virtual void DrawRoundRect(const BRect& rect, const BPoint& radii, bool fill);
	virtual void DrawBezier(const BPoint controlPoints[4], bool fill);
	virtual void DrawArc(const BPoint& center, const BPoint& radii, float startTheta,
		float arcTheta, bool fill);
	virtual void DrawEllipse(const BRect& rect, bool fill);
	virtual void DrawPolygon(size_t numPoints, const BPoint points[], bool isClosed, bool fill);
	virtual void DrawShape(const BShape& shape, bool fill);
	virtual void DrawString(const char* string, size_t length, float spaceEscapement,
		float nonSpaceEscapement);
	virtual void DrawPixels(const BRect& source, const BRect& destination, uint32 width,
		uint32 height, size_t bytesPerRow, color_space pixelFormat, uint32 flags, const void* data,
		size_t length);
	virtual void DrawPicture(const BPoint& where, int32 token);
	virtual void SetClippingRects(size_t numRects, const clipping_rect rects[]);
	virtual void ClipToPicture(int32 token, const BPoint& where, bool clipToInverse);
	virtual void PushState();
	virtual void PopState();
	virtual void EnterStateChange();
	virtual void ExitStateChange();
	virtual void EnterFontState();
	virtual void ExitFontState();
	virtual void SetOrigin(const BPoint& origin);
	virtual void SetPenLocation(const BPoint& location);
	virtual void SetDrawingMode(drawing_mode mode);
	virtual void SetLineMode(cap_mode capMode, join_mode joinMode, float miterLimit);
	virtual void SetPenSize(float size);
	virtual void SetForeColor(const rgb_color& color);
	virtual void SetBackColor(const rgb_color& color);
	virtual void SetStipplePattern(const pattern& patter);
	virtual void SetScale(float scale);
	virtual void SetFontFamily(const char* familyName, size_t length);
	virtual void SetFontStyle(const char* styleName, size_t length);
	virtual void SetFontSpacing(uint8 spacing);
	virtual void SetFontSize(float size);
	virtual void SetFontRotation(float rotation);
	virtual void SetFontEncoding(uint8 encoding);
	virtual void SetFontFlags(uint32 flags);
	virtual void SetFontShear(float shear);
	virtual void SetFontFace(uint16 face);
	virtual void SetBlendingMode(source_alpha alphaSourceMode, alpha_function alphaFunctionMode);
	virtual void SetTransform(const BAffineTransform& transform);
	virtual void TranslateBy(double x, double y);
	virtual void ScaleBy(double x, double y);
	virtual void RotateBy(double angleRadians);
	virtual void BlendLayer(Layer* layer);

private:
	BoundingBoxState* const fState;
};


BoundingBoxCallbacks::BoundingBoxCallbacks(BoundingBoxState* const state)
	:
	fState(state)
{
}


static void
get_polygon_frame(const BPoint* points, int32 numPoints, BRect* frame)
{
@@ -180,31 +245,27 @@
}


static void
move_pen_by(void* _state, const BPoint& delta)
void
BoundingBoxCallbacks::MovePenBy(const BPoint& delta)
{
	TRACE_BB("%p move pen by %.2f %.2f\n", _state, delta.x, delta.y);
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);

	state->GetDrawState()->SetPenLocation(
		state->GetDrawState()->PenLocation() + delta);
	fState->GetDrawState()->SetPenLocation(
		fState->GetDrawState()->PenLocation() + delta);
}


static void
determine_bounds_stroke_line(void* _state, const BPoint& _start,
void
BoundingBoxCallbacks::StrokeLine(const BPoint& _start,
	const BPoint& _end)
{
	TRACE_BB("%p stroke line %.2f %.2f -> %.2f %.2f\n", _state,
		_start.x, _start.y, _end.x, _end.y);
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);

	BPoint start = _start;
	BPoint end = _end;

	const SimpleTransform transform = state->PenToLocalTransform();
	const SimpleTransform transform = fState->PenToLocalTransform();
	transform.Apply(&start);
	transform.Apply(&end);

@@ -224,34 +285,32 @@
		rect.bottom = start.y;
	}

	expand_rect_for_pen_size(state, rect);
	state->IncludeRect(rect);
	expand_rect_for_pen_size(fState, rect);
	fState->IncludeRect(rect);

	state->GetDrawState()->SetPenLocation(_end);
	fState->GetDrawState()->SetPenLocation(_end);
}


static void
determine_bounds_draw_rect(void* _state, const BRect& _rect, bool fill)
void
BoundingBoxCallbacks::DrawRect(const BRect& _rect, bool fill)
{
	TRACE_BB("%p draw rect fill=%d %.2f %.2f %.2f %.2f\n", _state, fill,
		_rect.left, _rect.top, _rect.right, _rect.bottom);
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);

	BRect rect = _rect;
	state->PenToLocalTransform().Apply(&rect);
	fState->PenToLocalTransform().Apply(&rect);
	if (!fill)
		expand_rect_for_pen_size(state, rect);
	state->IncludeRect(rect);
		expand_rect_for_pen_size(fState, rect);
	fState->IncludeRect(rect);
}


static void
determine_bounds_draw_round_rect(void* _state, const BRect& _rect,
void
BoundingBoxCallbacks::DrawRoundRect(const BRect& _rect,
	const BPoint&, bool fill)
{
	determine_bounds_draw_rect(_state, _rect, fill);
	DrawRect(_rect, fill);
}


@@ -280,9 +339,8 @@
}


static void
determine_bounds_draw_bezier(void* _state,
	const BPoint viewPoints[4], bool fill)
void
BoundingBoxCallbacks::DrawBezier(const BPoint viewPoints[4], bool fill)
{
	TRACE_BB("%p draw bezier fill=%d (%.2f %.2f) (%.2f %.2f) "
		"(%.2f %.2f) (%.2f %.2f)\n",
@@ -292,40 +350,36 @@
		viewPoints[1].x, viewPoints[1].y,
		viewPoints[2].x, viewPoints[2].y,
		viewPoints[3].x, viewPoints[3].y);
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);

	BRect rect;
	determine_bounds_bezier(state, viewPoints, rect);
	determine_bounds_bezier(fState, viewPoints, rect);
	if (!fill)
		expand_rect_for_pen_size(state, rect);
	state->IncludeRect(rect);
		expand_rect_for_pen_size(fState, rect);
	fState->IncludeRect(rect);
}


static void
determine_bounds_draw_ellipse(void* _state, const BRect& _rect, bool fill)
void
BoundingBoxCallbacks::DrawEllipse(const BRect& _rect, bool fill)
{
	TRACE_BB("%p draw ellipse fill=%d (%.2f %.2f) (%.2f %.2f)\n", _state, fill,
		_rect.left, _rect.top, _rect.right, _rect.bottom);
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);

	BRect rect = _rect;
	state->PenToLocalTransform().Apply(&rect);
	fState->PenToLocalTransform().Apply(&rect);
	if (!fill)
		expand_rect_for_pen_size(state, rect);
	state->IncludeRect(rect);
		expand_rect_for_pen_size(fState, rect);
	fState->IncludeRect(rect);
}


static void
determine_bounds_draw_arc(void* _state, const BPoint& center,
void
BoundingBoxCallbacks::DrawArc(const BPoint& center,
	const BPoint& radii, float, float, bool fill)
{
	BRect rect(center.x - radii.x, center.y - radii.y,
		center.x + radii.x - 1, center.y + radii.y - 1);
	determine_bounds_draw_ellipse(_state, rect, fill);
	DrawEllipse(rect, fill);
}


@@ -361,479 +415,358 @@


void
determine_bounds_draw_polygon(void* _state, size_t numPoints,
BoundingBoxCallbacks::DrawPolygon(size_t numPoints,
	const BPoint viewPoints[], bool, bool fill)
{
	TRACE_BB("%p draw polygon fill=%d (%ld points)\n", _state, fill, numPoints);
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);
	TRACE_BB("%p draw polygon fill=%d (%ld points)\n", fState, fill, numPoints);

	BRect rect;
	determine_bounds_polygon(state, numPoints, viewPoints, rect);
	determine_bounds_polygon(fState, numPoints, viewPoints, rect);
	if (!fill)
		expand_rect_for_pen_size(state, rect);
	state->IncludeRect(rect);
		expand_rect_for_pen_size(fState, rect);
	fState->IncludeRect(rect);
}


static void
determine_bounds_draw_shape(void* _state, const BShape& shape, bool fill)
void
BoundingBoxCallbacks::DrawShape(const BShape& shape, bool fill)
{
	BRect rect = shape.Bounds();

	TRACE_BB("%p stroke shape (bounds %.2f %.2f %.2f %.2f)\n", _state,
	TRACE_BB("%p stroke shape (bounds %.2f %.2f %.2f %.2f)\n", fState,
		rect.left, rect.top, rect.right, rect.bottom);
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);

	state->PenToLocalTransform().Apply(&rect);
	fState->PenToLocalTransform().Apply(&rect);
	if (!fill)
		expand_rect_for_pen_size(state, rect);
	state->IncludeRect(rect);
		expand_rect_for_pen_size(fState, rect);
	fState->IncludeRect(rect);
}


static void
determine_bounds_draw_string(void* _state, const char* string, size_t length,
void
BoundingBoxCallbacks::DrawString(const char* string, size_t length,
	float deltaSpace, float deltaNonSpace)
{
	TRACE_BB("%p string '%s'\n", _state, string);
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);
	TRACE_BB("%p string '%s'\n", fState, string);

	ServerFont font = state->GetDrawState()->Font();
	ServerFont font = fState->GetDrawState()->Font();

	escapement_delta delta = { deltaSpace, deltaNonSpace };
	BRect rect;
	font.GetBoundingBoxesForStrings((char**)&string, &length, 1, &rect,
		B_SCREEN_METRIC, &delta);

	BPoint location = state->GetDrawState()->PenLocation();
	BPoint location = fState->GetDrawState()->PenLocation();

	state->PenToLocalTransform().Apply(&location);
	fState->PenToLocalTransform().Apply(&location);
	rect.OffsetBy(location);
	state->IncludeRect(rect);
	fState->IncludeRect(rect);

	state->PenToLocalTransform().Apply(&location);
	state->GetDrawState()->SetPenLocation(location);
	fState->PenToLocalTransform().Apply(&location);
	fState->GetDrawState()->SetPenLocation(location);
}


static void
determine_bounds_draw_pixels(void* _state, const BRect&, const BRect& _dest,
void
BoundingBoxCallbacks::DrawPixels(const BRect&, const BRect& _dest,
	uint32, uint32, size_t, color_space, uint32, const void*, size_t)
{
	TRACE_BB("%p pixels (dest %.2f %.2f %.2f %.2f)\n", _state,
	TRACE_BB("%p pixels (dest %.2f %.2f %.2f %.2f)\n", fState,
		_dest.left, _dest.top, _dest.right, _dest.bottom);
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);

	BRect dest = _dest;
	state->PenToLocalTransform().Apply(&dest);
	state->IncludeRect(dest);
	fState->PenToLocalTransform().Apply(&dest);
	fState->IncludeRect(dest);
}


static void
draw_picture(void* _state, const BPoint& where, int32 token)
void
BoundingBoxCallbacks::DrawPicture(const BPoint& where, int32 token)
{
	TRACE_BB("%p picture (unimplemented)\n", _state);
	TRACE_BB("%p picture (unimplemented)\n", fState);

	// TODO
	(void)_state;
	(void)where;
	(void)token;
}


static void
set_clipping_rects(void* _state, size_t numRects, const clipping_rect rects[])
void
BoundingBoxCallbacks::SetClippingRects(size_t numRects, const clipping_rect rects[])
{
	TRACE_BB("%p cliping rects (%ld rects)\n", _state, numRects);
	TRACE_BB("%p cliping rects (%ld rects)\n", fState, numRects);

	// TODO
	(void)_state;
	(void)rects;
	(void)numRects;
}


static void
clip_to_picture(void* _state, int32 pictureToken, const BPoint& where,
void
BoundingBoxCallbacks::ClipToPicture(int32 pictureToken, const BPoint& where,
	bool clipToInverse)
{
	TRACE_BB("%p clip to picture (unimplemented)\n", _state);
	TRACE_BB("%p clip to picture (unimplemented)\n", fState);

	// TODO
}


static void
push_state(void* _state)
void
BoundingBoxCallbacks::PushState()
{
	TRACE_BB("%p push state\n", _state);
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);
	TRACE_BB("%p push state\n", fState);

	state->PushDrawState();
	fState->PushDrawState();
}


static void
pop_state(void* _state)
void
BoundingBoxCallbacks::PopState()
{
	TRACE_BB("%p pop state\n", _state);
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);
	TRACE_BB("%p pop state\n", fState);

	state->PopDrawState();
	fState->PopDrawState();
}


static void
enter_state_change(void*)
void
BoundingBoxCallbacks::EnterStateChange()
{
}


static void
exit_state_change(void*)
void
BoundingBoxCallbacks::ExitStateChange()
{
}


static void
enter_font_state(void*)
void
BoundingBoxCallbacks::EnterFontState()
{
}


static void
exit_font_state(void*)
void
BoundingBoxCallbacks::ExitFontState()
{
}


static void
set_origin(void* _state, const BPoint& pt)
void
BoundingBoxCallbacks::SetOrigin(const BPoint& pt)
{
	TRACE_BB("%p set origin %.2f %.2f\n", _state, pt.x, pt.y);
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);
	state->GetDrawState()->SetOrigin(pt);
	TRACE_BB("%p set origin %.2f %.2f\n", , pt.x, pt.y);
	fState->GetDrawState()->SetOrigin(pt);
}


static void
set_pen_location(void* _state, const BPoint& pt)
void
BoundingBoxCallbacks::SetPenLocation(const BPoint& pt)
{
	TRACE_BB("%p set pen location %.2f %.2f\n", _state, pt.x, pt.y);
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);
	state->GetDrawState()->SetPenLocation(pt);
	TRACE_BB("%p set pen location %.2f %.2f\n", fState, pt.x, pt.y);
	fState->GetDrawState()->SetPenLocation(pt);
}


static void
set_drawing_mode(void*, drawing_mode)
void
BoundingBoxCallbacks::SetDrawingMode(drawing_mode)
{
}


static void
set_line_mode(void* _state, cap_mode capMode, join_mode joinMode,
void
BoundingBoxCallbacks::SetLineMode(cap_mode capMode, join_mode joinMode,
	float miterLimit)
{
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);

	DrawState* drawState = state->GetDrawState();
	DrawState* drawState = fState->GetDrawState();
	drawState->SetLineCapMode(capMode);
	drawState->SetLineJoinMode(joinMode);
	drawState->SetMiterLimit(miterLimit);
}


static void
set_pen_size(void* _state, float size)
void
BoundingBoxCallbacks::SetPenSize(float size)
{
	TRACE_BB("%p set pen size %.2f\n", _state, size);
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);
	TRACE_BB("%p set pen size %.2f\n", fState, size);

	state->GetDrawState()->SetPenSize(size);
	fState->GetDrawState()->SetPenSize(size);
}


static void
set_fore_color(void* _state, const rgb_color& color)
void
BoundingBoxCallbacks::SetForeColor(const rgb_color& color)
{
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);

	state->GetDrawState()->SetHighColor(color);
	fState->GetDrawState()->SetHighColor(color);
}


static void
set_back_color(void* _state, const rgb_color& color)
void
BoundingBoxCallbacks::SetBackColor(const rgb_color& color)
{
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);

	state->GetDrawState()->SetLowColor(color);
	fState->GetDrawState()->SetLowColor(color);
}


static void
set_stipple_pattern(void* _state, const pattern& _pattern)
void
BoundingBoxCallbacks::SetStipplePattern(const pattern& _pattern)
{
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);

	state->GetDrawState()->SetPattern(Pattern(_pattern));
	fState->GetDrawState()->SetPattern(Pattern(_pattern));
}


static void
set_scale(void* _state, float scale)
void
BoundingBoxCallbacks::SetScale(float scale)
{
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);

	state->GetDrawState()->SetScale(scale);
	fState->GetDrawState()->SetScale(scale);
}


static void
set_font_family(void* _state, const char* _family, size_t length)
void
BoundingBoxCallbacks::SetFontFamily(const char* _family, size_t length)
{
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);

	BString family(_family, length);
	gFontManager->Lock();
	FontStyle* fontStyle = gFontManager->GetStyleByIndex(family, 0);
	ServerFont font;
	font.SetStyle(fontStyle);
	gFontManager->Unlock();
	state->GetDrawState()->SetFont(font, B_FONT_FAMILY_AND_STYLE);
	fState->GetDrawState()->SetFont(font, B_FONT_FAMILY_AND_STYLE);
}


static void
set_font_style(void* _state, const char* _style, size_t length)
void
BoundingBoxCallbacks::SetFontStyle(const char* _style, size_t length)
{
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);

	BString style(_style, length);
	ServerFont font(state->GetDrawState()->Font());
	ServerFont font(fState->GetDrawState()->Font());
	gFontManager->Lock();
	FontStyle* fontStyle = gFontManager->GetStyle(font.Family(), style);
	font.SetStyle(fontStyle);
	gFontManager->Unlock();
	state->GetDrawState()->SetFont(font, B_FONT_FAMILY_AND_STYLE);
	fState->GetDrawState()->SetFont(font, B_FONT_FAMILY_AND_STYLE);
}


static void
set_font_spacing(void* _state, uint8 spacing)
void
BoundingBoxCallbacks::SetFontSpacing(uint8 spacing)
{
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);

	ServerFont font;
	font.SetSpacing(spacing);
	state->GetDrawState()->SetFont(font, B_FONT_SPACING);
	fState->GetDrawState()->SetFont(font, B_FONT_SPACING);
}


static void
set_font_size(void* _state, float size)
void
BoundingBoxCallbacks::SetFontSize(float size)
{
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);

	ServerFont font;
	font.SetSize(size);
	state->GetDrawState()->SetFont(font, B_FONT_SIZE);
	fState->GetDrawState()->SetFont(font, B_FONT_SIZE);
}


static void
set_font_rotate(void* _state, float rotation)
void
BoundingBoxCallbacks::SetFontRotation(float rotation)
{
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);

	ServerFont font;
	font.SetRotation(rotation);
	state->GetDrawState()->SetFont(font, B_FONT_ROTATION);
	fState->GetDrawState()->SetFont(font, B_FONT_ROTATION);
}


static void
set_font_encoding(void* _state, uint8 encoding)
void
BoundingBoxCallbacks::SetFontEncoding(uint8 encoding)
{
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);

	ServerFont font;
	font.SetEncoding(encoding);
	state->GetDrawState()->SetFont(font, B_FONT_ENCODING);
	fState->GetDrawState()->SetFont(font, B_FONT_ENCODING);
}


static void
set_font_flags(void* _state, uint32 flags)
void
BoundingBoxCallbacks::SetFontFlags(uint32 flags)
{
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);

	ServerFont font;
	font.SetFlags(flags);
	state->GetDrawState()->SetFont(font, B_FONT_FLAGS);
	fState->GetDrawState()->SetFont(font, B_FONT_FLAGS);
}


static void
set_font_shear(void* _state, float shear)
void
BoundingBoxCallbacks::SetFontShear(float shear)
{
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);

	ServerFont font;
	font.SetShear(shear);
	state->GetDrawState()->SetFont(font, B_FONT_SHEAR);
	fState->GetDrawState()->SetFont(font, B_FONT_SHEAR);
}


static void
set_font_face(void* _state, uint16 face)
void
BoundingBoxCallbacks::SetFontFace(uint16 face)
{
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);

	ServerFont font;
	font.SetFace(face);
	state->GetDrawState()->SetFont(font, B_FONT_FACE);
	fState->GetDrawState()->SetFont(font, B_FONT_FACE);
}


static void
set_blending_mode(void*, source_alpha, alpha_function)
void
BoundingBoxCallbacks::SetBlendingMode(source_alpha, alpha_function)
{
}


static void
set_transform(void* _state, const BAffineTransform& transform)
void
BoundingBoxCallbacks::SetTransform(const BAffineTransform& transform)
{
	TRACE_BB("%p transform\n", _state);
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);
	state->GetDrawState()->SetTransform(transform);
	TRACE_BB("%p transform\n", fState);
	fState->GetDrawState()->SetTransform(transform);
}


static void
translate_by(void* _state, double x, double y)
{
	TRACE_BB("%p translate\n", _state);
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);
	BAffineTransform transform = state->GetDrawState()->Transform();
void
BoundingBoxCallbacks::TranslateBy(double x, double y)
{
	TRACE_BB("%p translate\n", fState);
	BAffineTransform transform = fState->GetDrawState()->Transform();
	transform.PreTranslateBy(x, y);
	state->GetDrawState()->SetTransform(transform);
	fState->GetDrawState()->SetTransform(transform);
}


static void
scale_by(void* _state, double x, double y)
{
	TRACE_BB("%p scale\n", _state);
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);
	BAffineTransform transform = state->GetDrawState()->Transform();
void
BoundingBoxCallbacks::ScaleBy(double x, double y)
{
	TRACE_BB("%p scale\n", fState);
	BAffineTransform transform = fState->GetDrawState()->Transform();
	transform.PreScaleBy(x, y);
	state->GetDrawState()->SetTransform(transform);
	fState->GetDrawState()->SetTransform(transform);
}


static void
rotate_by(void* _state, double angleRadians)
{
	TRACE_BB("%p rotate\n", _state);
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);
	BAffineTransform transform = state->GetDrawState()->Transform();
void
BoundingBoxCallbacks::RotateBy(double angleRadians)
{
	TRACE_BB("%p rotate\n", fState);
	BAffineTransform transform = fState->GetDrawState()->Transform();
	transform.PreRotateBy(angleRadians);
	state->GetDrawState()->SetTransform(transform);
	fState->GetDrawState()->SetTransform(transform);
}


static void
determine_bounds_nested_layer(void* _state, Layer* layer)
void
BoundingBoxCallbacks::BlendLayer(Layer* layer)
{
	TRACE_BB("%p nested layer\n", _state);
	BoundingBoxState* const state =
		reinterpret_cast<BoundingBoxState*>(_state);
	TRACE_BB("%p nested layer\n", fState);

	BRect boundingBox;
	PictureBoundingBoxPlayer::Play(layer, state->GetDrawState(), &boundingBox);
	PictureBoundingBoxPlayer::Play(layer, fState->GetDrawState(), &boundingBox);
	if (boundingBox.IsValid())
		state->IncludeRect(boundingBox);
}


static const BPrivate::picture_player_callbacks
	kPictureBoundingBoxPlayerCallbacks = {
	move_pen_by,
	determine_bounds_stroke_line,
	determine_bounds_draw_rect,
	determine_bounds_draw_round_rect,
	determine_bounds_draw_bezier,
	determine_bounds_draw_arc,
	determine_bounds_draw_ellipse,
	determine_bounds_draw_polygon,
	determine_bounds_draw_shape,
	determine_bounds_draw_string,
	determine_bounds_draw_pixels,
	draw_picture,
	set_clipping_rects,
	clip_to_picture,
	push_state,
	pop_state,
	enter_state_change,
	exit_state_change,
	enter_font_state,
	exit_font_state,
	set_origin,
	set_pen_location,
	set_drawing_mode,
	set_line_mode,
	set_pen_size,
	set_fore_color,
	set_back_color,
	set_stipple_pattern,
	set_scale,
	set_font_family,
	set_font_style,
	set_font_spacing,
	set_font_size,
	set_font_rotate,
	set_font_encoding,
	set_font_flags,
	set_font_shear,
	set_font_face,
	set_blending_mode,
	set_transform,
	translate_by,
	scale_by,
	rotate_by,
	determine_bounds_nested_layer
};
		fState->IncludeRect(boundingBox);
}


// #pragma mark - PictureBoundingBoxPlayer
@@ -848,10 +781,11 @@
	BMallocIO* mallocIO = dynamic_cast<BMallocIO*>(picture->fData.Get());
	if (mallocIO == NULL)
		return;

	BoundingBoxCallbacks callbacks(&state);

	BPrivate::PicturePlayer player(mallocIO->Buffer(),
		mallocIO->BufferLength(), ServerPicture::PictureList::Private(
			picture->fPictures.Get()).AsBList());
	player.Play(kPictureBoundingBoxPlayerCallbacks,
		sizeof(kPictureBoundingBoxPlayerCallbacks), &state);
	player.Play(callbacks);
}
diff --git a/src/servers/app/ServerPicture.cpp b/src/servers/app/ServerPicture.cpp
index 622fadd..5dafb81 100644
--- a/src/servers/app/ServerPicture.cpp
+++ b/src/servers/app/ServerPicture.cpp
@@ -237,6 +237,89 @@
// #pragma mark - drawing functions


class CanvasCallbacks: public BPrivate::PicturePlayerCallbacks {
public:
	CanvasCallbacks(Canvas* const canvas);

	virtual void MovePenBy(const BPoint& where);
	virtual void StrokeLine(const BPoint& start, const BPoint& end);
	virtual void DrawRect(const BRect& rect, bool fill);
	virtual void DrawRoundRect(const BRect& rect, const BPoint& radii, bool fill);
	virtual void DrawBezier(const BPoint controlPoints[4], bool fill);
	virtual void DrawArc(const BPoint& center, const BPoint& radii, float startTheta,
		float arcTheta, bool fill);
	virtual void DrawEllipse(const BRect& rect, bool fill);
	virtual void DrawPolygon(size_t numPoints, const BPoint points[], bool isClosed, bool fill);
	virtual void DrawShape(const BShape& shape, bool fill);
	virtual void DrawString(const char* string, size_t length, float spaceEscapement,
		float nonSpaceEscapement);
	virtual void DrawPixels(const BRect& source, const BRect& destination, uint32 width,
		uint32 height, size_t bytesPerRow, color_space pixelFormat, uint32 flags, const void* data,
		size_t length);
	virtual void DrawPicture(const BPoint& where, int32 token);
	virtual void SetClippingRects(size_t numRects, const clipping_rect rects[]);
	virtual void ClipToPicture(int32 token, const BPoint& where, bool clipToInverse);
	virtual void PushState();
	virtual void PopState();
	virtual void EnterStateChange();
	virtual void ExitStateChange();
	virtual void EnterFontState();
	virtual void ExitFontState();
	virtual void SetOrigin(const BPoint& origin);
	virtual void SetPenLocation(const BPoint& location);
	virtual void SetDrawingMode(drawing_mode mode);
	virtual void SetLineMode(cap_mode capMode, join_mode joinMode, float miterLimit);
	virtual void SetPenSize(float size);
	virtual void SetForeColor(const rgb_color& color);
	virtual void SetBackColor(const rgb_color& color);
	virtual void SetStipplePattern(const pattern& patter);
	virtual void SetScale(float scale);
	virtual void SetFontFamily(const char* familyName, size_t length);
	virtual void SetFontStyle(const char* styleName, size_t length);
	virtual void SetFontSpacing(uint8 spacing);
	virtual void SetFontSize(float size);
	virtual void SetFontRotation(float rotation);
	virtual void SetFontEncoding(uint8 encoding);
	virtual void SetFontFlags(uint32 flags);
	virtual void SetFontShear(float shear);
	virtual void SetFontFace(uint16 face);
	virtual void SetBlendingMode(source_alpha alphaSourceMode, alpha_function alphaFunctionMode);
	virtual void SetTransform(const BAffineTransform& transform);
	virtual void TranslateBy(double x, double y);
	virtual void ScaleBy(double x, double y);
	virtual void RotateBy(double angleRadians);
	virtual void BlendLayer(Layer* layer);
	virtual void ClipToRect(const BRect& rect, bool inverse);
	virtual void ClipToShape(int32 opCount, const uint32 opList[], int32 ptCount,
		const BPoint ptList[], bool inverse);
	virtual void DrawStringLocations(const char* string, size_t length, const BPoint locations[],
		size_t locationCount);
	virtual void DrawRectGradient(const BRect& rect, BGradient& gradient, bool fill);
	virtual void DrawRoundRectGradient(const BRect& rect, const BPoint& radii, BGradient& gradient,
		bool fill);
	virtual void DrawBezierGradient(const BPoint controlPoints[4], BGradient& gradient, bool fill);
	virtual void DrawArcGradient(const BPoint& center, const BPoint& radii, float startTheta,
		float arcTheta, BGradient& gradient, bool fill);
	virtual void DrawEllipseGradient(const BRect& rect, BGradient& gradient, bool fill);
	virtual void DrawPolygonGradient(size_t numPoints, const BPoint points[], bool isClosed,
		BGradient& gradient, bool fill);
	virtual void DrawShapeGradient(const BShape& shape, BGradient& gradient, bool fill);
	virtual void SetFillRule(int32 fillRule);
	virtual void StrokeLineGradient(const BPoint& start, const BPoint& end,
		const BGradient& gradient);

private:
	Canvas* const fCanvas;
};


CanvasCallbacks::CanvasCallbacks(Canvas* const canvas)
	:
	fCanvas(canvas)
{
}


static void
get_polygon_frame(const BPoint* points, uint32 numPoints, BRect* _frame)
{
@@ -266,105 +349,93 @@
}


static void
move_pen_by(void* _canvas, const BPoint& delta)
void
CanvasCallbacks::MovePenBy(const BPoint& delta)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	canvas->CurrentState()->SetPenLocation(
		canvas->CurrentState()->PenLocation() + delta);
	fCanvas->CurrentState()->SetPenLocation(
		fCanvas->CurrentState()->PenLocation() + delta);
}


static void
stroke_line(void* _canvas, const BPoint& _start, const BPoint& _end)
void
CanvasCallbacks::StrokeLine(const BPoint& _start, const BPoint& _end)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	BPoint start = _start;
	BPoint end = _end;

	const SimpleTransform transform = canvas->PenToScreenTransform();
	const SimpleTransform transform = fCanvas->PenToScreenTransform();
	transform.Apply(&start);
	transform.Apply(&end);
	canvas->GetDrawingEngine()->StrokeLine(start, end);
	fCanvas->GetDrawingEngine()->StrokeLine(start, end);

	canvas->CurrentState()->SetPenLocation(_end);
	fCanvas->CurrentState()->SetPenLocation(_end);
	// the DrawingEngine/Painter does not need to be updated, since this
	// effects only the view->screen coord conversion, which is handled
	// by the view only
}


static void
draw_rect(void* _canvas, const BRect& _rect, bool fill)
void
CanvasCallbacks::DrawRect(const BRect& _rect, bool fill)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	BRect rect = _rect;

	canvas->PenToScreenTransform().Apply(&rect);
	fCanvas->PenToScreenTransform().Apply(&rect);
	if (fill)
		canvas->GetDrawingEngine()->FillRect(rect);
		fCanvas->GetDrawingEngine()->FillRect(rect);
	else
		canvas->GetDrawingEngine()->StrokeRect(rect);
		fCanvas->GetDrawingEngine()->StrokeRect(rect);
}


static void
draw_round_rect(void* _canvas, const BRect& _rect, const BPoint& radii,
void
CanvasCallbacks::DrawRoundRect(const BRect& _rect, const BPoint& radii,
	bool fill)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	BRect rect = _rect;

	canvas->PenToScreenTransform().Apply(&rect);
	float scale = canvas->CurrentState()->CombinedScale();
	canvas->GetDrawingEngine()->DrawRoundRect(rect, radii.x * scale,
	fCanvas->PenToScreenTransform().Apply(&rect);
	float scale = fCanvas->CurrentState()->CombinedScale();
	fCanvas->GetDrawingEngine()->DrawRoundRect(rect, radii.x * scale,
		radii.y * scale, fill);
}


static void
draw_bezier(void* _canvas, const BPoint viewPoints[4], bool fill)
void
CanvasCallbacks::DrawBezier(const BPoint viewPoints[4], bool fill)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);

	const size_t kNumPoints = 4;

	BPoint points[kNumPoints];
	canvas->PenToScreenTransform().Apply(points, viewPoints, kNumPoints);
	canvas->GetDrawingEngine()->DrawBezier(points, fill);
	fCanvas->PenToScreenTransform().Apply(points, viewPoints, kNumPoints);
	fCanvas->GetDrawingEngine()->DrawBezier(points, fill);
}


static void
draw_arc(void* _canvas, const BPoint& center, const BPoint& radii,
void
CanvasCallbacks::DrawArc(const BPoint& center, const BPoint& radii,
	float startTheta, float arcTheta, bool fill)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);

	BRect rect(center.x - radii.x, center.y - radii.y,
		center.x + radii.x - 1, center.y + radii.y - 1);
	canvas->PenToScreenTransform().Apply(&rect);
	canvas->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, fill);
	fCanvas->PenToScreenTransform().Apply(&rect);
	fCanvas->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, fill);
}


static void
draw_ellipse(void* _canvas, const BRect& _rect, bool fill)
void
CanvasCallbacks::DrawEllipse(const BRect& _rect, bool fill)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);

	BRect rect = _rect;
	canvas->PenToScreenTransform().Apply(&rect);
	canvas->GetDrawingEngine()->DrawEllipse(rect, fill);
	fCanvas->PenToScreenTransform().Apply(&rect);
	fCanvas->GetDrawingEngine()->DrawEllipse(rect, fill);
}


static void
draw_polygon(void* _canvas, size_t numPoints, const BPoint viewPoints[],
void
CanvasCallbacks::DrawPolygon(size_t numPoints, const BPoint viewPoints[],
	bool isClosed, bool fill)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);

	if (numPoints == 0)
		return;

@@ -372,111 +443,101 @@
	if (!points.IsValid())
		return;

	canvas->PenToScreenTransform().Apply(points, viewPoints, numPoints);
	fCanvas->PenToScreenTransform().Apply(points, viewPoints, numPoints);

	BRect polyFrame;
	get_polygon_frame(points, numPoints, &polyFrame);

	canvas->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame,
	fCanvas->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame,
		fill, isClosed && numPoints > 2);
}


static void
draw_shape(void* _canvas, const BShape& shape, bool fill)
void
CanvasCallbacks::DrawShape(const BShape& shape, bool fill)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	ShapePainter drawShape(canvas, NULL);
	ShapePainter drawShape(fCanvas, NULL);

	drawShape.Iterate(&shape);
	drawShape.Draw(shape.Bounds(), fill);
}


static void
draw_rect_gradient(void* _canvas, const BRect& _rect, BGradient& gradient, bool fill)
void
CanvasCallbacks::DrawRectGradient(const BRect& _rect, BGradient& gradient, bool fill)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	BRect rect = _rect;

	const SimpleTransform transform =
		canvas->PenToScreenTransform();
		fCanvas->PenToScreenTransform();
	transform.Apply(&rect);
	transform.Apply(&gradient);

	canvas->GetDrawingEngine()->FillRect(rect, gradient);
	fCanvas->GetDrawingEngine()->FillRect(rect, gradient);
}


static void
draw_round_rect_gradient(void* _canvas, const BRect& _rect, const BPoint& radii, BGradient& gradient,
void
CanvasCallbacks::DrawRoundRectGradient(const BRect& _rect, const BPoint& radii, BGradient& gradient,
	bool fill)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	BRect rect = _rect;

	const SimpleTransform transform =
		canvas->PenToScreenTransform();
		fCanvas->PenToScreenTransform();
	transform.Apply(&rect);
	transform.Apply(&gradient);
	float scale = canvas->CurrentState()->CombinedScale();
	canvas->GetDrawingEngine()->DrawRoundRect(rect, radii.x * scale,
	float scale = fCanvas->CurrentState()->CombinedScale();
	fCanvas->GetDrawingEngine()->DrawRoundRect(rect, radii.x * scale,
		radii.y * scale, fill, gradient);
}


static void
draw_bezier_gradient(void* _canvas, const BPoint viewPoints[4], BGradient& gradient, bool fill)
void
CanvasCallbacks::DrawBezierGradient(const BPoint viewPoints[4], BGradient& gradient, bool fill)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);

	const size_t kNumPoints = 4;

	BPoint points[kNumPoints];
	const SimpleTransform transform =
		canvas->PenToScreenTransform();
		fCanvas->PenToScreenTransform();
	transform.Apply(points, viewPoints, kNumPoints);
	transform.Apply(&gradient);
	canvas->GetDrawingEngine()->DrawBezier(points, fill, gradient);
	fCanvas->GetDrawingEngine()->DrawBezier(points, fill, gradient);
}


static void
draw_arc_gradient(void* _canvas, const BPoint& center, const BPoint& radii,
void
CanvasCallbacks::DrawArcGradient(const BPoint& center, const BPoint& radii,
	float startTheta, float arcTheta, BGradient& gradient, bool fill)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);

	BRect rect(center.x - radii.x, center.y - radii.y,
		center.x + radii.x - 1, center.y + radii.y - 1);
	const SimpleTransform transform =
		canvas->PenToScreenTransform();
		fCanvas->PenToScreenTransform();
	transform.Apply(&rect);
	transform.Apply(&gradient);
	canvas->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, fill, gradient);
	fCanvas->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, fill, gradient);
}


static void
draw_ellipse_gradient(void* _canvas, const BRect& _rect, BGradient& gradient, bool fill)
void
CanvasCallbacks::DrawEllipseGradient(const BRect& _rect, BGradient& gradient, bool fill)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	BRect rect = _rect;

	const SimpleTransform transform =
		canvas->PenToScreenTransform();
		fCanvas->PenToScreenTransform();
	transform.Apply(&rect);
	transform.Apply(&gradient);
	canvas->GetDrawingEngine()->DrawEllipse(rect, fill, gradient);
	fCanvas->GetDrawingEngine()->DrawEllipse(rect, fill, gradient);
}


static void
draw_polygon_gradient(void* _canvas, size_t numPoints, const BPoint viewPoints[],
void
CanvasCallbacks::DrawPolygonGradient(size_t numPoints, const BPoint viewPoints[],
	bool isClosed, BGradient& gradient, bool fill)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);

	if (numPoints == 0)
		return;

@@ -485,106 +546,99 @@
		return;

	const SimpleTransform transform =
		canvas->PenToScreenTransform();
		fCanvas->PenToScreenTransform();
	transform.Apply(points, viewPoints, numPoints);
	transform.Apply(&gradient);

	BRect polyFrame;
	get_polygon_frame(points, numPoints, &polyFrame);

	canvas->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame,
	fCanvas->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame,
		isClosed && numPoints > 2, fill, gradient);
}


static void
draw_shape_gradient(void* _canvas, const BShape& shape, BGradient& gradient, bool fill)
void
CanvasCallbacks::DrawShapeGradient(const BShape& shape, BGradient& gradient, bool fill)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	ShapePainter drawShape(canvas, &gradient);
	ShapePainter drawShape(fCanvas, &gradient);

	drawShape.Iterate(&shape);
	drawShape.Draw(shape.Bounds(), fill);
}


static void
stroke_line_gradient(void* _canvas, const BPoint& _start, const BPoint& _end,
void
CanvasCallbacks::StrokeLineGradient(const BPoint& _start, const BPoint& _end,
	const BGradient& gradient)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	BPoint start = _start;
	BPoint end = _end;

	const SimpleTransform transform = canvas->PenToScreenTransform();
	const SimpleTransform transform = fCanvas->PenToScreenTransform();
	transform.Apply(&start);
	transform.Apply(&end);
	canvas->GetDrawingEngine()->StrokeLine(start, end, gradient);
	fCanvas->GetDrawingEngine()->StrokeLine(start, end, gradient);

	canvas->CurrentState()->SetPenLocation(_end);
	fCanvas->CurrentState()->SetPenLocation(_end);
	// the DrawingEngine/Painter does not need to be updated, since this
	// effects only the view->screen coord conversion, which is handled
	// by the view only
}


static void
draw_string(void* _canvas, const char* string, size_t length, float deltaSpace,
void
CanvasCallbacks::DrawString(const char* string, size_t length, float deltaSpace,
	float deltaNonSpace)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);

	// NOTE: the picture data was recorded with a "set pen location"
	// command inserted before the "draw string" command, so we can
	// use PenLocation()
	BPoint location = canvas->CurrentState()->PenLocation();
	BPoint location = fCanvas->CurrentState()->PenLocation();

	escapement_delta delta = { deltaSpace, deltaNonSpace };
	canvas->PenToScreenTransform().Apply(&location);
	location = canvas->GetDrawingEngine()->DrawString(string, length,
	fCanvas->PenToScreenTransform().Apply(&location);
	location = fCanvas->GetDrawingEngine()->DrawString(string, length,
		location, &delta);

	canvas->PenToScreenTransform().Apply(&location);
	canvas->CurrentState()->SetPenLocation(location);
	fCanvas->PenToScreenTransform().Apply(&location);
	fCanvas->CurrentState()->SetPenLocation(location);
	// the DrawingEngine/Painter does not need to be updated, since this
	// effects only the view->screen coord conversion, which is handled
	// by the view only
}


static void
draw_string_locations(void* _canvas, const char* string, size_t length,
void
CanvasCallbacks::DrawStringLocations(const char* string, size_t length,
	const BPoint* _locations, size_t locationsCount)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	BStackOrHeapArray<BPoint, 200> locations(locationsCount);
	if (!locations.IsValid())
		return;

	const SimpleTransform transform = canvas->PenToScreenTransform();
	const SimpleTransform transform = fCanvas->PenToScreenTransform();
	for (size_t i = 0; i < locationsCount; i++) {
		locations[i] = _locations[i];
		transform.Apply(&locations[i]);
	}

	BPoint location = canvas->GetDrawingEngine()->DrawString(string, length,
	BPoint location = fCanvas->GetDrawingEngine()->DrawString(string, length,
		locations);

	canvas->PenToScreenTransform().Apply(&location);
	canvas->CurrentState()->SetPenLocation(location);
	fCanvas->PenToScreenTransform().Apply(&location);
	fCanvas->CurrentState()->SetPenLocation(location);
	// the DrawingEngine/Painter does not need to be updated, since this
	// effects only the view->screen coord conversion, which is handled
	// by the view only
}


static void
draw_pixels(void* _canvas, const BRect& src, const BRect& _dest, uint32 width,
void
CanvasCallbacks::DrawPixels(const BRect& src, const BRect& _dest, uint32 width,
	uint32 height, size_t bytesPerRow, color_space pixelFormat, uint32 options,
	const void* data, size_t length)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);

	UtilityBitmap bitmap(BRect(0, 0, width - 1, height - 1),
		(color_space)pixelFormat, 0, bytesPerRow);

@@ -594,214 +648,194 @@
	memcpy(bitmap.Bits(), data, std::min(height * bytesPerRow, length));

	BRect dest = _dest;
	canvas->PenToScreenTransform().Apply(&dest);
	canvas->GetDrawingEngine()->DrawBitmap(&bitmap, src, dest, options);
	fCanvas->PenToScreenTransform().Apply(&dest);
	fCanvas->GetDrawingEngine()->DrawBitmap(&bitmap, src, dest, options);
}


static void
draw_picture(void* _canvas, const BPoint& where, int32 token)
void
CanvasCallbacks::DrawPicture(const BPoint& where, int32 token)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);

	BReference<ServerPicture> picture(canvas->GetPicture(token), true);
	BReference<ServerPicture> picture(fCanvas->GetPicture(token), true);
	if (picture != NULL) {
		canvas->PushState();
		canvas->SetDrawingOrigin(where);
		fCanvas->PushState();
		fCanvas->SetDrawingOrigin(where);

		canvas->PushState();
		picture->Play(canvas);
		canvas->PopState();
		fCanvas->PushState();
		picture->Play(fCanvas);
		fCanvas->PopState();

		canvas->PopState();
		fCanvas->PopState();
	}
}


static void
set_clipping_rects(void* _canvas, size_t numRects, const clipping_rect rects[])
void
CanvasCallbacks::SetClippingRects(size_t numRects, const clipping_rect rects[])
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);

	if (numRects == 0)
		canvas->SetUserClipping(NULL);
		fCanvas->SetUserClipping(NULL);
	else {
		// TODO: This might be too slow, we should copy the rects
		// directly to BRegion's internal data
		BRegion region;
		for (uint32 c = 0; c < numRects; c++)
			region.Include(rects[c]);
		canvas->SetUserClipping(&region);
		fCanvas->SetUserClipping(&region);
	}
	canvas->UpdateCurrentDrawingRegion();
	fCanvas->UpdateCurrentDrawingRegion();
}


static void
clip_to_picture(void* _canvas, int32 pictureToken, const BPoint& where,
void
CanvasCallbacks::ClipToPicture(int32 pictureToken, const BPoint& where,
	bool clipToInverse)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);

	BReference<ServerPicture> picture(canvas->GetPicture(pictureToken), true);
	BReference<ServerPicture> picture(fCanvas->GetPicture(pictureToken), true);
	if (picture == NULL)
		return;
	BReference<AlphaMask> mask(new(std::nothrow) PictureAlphaMask(canvas->GetAlphaMask(),
		picture, *canvas->CurrentState(), where, clipToInverse), true);
	canvas->SetAlphaMask(mask);
	canvas->CurrentState()->GetAlphaMask()->SetCanvasGeometry(BPoint(0, 0),
		canvas->Bounds());
	canvas->ResyncDrawState();
	BReference<AlphaMask> mask(new(std::nothrow) PictureAlphaMask(fCanvas->GetAlphaMask(),
		picture, *fCanvas->CurrentState(), where, clipToInverse), true);
	fCanvas->SetAlphaMask(mask);
	fCanvas->CurrentState()->GetAlphaMask()->SetCanvasGeometry(BPoint(0, 0),
		fCanvas->Bounds());
	fCanvas->ResyncDrawState();
}


static void
push_state(void* _canvas)
void
CanvasCallbacks::PushState()
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	canvas->PushState();
	fCanvas->PushState();
}


static void
pop_state(void* _canvas)
void
CanvasCallbacks::PopState()
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	canvas->PopState();
	fCanvas->PopState();

	BPoint p(0, 0);
	canvas->PenToScreenTransform().Apply(&p);
	canvas->GetDrawingEngine()->SetDrawState(canvas->CurrentState(),
	fCanvas->PenToScreenTransform().Apply(&p);
	fCanvas->GetDrawingEngine()->SetDrawState(fCanvas->CurrentState(),
		(int32)p.x, (int32)p.y);
}


// TODO: Be smart and actually take advantage of these methods:
// only apply state changes when they are called
static void
enter_state_change(void* _canvas)
void
CanvasCallbacks::EnterStateChange()
{
}


static void
exit_state_change(void* _canvas)
void
CanvasCallbacks::ExitStateChange()
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	canvas->ResyncDrawState();
	fCanvas->ResyncDrawState();
}


static void
enter_font_state(void* _canvas)
void
CanvasCallbacks::EnterFontState()
{
}


static void
exit_font_state(void* _canvas)
void
CanvasCallbacks::ExitFontState()
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	canvas->GetDrawingEngine()->SetFont(canvas->CurrentState()->Font());
	fCanvas->GetDrawingEngine()->SetFont(fCanvas->CurrentState()->Font());
}


static void
set_origin(void* _canvas, const BPoint& pt)
void
CanvasCallbacks::SetOrigin(const BPoint& pt)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	canvas->CurrentState()->SetOrigin(pt);
	fCanvas->CurrentState()->SetOrigin(pt);
}


static void
set_pen_location(void* _canvas, const BPoint& pt)
void
CanvasCallbacks::SetPenLocation(const BPoint& pt)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	canvas->CurrentState()->SetPenLocation(pt);
	fCanvas->CurrentState()->SetPenLocation(pt);
	// the DrawingEngine/Painter does not need to be updated, since this
	// effects only the view->screen coord conversion, which is handled
	// by the view only
}


static void
set_drawing_mode(void* _canvas, drawing_mode mode)
void
CanvasCallbacks::SetDrawingMode(drawing_mode mode)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	if (canvas->CurrentState()->SetDrawingMode(mode))
		canvas->GetDrawingEngine()->SetDrawingMode(mode);
	if (fCanvas->CurrentState()->SetDrawingMode(mode))
		fCanvas->GetDrawingEngine()->SetDrawingMode(mode);
}


static void
set_line_mode(void* _canvas, cap_mode capMode, join_mode joinMode,
void
CanvasCallbacks::SetLineMode(cap_mode capMode, join_mode joinMode,
	float miterLimit)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	DrawState* state = canvas->CurrentState();
	DrawState* state = fCanvas->CurrentState();
	state->SetLineCapMode(capMode);
	state->SetLineJoinMode(joinMode);
	state->SetMiterLimit(miterLimit);
	canvas->GetDrawingEngine()->SetStrokeMode(capMode, joinMode, miterLimit);
	fCanvas->GetDrawingEngine()->SetStrokeMode(capMode, joinMode, miterLimit);
}


static void
set_pen_size(void* _canvas, float size)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	canvas->CurrentState()->SetPenSize(size);
	canvas->GetDrawingEngine()->SetPenSize(
		canvas->CurrentState()->PenSize());
void
CanvasCallbacks::SetPenSize(float size)
{
	fCanvas->CurrentState()->SetPenSize(size);
	fCanvas->GetDrawingEngine()->SetPenSize(
		fCanvas->CurrentState()->PenSize());
		// DrawState::PenSize() returns the scaled pen size, so we
		// need to use that value to set the drawing engine pen size.
}


static void
set_fore_color(void* _canvas, const rgb_color& color)
void
CanvasCallbacks::SetForeColor(const rgb_color& color)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	canvas->CurrentState()->SetHighColor(color);
	canvas->GetDrawingEngine()->SetHighColor(color);
	fCanvas->CurrentState()->SetHighColor(color);
	fCanvas->GetDrawingEngine()->SetHighColor(color);
}


static void
set_back_color(void* _canvas, const rgb_color& color)
void
CanvasCallbacks::SetBackColor(const rgb_color& color)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	canvas->CurrentState()->SetLowColor(color);
	canvas->GetDrawingEngine()->SetLowColor(color);
	fCanvas->CurrentState()->SetLowColor(color);
	fCanvas->GetDrawingEngine()->SetLowColor(color);
}


static void
set_stipple_pattern(void* _canvas, const pattern& pattern)
void
CanvasCallbacks::SetStipplePattern(const pattern& pattern)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	canvas->CurrentState()->SetPattern(Pattern(pattern));
	canvas->GetDrawingEngine()->SetPattern(pattern);
	fCanvas->CurrentState()->SetPattern(Pattern(pattern));
	fCanvas->GetDrawingEngine()->SetPattern(pattern);
}


static void
set_scale(void* _canvas, float scale)
void
CanvasCallbacks::SetScale(float scale)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	canvas->CurrentState()->SetScale(scale);
	canvas->ResyncDrawState();
	fCanvas->CurrentState()->SetScale(scale);
	fCanvas->ResyncDrawState();

	// Update the drawing engine draw state, since some stuff
	// (for example the pen size) needs to be recalculated.
}


static void
set_font_family(void* _canvas, const char* _family, size_t length)
void
CanvasCallbacks::SetFontFamily(const char* _family, size_t length)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	BString family(_family, length);

	gFontManager->Lock();
@@ -809,204 +843,183 @@
	ServerFont font;
	font.SetStyle(fontStyle);
	gFontManager->Unlock();
	canvas->CurrentState()->SetFont(font, B_FONT_FAMILY_AND_STYLE);
	fCanvas->CurrentState()->SetFont(font, B_FONT_FAMILY_AND_STYLE);
}


static void
set_font_style(void* _canvas, const char* _style, size_t length)
void
CanvasCallbacks::SetFontStyle(const char* _style, size_t length)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	BString style(_style, length);

	ServerFont font(canvas->CurrentState()->Font());
	ServerFont font(fCanvas->CurrentState()->Font());

	gFontManager->Lock();
	FontStyle* fontStyle = gFontManager->GetStyle(font.Family(), style);

	font.SetStyle(fontStyle);
	gFontManager->Unlock();
	canvas->CurrentState()->SetFont(font, B_FONT_FAMILY_AND_STYLE);
	fCanvas->CurrentState()->SetFont(font, B_FONT_FAMILY_AND_STYLE);
}


static void
set_font_spacing(void* _canvas, uint8 spacing)
void
CanvasCallbacks::SetFontSpacing(uint8 spacing)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	ServerFont font;
	font.SetSpacing(spacing);
	canvas->CurrentState()->SetFont(font, B_FONT_SPACING);
	fCanvas->CurrentState()->SetFont(font, B_FONT_SPACING);
}


static void
set_font_size(void* _canvas, float size)
void
CanvasCallbacks::SetFontSize(float size)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	ServerFont font;
	font.SetSize(size);
	canvas->CurrentState()->SetFont(font, B_FONT_SIZE);
	fCanvas->CurrentState()->SetFont(font, B_FONT_SIZE);
}


static void
set_font_rotation(void* _canvas, float rotation)
void
CanvasCallbacks::SetFontRotation(float rotation)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	ServerFont font;
	font.SetRotation(rotation);
	canvas->CurrentState()->SetFont(font, B_FONT_ROTATION);
	fCanvas->CurrentState()->SetFont(font, B_FONT_ROTATION);
}


static void
set_font_encoding(void* _canvas, uint8 encoding)
void
CanvasCallbacks::SetFontEncoding(uint8 encoding)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	ServerFont font;
	font.SetEncoding(encoding);
	canvas->CurrentState()->SetFont(font, B_FONT_ENCODING);
	fCanvas->CurrentState()->SetFont(font, B_FONT_ENCODING);
}


static void
set_font_flags(void* _canvas, uint32 flags)
void
CanvasCallbacks::SetFontFlags(uint32 flags)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	ServerFont font;
	font.SetFlags(flags);
	canvas->CurrentState()->SetFont(font, B_FONT_FLAGS);
	fCanvas->CurrentState()->SetFont(font, B_FONT_FLAGS);
}


static void
set_font_shear(void* _canvas, float shear)
void
CanvasCallbacks::SetFontShear(float shear)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	ServerFont font;
	font.SetShear(shear);
	canvas->CurrentState()->SetFont(font, B_FONT_SHEAR);
	fCanvas->CurrentState()->SetFont(font, B_FONT_SHEAR);
}


static void
set_font_face(void* _canvas, uint16 face)
void
CanvasCallbacks::SetFontFace(uint16 face)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	ServerFont font;
	font.SetFace(face);
	canvas->CurrentState()->SetFont(font, B_FONT_FACE);
	fCanvas->CurrentState()->SetFont(font, B_FONT_FACE);
}


static void
set_blending_mode(void* _canvas, source_alpha alphaSrcMode,
void
CanvasCallbacks::SetBlendingMode(source_alpha alphaSrcMode,
	alpha_function alphaFncMode)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	canvas->CurrentState()->SetBlendingMode(alphaSrcMode, alphaFncMode);
	fCanvas->CurrentState()->SetBlendingMode(alphaSrcMode, alphaFncMode);
}


static void
set_fill_rule(void* _canvas, int32 fillRule)
void
CanvasCallbacks::SetFillRule(int32 fillRule)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	canvas->CurrentState()->SetFillRule(fillRule);
	canvas->GetDrawingEngine()->SetFillRule(fillRule);
	fCanvas->CurrentState()->SetFillRule(fillRule);
	fCanvas->GetDrawingEngine()->SetFillRule(fillRule);
}


static void
set_transform(void* _canvas, const BAffineTransform& transform)
void
CanvasCallbacks::SetTransform(const BAffineTransform& transform)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);

	BPoint leftTop(0, 0);
	canvas->PenToScreenTransform().Apply(&leftTop);
	fCanvas->PenToScreenTransform().Apply(&leftTop);

	canvas->CurrentState()->SetTransform(transform);
	canvas->GetDrawingEngine()->SetTransform(
		canvas->CurrentState()->CombinedTransform(), leftTop.x, leftTop.y);
	fCanvas->CurrentState()->SetTransform(transform);
	fCanvas->GetDrawingEngine()->SetTransform(
		fCanvas->CurrentState()->CombinedTransform(), leftTop.x, leftTop.y);
}


static void
translate_by(void* _canvas, double x, double y)
void
CanvasCallbacks::TranslateBy(double x, double y)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);

	BPoint leftTop(0, 0);
	canvas->PenToScreenTransform().Apply(&leftTop);
	fCanvas->PenToScreenTransform().Apply(&leftTop);

	BAffineTransform transform = canvas->CurrentState()->Transform();
	BAffineTransform transform = fCanvas->CurrentState()->Transform();
	transform.PreTranslateBy(x, y);
	canvas->CurrentState()->SetTransform(transform);
	canvas->GetDrawingEngine()->SetTransform(
		canvas->CurrentState()->CombinedTransform(), leftTop.x, leftTop.y);
	fCanvas->CurrentState()->SetTransform(transform);
	fCanvas->GetDrawingEngine()->SetTransform(
		fCanvas->CurrentState()->CombinedTransform(), leftTop.x, leftTop.y);
}


static void
scale_by(void* _canvas, double x, double y)
void
CanvasCallbacks::ScaleBy(double x, double y)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);

	BPoint leftTop(0, 0);
	canvas->PenToScreenTransform().Apply(&leftTop);
	fCanvas->PenToScreenTransform().Apply(&leftTop);

	BAffineTransform transform = canvas->CurrentState()->Transform();
	BAffineTransform transform = fCanvas->CurrentState()->Transform();
	transform.PreScaleBy(x, y);
	canvas->CurrentState()->SetTransform(transform);
	canvas->GetDrawingEngine()->SetTransform(
		canvas->CurrentState()->CombinedTransform(), leftTop.x, leftTop.y);
	fCanvas->CurrentState()->SetTransform(transform);
	fCanvas->GetDrawingEngine()->SetTransform(
		fCanvas->CurrentState()->CombinedTransform(), leftTop.x, leftTop.y);
}


static void
rotate_by(void* _canvas, double angleRadians)
void
CanvasCallbacks::RotateBy(double angleRadians)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);

	BPoint leftTop(0, 0);
	canvas->PenToScreenTransform().Apply(&leftTop);
	fCanvas->PenToScreenTransform().Apply(&leftTop);

	BAffineTransform transform = canvas->CurrentState()->Transform();
	BAffineTransform transform = fCanvas->CurrentState()->Transform();
	transform.PreRotateBy(angleRadians);
	canvas->CurrentState()->SetTransform(transform);
	canvas->GetDrawingEngine()->SetTransform(
		canvas->CurrentState()->CombinedTransform(), leftTop.x, leftTop.y);
	fCanvas->CurrentState()->SetTransform(transform);
	fCanvas->GetDrawingEngine()->SetTransform(
		fCanvas->CurrentState()->CombinedTransform(), leftTop.x, leftTop.y);
}


static void
blend_layer(void* _canvas, Layer* layer)
void
CanvasCallbacks::BlendLayer(Layer* layer)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	canvas->BlendLayer(layer);
	fCanvas->BlendLayer(layer);
}


static void
clip_to_rect(void* _canvas, const BRect& rect, bool inverse)
void
CanvasCallbacks::ClipToRect(const BRect& rect, bool inverse)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	bool needDrawStateUpdate = canvas->ClipToRect(rect, inverse);
	bool needDrawStateUpdate = fCanvas->ClipToRect(rect, inverse);
	if (needDrawStateUpdate) {
		canvas->CurrentState()->GetAlphaMask()->SetCanvasGeometry(BPoint(0, 0),
			canvas->Bounds());
		canvas->ResyncDrawState();
		fCanvas->CurrentState()->GetAlphaMask()->SetCanvasGeometry(BPoint(0, 0),
			fCanvas->Bounds());
		fCanvas->ResyncDrawState();
	}
	canvas->UpdateCurrentDrawingRegion();
	fCanvas->UpdateCurrentDrawingRegion();
}


static void
clip_to_shape(void* _canvas, int32 opCount, const uint32 opList[],
void
CanvasCallbacks::ClipToShape(int32 opCount, const uint32 opList[],
	int32 ptCount, const BPoint ptList[], bool inverse)
{
	Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
	shape_data shapeData;

	// TODO: avoid copies
@@ -1020,76 +1033,16 @@
	shapeData.ptCount = ptCount;
	shapeData.ptSize = ptCount * sizeof(BPoint);

	canvas->ClipToShape(&shapeData, inverse);
	canvas->CurrentState()->GetAlphaMask()->SetCanvasGeometry(BPoint(0, 0),
		canvas->Bounds());
	canvas->ResyncDrawState();
	fCanvas->ClipToShape(&shapeData, inverse);
	fCanvas->CurrentState()->GetAlphaMask()->SetCanvasGeometry(BPoint(0, 0),
		fCanvas->Bounds());
	fCanvas->ResyncDrawState();

	free(shapeData.opList);
	free(shapeData.ptList);
}


static const BPrivate::picture_player_callbacks kPicturePlayerCallbacks = {
	move_pen_by,
	stroke_line,
	draw_rect,
	draw_round_rect,
	draw_bezier,
	draw_arc,
	draw_ellipse,
	draw_polygon,
	draw_shape,
	draw_string,
	draw_pixels,
	draw_picture,
	set_clipping_rects,
	clip_to_picture,
	push_state,
	pop_state,
	enter_state_change,
	exit_state_change,
	enter_font_state,
	exit_font_state,
	set_origin,
	set_pen_location,
	set_drawing_mode,
	set_line_mode,
	set_pen_size,
	set_fore_color,
	set_back_color,
	set_stipple_pattern,
	set_scale,
	set_font_family,
	set_font_style,
	set_font_spacing,
	set_font_size,
	set_font_rotation,
	set_font_encoding,
	set_font_flags,
	set_font_shear,
	set_font_face,
	set_blending_mode,
	set_transform,
	translate_by,
	scale_by,
	rotate_by,
	blend_layer,
	clip_to_rect,
	clip_to_shape,
	draw_string_locations,
	draw_rect_gradient,
	draw_round_rect_gradient,
	draw_bezier_gradient,
	draw_arc_gradient,
	draw_ellipse_gradient,
	draw_polygon_gradient,
	draw_shape_gradient,
	set_fill_rule,
	stroke_line_gradient
};


// #pragma mark - ServerPicture


@@ -1293,11 +1246,12 @@
	BMallocIO* mallocIO = dynamic_cast<BMallocIO*>(fData.Get());
	if (mallocIO == NULL)
		return;

	CanvasCallbacks callbacks(target);

	BPrivate::PicturePlayer player(mallocIO->Buffer(),
		mallocIO->BufferLength(), PictureList::Private(fPictures.Get()).AsBList());
	player.Play(kPicturePlayerCallbacks, sizeof(kPicturePlayerCallbacks),
		target);
	player.Play(callbacks);
}