From a6db6bd40fe3492fd3104dba560f0e3ff61d388d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Tue, 4 Feb 2014 22:46:55 +0100 Subject: [PATCH] Added WIP support for affine transformations to BViews. Everything untested, but compiles, so it must work. The idea is to introduce BAffineTransform additionally to the existing Origin and Scale properties of BViews. One may use it in parallel or as an alternative. Painter in app_server is not yet aware of the additional transformation. It is however already used to transform drawing coordinates. It probably needs to work differently, perhaps only in Painter and AGGTextRenderer. --- headers/os/interface/View.h | 7 ++ headers/private/app/ServerProtocol.h | 4 + headers/private/app/ServerProtocolStructs.h | 2 + headers/private/interface/PictureDataWriter.h | 2 + headers/private/interface/PictureProtocol.h | 51 ++++++------ headers/private/interface/ViewPrivate.h | 9 +- src/kits/interface/PictureDataWriter.cpp | 14 ++++ src/kits/interface/PicturePlayer.cpp | 16 +++- src/kits/interface/View.cpp | 75 ++++++++++++++--- src/servers/app/DrawState.cpp | 82 ++++++++++++++----- src/servers/app/DrawState.h | 11 ++- src/servers/app/ServerWindow.cpp | 46 ++++++++++- 12 files changed, 258 insertions(+), 61 deletions(-) diff --git a/headers/os/interface/View.h b/headers/os/interface/View.h index 6b8927373c..b2e183cd79 100644 --- a/headers/os/interface/View.h +++ b/headers/os/interface/View.h @@ -6,6 +6,7 @@ #define _VIEW_H +#include #include #include #include @@ -285,6 +286,12 @@ public: void SetOrigin(float x, float y); BPoint Origin() const; + // Works in addition to Origin and Scale. + // May be used in parallel or as a much + // more powerful alternative. + void SetTransform(BAffineTransform transform); + BAffineTransform Transform() const; + void PushState(); void PopState(); diff --git a/headers/private/app/ServerProtocol.h b/headers/private/app/ServerProtocol.h index ca6c19a31e..782a5780fb 100644 --- a/headers/private/app/ServerProtocol.h +++ b/headers/private/app/ServerProtocol.h @@ -341,6 +341,10 @@ enum { AS_DUMP_ALLOCATOR, AS_DUMP_BITMAPS, + // transformation in addition to origin/scale + AS_VIEW_SET_TRANSFORM, + AS_VIEW_GET_TRANSFORM, + AS_LAST_CODE }; diff --git a/headers/private/app/ServerProtocolStructs.h b/headers/private/app/ServerProtocolStructs.h index 12f70a1b8a..853473348e 100644 --- a/headers/private/app/ServerProtocolStructs.h +++ b/headers/private/app/ServerProtocolStructs.h @@ -9,6 +9,7 @@ #define APP_SERVER_PROTOCOL_STRUCTS_H +#include #include @@ -21,6 +22,7 @@ struct ViewSetStateInfo { drawing_mode drawingMode; BPoint origin; float scale; + BAffineTransform transform; join_mode lineJoin; cap_mode lineCap; float miterLimit; diff --git a/headers/private/interface/PictureDataWriter.h b/headers/private/interface/PictureDataWriter.h index 573f6f3e43..9015c05f7e 100644 --- a/headers/private/interface/PictureDataWriter.h +++ b/headers/private/interface/PictureDataWriter.h @@ -9,6 +9,7 @@ #define _PICTURE_DATA_WRITER_H +#include #include #include #include @@ -35,6 +36,7 @@ public: status_t WriteSetPenSize(const float &penSize); status_t WriteSetLineMode(const cap_mode &cap, const join_mode &join, const float &miterLimit); status_t WriteSetScale(const float &scale); + status_t WriteSetTransform(BAffineTransform transform); status_t WriteSetPattern(const pattern &pat); status_t WriteSetClipping(const BRegion ®ion); status_t WriteClearClipping(); diff --git a/headers/private/interface/PictureProtocol.h b/headers/private/interface/PictureProtocol.h index 08d9ca0586..f83b53d86c 100644 --- a/headers/private/interface/PictureProtocol.h +++ b/headers/private/interface/PictureProtocol.h @@ -2,40 +2,40 @@ #define _PICTUREPROTOCOL_H enum { - B_PIC_MOVE_PEN_BY = 0x0010, + B_PIC_MOVE_PEN_BY = 0x0010, - B_PIC_STROKE_LINE = 0x0100, - B_PIC_STROKE_RECT = 0x0101, - B_PIC_FILL_RECT = 0x0102, + B_PIC_STROKE_LINE = 0x0100, + B_PIC_STROKE_RECT = 0x0101, + B_PIC_FILL_RECT = 0x0102, B_PIC_STROKE_ROUND_RECT = 0x0103, B_PIC_FILL_ROUND_RECT = 0x0104, - B_PIC_STROKE_BEZIER = 0x0105, - B_PIC_FILL_BEZIER = 0x0106, + B_PIC_STROKE_BEZIER = 0x0105, + B_PIC_FILL_BEZIER = 0x0106, B_PIC_STROKE_POLYGON = 0x010B, - B_PIC_FILL_POLYGON = 0x010C, - B_PIC_STROKE_SHAPE = 0x010D, - B_PIC_FILL_SHAPE = 0x010E, - B_PIC_DRAW_STRING = 0x010F, - B_PIC_DRAW_PIXELS = 0x0110, - B_PIC_DRAW_PICTURE = 0x0112, - B_PIC_STROKE_ARC = 0x0113, - B_PIC_FILL_ARC = 0x0114, + B_PIC_FILL_POLYGON = 0x010C, + B_PIC_STROKE_SHAPE = 0x010D, + B_PIC_FILL_SHAPE = 0x010E, + B_PIC_DRAW_STRING = 0x010F, + B_PIC_DRAW_PIXELS = 0x0110, + B_PIC_DRAW_PICTURE = 0x0112, + B_PIC_STROKE_ARC = 0x0113, + B_PIC_FILL_ARC = 0x0114, B_PIC_STROKE_ELLIPSE = 0x0115, - B_PIC_FILL_ELLIPSE = 0x0116, + B_PIC_FILL_ELLIPSE = 0x0116, B_PIC_ENTER_STATE_CHANGE = 0x0200, B_PIC_SET_CLIPPING_RECTS = 0x0201, B_PIC_CLIP_TO_PICTURE = 0x0202, - B_PIC_PUSH_STATE = 0x0203, - B_PIC_POP_STATE = 0x0204, + B_PIC_PUSH_STATE = 0x0203, + B_PIC_POP_STATE = 0x0204, B_PIC_CLEAR_CLIPPING_RECTS = 0x0205, - B_PIC_SET_ORIGIN = 0x0300, + B_PIC_SET_ORIGIN = 0x0300, B_PIC_SET_PEN_LOCATION = 0x0301, B_PIC_SET_DRAWING_MODE = 0x0302, - B_PIC_SET_LINE_MODE = 0x0303, - B_PIC_SET_PEN_SIZE = 0x0304, - B_PIC_SET_SCALE = 0x0305, + B_PIC_SET_LINE_MODE = 0x0303, + B_PIC_SET_PEN_SIZE = 0x0304, + B_PIC_SET_SCALE = 0x0305, B_PIC_SET_FORE_COLOR = 0x0306, B_PIC_SET_BACK_COLOR = 0x0307, B_PIC_SET_STIPLE_PATTERN = 0x0308, @@ -46,15 +46,16 @@ enum { B_PIC_SET_FONT_SPACING = 0x0382, B_PIC_SET_FONT_ENCODING = 0x0383, B_PIC_SET_FONT_FLAGS = 0x0384, - B_PIC_SET_FONT_SIZE = 0x0385, + B_PIC_SET_FONT_SIZE = 0x0385, B_PIC_SET_FONT_ROTATE = 0x0386, B_PIC_SET_FONT_SHEAR = 0x0387, - B_PIC_SET_FONT_BPP = 0x0388, - B_PIC_SET_FONT_FACE = 0x0389, + B_PIC_SET_FONT_BPP = 0x0388, + B_PIC_SET_FONT_FACE = 0x0389, + B_PIC_SET_TRANSFORM = 0x0390, }; -const static uint32 kOpsTableSize = 48; +const static uint32 kOpsTableSize = 49; #endif diff --git a/headers/private/interface/ViewPrivate.h b/headers/private/interface/ViewPrivate.h index cd32f93b39..4be0f77869 100644 --- a/headers/private/interface/ViewPrivate.h +++ b/headers/private/interface/ViewPrivate.h @@ -39,8 +39,9 @@ enum { B_VIEW_LOW_COLOR_BIT = 0x00008000, B_VIEW_VIEW_COLOR_BIT = 0x00010000, B_VIEW_PATTERN_BIT = 0x00020000, + B_VIEW_TRANSFORM_BIT = 0x00040000, - B_VIEW_ALL_BITS = 0x0003ffff, + B_VIEW_ALL_BITS = 0x0007ffff, // these used for archiving only B_VIEW_RESIZE_BIT = 0x00001000, @@ -111,7 +112,11 @@ class ViewState { ::drawing_mode drawing_mode; BRegion clipping_region; bool clipping_region_used; + + // transformation BPoint origin; + float scale; + BAffineTransform transform; // line modes join_mode line_join; @@ -122,8 +127,6 @@ class ViewState { source_alpha alpha_source_mode; alpha_function alpha_function_mode; - float scale; - // fonts BFont font; uint16 font_flags; diff --git a/src/kits/interface/PictureDataWriter.cpp b/src/kits/interface/PictureDataWriter.cpp index 32154151b9..21b64106b2 100644 --- a/src/kits/interface/PictureDataWriter.cpp +++ b/src/kits/interface/PictureDataWriter.cpp @@ -157,6 +157,20 @@ PictureDataWriter::WriteSetScale(const float &scale) } +status_t +PictureDataWriter::WriteSetTransform(BAffineTransform transform) +{ + try { + BeginOp(B_PIC_SET_TRANSFORM); + Write(transform); + EndOp(); + } catch (status_t &status) { + return status; + } + return B_OK; +} + + status_t PictureDataWriter::WriteSetPattern(const pattern &pat) { diff --git a/src/kits/interface/PicturePlayer.cpp b/src/kits/interface/PicturePlayer.cpp index 5a1fcbdf40..f337bc1896 100644 --- a/src/kits/interface/PicturePlayer.cpp +++ b/src/kits/interface/PicturePlayer.cpp @@ -10,16 +10,19 @@ /** PicturePlayer is used to play picture data. */ +#include + #include #include -#include +#include #include - #include + using BPrivate::PicturePlayer; + typedef void (*fnc)(void*); typedef void (*fnc_BPoint)(void*, BPoint); typedef void (*fnc_BPointBPoint)(void*, BPoint, BPoint); @@ -43,6 +46,7 @@ typedef void (*fnc_DrawPixels)(void *, BRect, BRect, int32, int32, int32, int32, int32, const void *); typedef void (*fnc_DrawPicture)(void *, BPoint, int32); typedef void (*fnc_BShape)(void*, BShape*); +typedef void (*fnc_BAffineTransform)(void*, BAffineTransform); static void @@ -91,6 +95,7 @@ PictureOpToString(int op) RETURN_STRING(B_PIC_SET_LINE_MODE); RETURN_STRING(B_PIC_SET_PEN_SIZE); RETURN_STRING(B_PIC_SET_SCALE); + RETURN_STRING(B_PIC_SET_TRANSFORM); RETURN_STRING(B_PIC_SET_FORE_COLOR); RETURN_STRING(B_PIC_SET_BACK_COLOR); RETURN_STRING(B_PIC_SET_STIPLE_PATTERN); @@ -533,6 +538,13 @@ PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData) break; } + case B_PIC_SET_TRANSFORM: + { + ((fnc_BAffineTransform)functionTable[48])(userData, + *reinterpret_cast(data)); + break; + } + default: break; } diff --git a/src/kits/interface/View.cpp b/src/kits/interface/View.cpp index f20295d1e7..84da3eda82 100644 --- a/src/kits/interface/View.cpp +++ b/src/kits/interface/View.cpp @@ -221,6 +221,7 @@ ViewState::UpdateServerState(BPrivate::PortLink &link) info.drawingMode = drawing_mode; info.origin = origin; info.scale = scale; + info.transform = transform; info.lineJoin = line_join; info.lineCap = line_cap; info.miterLimit = miter_limit; @@ -284,6 +285,7 @@ ViewState::UpdateFrom(BPrivate::PortLink &link) drawing_mode = info.viewStateInfo.drawingMode; origin = info.viewStateInfo.origin; scale = info.viewStateInfo.scale; + transform = info.viewStateInfo.transform; line_join = info.viewStateInfo.lineJoin; line_cap = info.viewStateInfo.lineCap; miter_limit = info.viewStateInfo.miterLimit; @@ -467,6 +469,14 @@ BView::BView(BMessage* archive) if (archive->FindPoint("_origin", &origin) == B_OK) SetOrigin(origin); + float scale; + if (archive->FindFloat("_scale", &scale) == B_OK) + SetScale(scale); + + BAffineTransform transform; + if (archive->FindFlat("_transform", &transform) == B_OK) + SetTransform(transform); + float penSize; if (archive->FindFloat("_psize", &penSize) == B_OK) SetPenSize(penSize); @@ -584,6 +594,14 @@ BView::Archive(BMessage* data, bool deep) const if (ret == B_OK && (fState->archiving_flags & B_VIEW_ORIGIN_BIT) != 0) ret = data->AddPoint("_origin", Origin()); + if (ret == B_OK && (fState->archiving_flags & B_VIEW_SCALE_BIT) != 0) + ret = data->AddFloat("_scale", Scale()); + + if (ret == B_OK && (fState->archiving_flags & B_VIEW_TRANSFORM_BIT) != 0) { + BAffineTransform transform = Transform(); + ret = data->AddFlat("_transform", &transform); + } + if (ret == B_OK && (fState->archiving_flags & B_VIEW_PEN_SIZE_BIT) != 0) ret = data->AddFloat("_psize", PenSize()); @@ -1743,10 +1761,12 @@ BView::PushState() fOwner->fLink->StartMessage(AS_VIEW_PUSH_STATE); - // initialize origin and scale - fState->valid_flags |= B_VIEW_SCALE_BIT | B_VIEW_ORIGIN_BIT; + // initialize origin, scale and transform, new states start "clean". + fState->valid_flags |= B_VIEW_SCALE_BIT | B_VIEW_ORIGIN_BIT + | B_VIEW_TRANSFORM_BIT; fState->scale = 1.0f; fState->origin.Set(0, 0); + fState->transform.Reset(); } @@ -1805,12 +1825,10 @@ BView::Origin() const fOwner->fLink->StartMessage(AS_VIEW_GET_ORIGIN); int32 code; - if (fOwner->fLink->FlushWithReply(code) == B_OK - && code == B_OK) { + if (fOwner->fLink->FlushWithReply(code) == B_OK && code == B_OK) fOwner->fLink->Read(&fState->origin); - fState->valid_flags |= B_VIEW_ORIGIN_BIT; - } + fState->valid_flags |= B_VIEW_ORIGIN_BIT; } return fState->origin; @@ -1846,8 +1864,7 @@ BView::Scale() const fOwner->fLink->StartMessage(AS_VIEW_GET_SCALE); int32 code; - if (fOwner->fLink->FlushWithReply(code) == B_OK - && code == B_OK) + if (fOwner->fLink->FlushWithReply(code) == B_OK && code == B_OK) fOwner->fLink->Read(&fState->scale); fState->valid_flags |= B_VIEW_SCALE_BIT; @@ -1857,6 +1874,45 @@ BView::Scale() const } +void +BView::SetTransform(BAffineTransform transform) +{ + if (fState->IsValid(B_VIEW_TRANSFORM_BIT) && transform == fState->transform) + return; + + if (fOwner != NULL) { + _CheckLockAndSwitchCurrent(); + + fOwner->fLink->StartMessage(AS_VIEW_SET_TRANSFORM); + fOwner->fLink->Attach(transform); + + fState->valid_flags |= B_VIEW_TRANSFORM_BIT; + } + + fState->transform = transform; + fState->archiving_flags |= B_VIEW_TRANSFORM_BIT; +} + + +BAffineTransform +BView::Transform() const +{ + if (!fState->IsValid(B_VIEW_TRANSFORM_BIT) && fOwner != NULL) { + _CheckLockAndSwitchCurrent(); + + fOwner->fLink->StartMessage(AS_VIEW_GET_TRANSFORM); + + int32 code; + if (fOwner->fLink->FlushWithReply(code) == B_OK && code == B_OK) + fOwner->fLink->Read(&fState->transform); + + fState->valid_flags |= B_VIEW_TRANSFORM_BIT; + } + + return fState->transform; +} + + void BView::SetLineMode(cap_mode lineCap, join_mode lineJoin, float miterLimit) { @@ -1918,8 +1974,7 @@ BView::LineMiterLimit() const fOwner->fLink->StartMessage(AS_VIEW_GET_LINE_MODE); int32 code; - if (fOwner->fLink->FlushWithReply(code) == B_OK - && code == B_OK) { + if (fOwner->fLink->FlushWithReply(code) == B_OK && code == B_OK) { ViewSetLineModeInfo info; fOwner->fLink->Read(&info); diff --git a/src/servers/app/DrawState.cpp b/src/servers/app/DrawState.cpp index 767d77607b..a673aea410 100644 --- a/src/servers/app/DrawState.cpp +++ b/src/servers/app/DrawState.cpp @@ -30,10 +30,12 @@ using std::nothrow; DrawState::DrawState() : - fOrigin(0.0, 0.0), - fCombinedOrigin(0.0, 0.0), - fScale(1.0), - fCombinedScale(1.0), + fOrigin(0.0f, 0.0f), + fCombinedOrigin(0.0f, 0.0f), + fScale(1.0f), + fCombinedScale(1.0f), + fTransform(), + fCombinedTransform(), fClippingRegion(NULL), fAlphaMask(NULL), @@ -45,8 +47,8 @@ DrawState::DrawState() fAlphaSrcMode(B_PIXEL_ALPHA), fAlphaFncMode(B_ALPHA_OVERLAY), - fPenLocation(0.0, 0.0), - fPenSize(1.0), + fPenLocation(0.0f, 0.0f), + fPenSize(1.0f), fFontAliasing(false), fSubPixelPrecise(false), @@ -65,6 +67,8 @@ DrawState::DrawState(const DrawState& other) fCombinedOrigin(other.fCombinedOrigin), fScale(other.fScale), fCombinedScale(other.fCombinedScale), + fTransform(other.fTransform), + fCombinedTransform(other.fCombinedTransform), fClippingRegion(NULL), fAlphaMask(NULL), @@ -115,6 +119,7 @@ DrawState::PushState() // Prepare state as derived from this state next->fOrigin = BPoint(0.0, 0.0); next->fScale = 1.0; + next->fTransform.Reset(); next->fPreviousState = this; next->SetAlphaMask(fAlphaMask); } @@ -212,6 +217,7 @@ DrawState::ReadFromLink(BPrivate::LinkReceiver& link) fDrawingMode = info.drawingMode; fOrigin = info.origin; fScale = info.scale; + fTransform = info.transform; fLineJoinMode = info.lineJoin; fLineCapMode = info.lineCap; fMiterLimit = info.miterLimit; @@ -222,9 +228,11 @@ DrawState::ReadFromLink(BPrivate::LinkReceiver& link) if (fPreviousState != NULL) { fCombinedOrigin = fPreviousState->fCombinedOrigin + fOrigin; fCombinedScale = fPreviousState->fCombinedScale * fScale; + fCombinedTransform = fPreviousState->fCombinedTransform * fTransform; } else { fCombinedOrigin = fOrigin; fCombinedScale = fScale; + fCombinedTransform = fTransform; } @@ -273,6 +281,7 @@ DrawState::WriteToLink(BPrivate::LinkSender& link) const info.viewStateInfo.drawingMode = fDrawingMode; info.viewStateInfo.origin = fOrigin; info.viewStateInfo.scale = fScale; + info.viewStateInfo.transform = fTransform; info.viewStateInfo.lineJoin = fLineJoinMode; info.viewStateInfo.lineCap = fLineCapMode; info.viewStateInfo.miterLimit = fMiterLimit; @@ -319,21 +328,39 @@ DrawState::SetOrigin(BPoint origin) void DrawState::SetScale(float scale) { - if (fScale != scale) { - fScale = scale; + if (fScale == scale) + return; - // NOTE: the scales of earlier states are never expected to - // change, only the topmost state ever changes - if (fPreviousState != NULL) - fCombinedScale = fPreviousState->fCombinedScale * fScale; - else - fCombinedScale = fScale; + fScale = scale; - // update font size - // NOTE: This is what makes the call potentially expensive, - // hence the introductory check - fFont.SetSize(fUnscaledFontSize * fCombinedScale); - } + // NOTE: the scales of earlier states are never expected to + // change, only the topmost state ever changes + if (fPreviousState != NULL) + fCombinedScale = fPreviousState->fCombinedScale * fScale; + else + fCombinedScale = fScale; + + // update font size + // NOTE: This is what makes the call potentially expensive, + // hence the introductory check + fFont.SetSize(fUnscaledFontSize * fCombinedScale); +} + + +void +DrawState::SetTransform(BAffineTransform transform) +{ + if (fTransform == transform) + return; + + fTransform = transform; + + // NOTE: the transforms of earlier states are never expected to + // change, only the topmost state ever changes + if (fPreviousState != NULL) + fCombinedTransform = fPreviousState->fCombinedTransform * fTransform; + else + fCombinedTransform = fTransform; } @@ -430,12 +457,26 @@ DrawState::Transform(float* x, float* y) const *y *= fCombinedScale; *x += fCombinedOrigin.x; *y += fCombinedOrigin.y; + if (!fCombinedTransform.IsIdentity()) { + double _x = *x; + double _y = *y; + fCombinedTransform.Apply(&_x, &_y); + *x = _x; + *y = _y; + } } void DrawState::InverseTransform(float* x, float* y) const { + if (!fCombinedTransform.IsIdentity()) { + double _x = *x; + double _y = *y; + fCombinedTransform.ApplyInverse(&_x, &_y); + *x = _x; + *y = _y; + } *x -= fCombinedOrigin.x; *y -= fCombinedOrigin.y; if (fCombinedScale != 0.0) { @@ -667,6 +708,9 @@ DrawState::PrintToStream() const { printf("\t Origin: (%.1f, %.1f)\n", fOrigin.x, fOrigin.y); printf("\t Scale: %.2f\n", fScale); + printf("\t Transform: %.2f, %.2f, %.2f, %.2f, %.2f, %.2f\n", + fTransform.sx, fTransform.shy, fTransform.shx, + fTransform.sy, fTransform.tx, fTransform.ty); printf("\t Pen Location and Size: (%.1f, %.1f) - %.2f (%.2f)\n", fPenLocation.x, fPenLocation.y, PenSize(), fPenSize); diff --git a/src/servers/app/DrawState.h b/src/servers/app/DrawState.h index 792257e02a..58ca037907 100644 --- a/src/servers/app/DrawState.h +++ b/src/servers/app/DrawState.h @@ -12,10 +12,11 @@ #define _DRAW_STATE_H_ +#include #include #include #include -#include // for B_FONT_ALL +#include #include "ServerFont.h" #include "PatternHandler.h" @@ -60,6 +61,12 @@ public: float CombinedScale() const { return fCombinedScale; } + void SetTransform(BAffineTransform transform); + BAffineTransform Transform() const + { return fTransform; } + BAffineTransform CombinedTransform() const + { return fCombinedTransform; } + // additional clipping as requested by client void SetClippingRegion(const BRegion* region); @@ -149,6 +156,8 @@ protected: BPoint fCombinedOrigin; float fScale; float fCombinedScale; + BAffineTransform fTransform; + BAffineTransform fCombinedTransform; BRegion* fClippingRegion; diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index 1083673e07..c308149bc5 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -1575,6 +1575,36 @@ fDesktop->LockSingleWindow(); fLink.Flush(); break; } + case AS_VIEW_SET_TRANSFORM: + { + BAffineTransform transform; + if (link.Read(&transform) != B_OK) + break; + + DTRACE(("ServerWindow %s: Message AS_VIEW_SET_TRANSFORM: " + "View: %s -> transform: %.2f, %.2f, %.2f, %.2f, %.2f, %.2f\n", + Title(), fCurrentView->Name(), transform.sx, transform.shy, + transform.shx, transform.sy, transform.tx, transform.ty)); + + fCurrentView->CurrentState()->SetTransform(transform); + _UpdateDrawState(fCurrentView); + break; + } + case AS_VIEW_GET_TRANSFORM: + { + BAffineTransform transform + = fCurrentView->CurrentState()->Transform(); + + DTRACE(("ServerWindow %s: Message AS_VIEW_GET_TRANSFORM: " + "View: %s -> transform: %.2f, %.2f, %.2f, %.2f, %.2f, %.2f\n", + Title(), fCurrentView->Name(), transform.sx, transform.shy, + transform.shx, transform.sy, transform.tx, transform.ty)); + + fLink.StartMessage(B_OK); + fLink.Attach(transform); + fLink.Flush(); + break; + } case AS_VIEW_SET_PEN_LOC: { BPoint location; @@ -2944,13 +2974,27 @@ ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver& link) case AS_VIEW_SET_SCALE: { float scale; - link.Read(&scale); + if (link.Read(&scale) != B_OK) + break; + picture->WriteSetScale(scale); fCurrentView->SetScale(scale); _UpdateDrawState(fCurrentView); break; } + case AS_VIEW_SET_TRANSFORM: + { + BAffineTransform transform; + if (link.Read(&transform) != B_OK) + break; + + picture->WriteSetTransform(transform); + + fCurrentView->CurrentState()->SetTransform(transform); + _UpdateDrawState(fCurrentView); + break; + } case AS_VIEW_SET_PATTERN: {