/* * Copyright 2009, Haiku, Inc. * Distributed under the terms of the MIT License. * * Authors: * Michael Lotz */ #ifndef REMOTE_MESSAGE_H #define REMOTE_MESSAGE_H #ifndef CLIENT_COMPILE # include "PatternHandler.h" # include #endif #include "StreamingRingBuffer.h" #include #include #include #include #include #include class BBitmap; class BFont; class BGradient; class BView; class DrawState; class Pattern; class RemotePainter; class ServerBitmap; class ServerCursor; class ServerFont; struct ViewLineArrayInfo; enum { RP_INIT_CONNECTION = 1, RP_UPDATE_DISPLAY_MODE, RP_CLOSE_CONNECTION, RP_GET_SYSTEM_PALETTE, RP_GET_SYSTEM_PALETTE_RESULT, RP_CREATE_STATE = 20, RP_DELETE_STATE, RP_ENABLE_SYNC_DRAWING, RP_DISABLE_SYNC_DRAWING, RP_INVALIDATE_RECT, RP_INVALIDATE_REGION, RP_SET_OFFSETS = 40, RP_SET_HIGH_COLOR, RP_SET_LOW_COLOR, RP_SET_PEN_SIZE, RP_SET_STROKE_MODE, RP_SET_BLENDING_MODE, RP_SET_PATTERN, RP_SET_DRAWING_MODE, RP_SET_FONT, RP_SET_TRANSFORM, RP_CONSTRAIN_CLIPPING_REGION = 60, RP_COPY_RECT_NO_CLIPPING, RP_INVERT_RECT, RP_DRAW_BITMAP, RP_DRAW_BITMAP_RECTS, RP_STROKE_ARC = 80, RP_STROKE_BEZIER, RP_STROKE_ELLIPSE, RP_STROKE_POLYGON, RP_STROKE_RECT, RP_STROKE_ROUND_RECT, RP_STROKE_SHAPE, RP_STROKE_TRIANGLE, RP_STROKE_LINE, RP_STROKE_LINE_ARRAY, RP_FILL_ARC = 100, RP_FILL_BEZIER, RP_FILL_ELLIPSE, RP_FILL_POLYGON, RP_FILL_RECT, RP_FILL_ROUND_RECT, RP_FILL_SHAPE, RP_FILL_TRIANGLE, RP_FILL_REGION, RP_FILL_ARC_GRADIENT = 120, RP_FILL_BEZIER_GRADIENT, RP_FILL_ELLIPSE_GRADIENT, RP_FILL_POLYGON_GRADIENT, RP_FILL_RECT_GRADIENT, RP_FILL_ROUND_RECT_GRADIENT, RP_FILL_SHAPE_GRADIENT, RP_FILL_TRIANGLE_GRADIENT, RP_FILL_REGION_GRADIENT, RP_STROKE_POINT_COLOR = 140, RP_STROKE_LINE_1PX_COLOR, RP_STROKE_RECT_1PX_COLOR, RP_FILL_RECT_COLOR = 160, RP_FILL_REGION_COLOR_NO_CLIPPING, RP_DRAW_STRING = 180, RP_DRAW_STRING_WITH_OFFSETS, RP_DRAW_STRING_RESULT, RP_STRING_WIDTH, RP_STRING_WIDTH_RESULT, RP_READ_BITMAP, RP_READ_BITMAP_RESULT, RP_SET_CURSOR = 200, RP_SET_CURSOR_VISIBLE, RP_MOVE_CURSOR_TO, RP_MOUSE_MOVED = 220, RP_MOUSE_DOWN, RP_MOUSE_UP, RP_MOUSE_WHEEL_CHANGED, RP_KEY_DOWN = 240, RP_KEY_UP, RP_UNMAPPED_KEY_DOWN, RP_UNMAPPED_KEY_UP, RP_MODIFIERS_CHANGED }; class RemoteMessage { public: RemoteMessage(StreamingRingBuffer* source, StreamingRingBuffer *target); ~RemoteMessage(); void Start(uint16 code); status_t Flush(); void Cancel(); status_t NextMessage(uint16& code); uint16 Code() { return fCode; } uint32 DataLeft() { return fDataLeft; } template void Add(const T& value); void AddString(const char* string, size_t length); void AddRegion(const BRegion& region); void AddGradient(const BGradient& gradient); void AddTransform(const BAffineTransform& transform); #ifndef CLIENT_COMPILE void AddBitmap(const ServerBitmap& bitmap, bool minimal = false); void AddFont(const ServerFont& font); void AddPattern(const Pattern& pattern); void AddDrawState(const DrawState& drawState); void AddArrayLine(const ViewLineArrayInfo& line); void AddCursor(const ServerCursor& cursor); #else void AddBitmap(const BBitmap& bitmap); #endif template void AddList(const T* array, int32 count); template status_t Read(T& value); status_t ReadRegion(BRegion& region); status_t ReadFontState(BFont& font); // sets font state status_t ReadViewState(BView& view, ::pattern& pattern); // sets viewstate and returns pattern status_t ReadString(char** _string, size_t& length); status_t ReadBitmap(BBitmap** _bitmap, bool minimal = false, color_space colorSpace = B_RGB32, uint32 flags = 0); status_t ReadGradient(BGradient** _gradient); status_t ReadTransform(BAffineTransform& transform); status_t ReadArrayLine(BPoint& startPoint, BPoint& endPoint, rgb_color& color); template status_t ReadList(T* array, int32 count); private: bool _MakeSpace(size_t size); StreamingRingBuffer* fSource; StreamingRingBuffer* fTarget; uint8* fBuffer; size_t fAvailable; size_t fWriteIndex; uint32 fDataLeft; uint16 fCode; }; inline RemoteMessage::RemoteMessage(StreamingRingBuffer* source, StreamingRingBuffer* target) : fSource(source), fTarget(target), fBuffer(NULL), fAvailable(0), fWriteIndex(0), fDataLeft(0) { } inline RemoteMessage::~RemoteMessage() { if (fWriteIndex > 0) Flush(); free(fBuffer); } inline void RemoteMessage::Start(uint16 code) { if (fWriteIndex > 0) Flush(); Add(code); uint32 sizeDummy = 0; Add(sizeDummy); } inline status_t RemoteMessage::Flush() { if (fWriteIndex == 0 || fTarget == NULL) return B_NO_INIT; uint32 length = fWriteIndex; fAvailable += fWriteIndex; fWriteIndex = 0; memcpy(fBuffer + sizeof(uint16), &length, sizeof(uint32)); return fTarget->Write(fBuffer, length); } template inline void RemoteMessage::Add(const T& value) { if (!_MakeSpace(sizeof(T))) return; memcpy(fBuffer + fWriteIndex, &value, sizeof(T)); fWriteIndex += sizeof(T); fAvailable -= sizeof(T); } inline void RemoteMessage::AddString(const char* string, size_t length) { Add((uint32)length); if (length > fAvailable && !_MakeSpace(length)) return; memcpy(fBuffer + fWriteIndex, string, length); fWriteIndex += length; fAvailable -= length; } inline void RemoteMessage::AddRegion(const BRegion& region) { int32 rectCount = region.CountRects(); Add(rectCount); for (int32 i = 0; i < rectCount; i++) Add(region.RectAt(i)); } template inline void RemoteMessage::AddList(const T* array, int32 count) { for (int32 i = 0; i < count; i++) Add(array[i]); } template inline status_t RemoteMessage::Read(T& value) { if (fDataLeft < sizeof(T)) return B_ERROR; if (fSource == NULL) return B_NO_INIT; int32 readSize = fSource->Read(&value, sizeof(T)); if (readSize < 0) return readSize; if (readSize != sizeof(T)) return B_ERROR; fDataLeft -= sizeof(T); return B_OK; } inline status_t RemoteMessage::ReadRegion(BRegion& region) { region.MakeEmpty(); int32 rectCount; Read(rectCount); for (int32 i = 0; i < rectCount; i++) { BRect rect; status_t result = Read(rect); if (result != B_OK) return result; region.Include(rect); } return B_OK; } template inline status_t RemoteMessage::ReadList(T* array, int32 count) { for (int32 i = 0; i < count; i++) { status_t result = Read(array[i]); if (result != B_OK) return result; } return B_OK; } inline bool RemoteMessage::_MakeSpace(size_t size) { if (fAvailable >= size) return true; size_t extraSize = size + 20; uint8 *newBuffer = (uint8*)realloc(fBuffer, fWriteIndex + extraSize); if (newBuffer == NULL) return false; fAvailable = extraSize; fBuffer = newBuffer; return true; } #endif // REMOTE_MESSAGE_H