BView: add methods for affine translation/scaling/rotation

* BView::TranslateBy(), BView::ScaleBy() and BView::RotateBy()
  allow to conveniently modify the current affine transformation.
  This makes it unnecessary to first read the current transform,
  modify it, and then set it again.
  Uses the new Pre...() methods of BAffineTransform.

* Also, remove setting the transform "through" to the BView even
  while recording a BPicture, as this now results in transforms
  being applied more than once.
This commit is contained in:
Julian Harnath
2015-11-10 23:34:08 +01:00
parent 4721524cb5
commit 25dbf74b8e
13 changed files with 301 additions and 4 deletions
+3
View File
@@ -300,6 +300,9 @@ public:
// more powerful alternative. // more powerful alternative.
void SetTransform(BAffineTransform transform); void SetTransform(BAffineTransform transform);
BAffineTransform Transform() const; BAffineTransform Transform() const;
void TranslateBy(double x, double y);
void ScaleBy(double x, double y);
void RotateBy(double angleRadians);
void PushState(); void PushState();
void PopState(); void PopState();
+4
View File
@@ -343,6 +343,10 @@ enum {
AS_VIEW_SET_TRANSFORM, AS_VIEW_SET_TRANSFORM,
AS_VIEW_GET_TRANSFORM, AS_VIEW_GET_TRANSFORM,
AS_VIEW_AFFINE_TRANSLATE,
AS_VIEW_AFFINE_SCALE,
AS_VIEW_AFFINE_ROTATE,
// Polygon filling rules // Polygon filling rules
AS_VIEW_SET_FILL_RULE, AS_VIEW_SET_FILL_RULE,
AS_VIEW_GET_FILL_RULE, AS_VIEW_GET_FILL_RULE,
@@ -41,6 +41,9 @@ public:
const float& miterLimit); const float& miterLimit);
status_t WriteSetScale(const float& scale); status_t WriteSetScale(const float& scale);
status_t WriteSetTransform(BAffineTransform transform); status_t WriteSetTransform(BAffineTransform transform);
status_t WriteTranslateBy(double x, double y);
status_t WriteScaleBy(double x, double y);
status_t WriteRotateBy(double angleRadians);
status_t WriteSetPattern(const ::pattern& pattern); status_t WriteSetPattern(const ::pattern& pattern);
status_t WriteClipToPicture(int32 pictureToken, status_t WriteClipToPicture(int32 pictureToken,
const BPoint& origin, bool inverse); const BPoint& origin, bool inverse);
@@ -84,6 +84,9 @@ struct picture_player_callbacks {
void (*set_blending_mode)(void* userData, source_alpha alphaSourceMode, void (*set_blending_mode)(void* userData, source_alpha alphaSourceMode,
alpha_function alphaFunctionMode); alpha_function alphaFunctionMode);
void (*set_transform)(void* userData, const BAffineTransform& transform); 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 (*blend_layer)(void* userData, Layer* layer);
void (*clip_to_rect)(void* userData, const BRect& rect, bool inverse); void (*clip_to_rect)(void* userData, const BRect& rect, bool inverse);
void (*clip_to_shape)(void* userData, int32 opCount, const uint32 opList[], void (*clip_to_shape)(void* userData, int32 opCount, const uint32 opList[],
+4 -1
View File
@@ -54,7 +54,10 @@ enum {
B_PIC_SET_FONT_BPP = 0x0388, B_PIC_SET_FONT_BPP = 0x0388,
B_PIC_SET_FONT_FACE = 0x0389, B_PIC_SET_FONT_FACE = 0x0389,
B_PIC_SET_TRANSFORM = 0x0390, B_PIC_SET_TRANSFORM = 0x0390,
B_PIC_BLEND_LAYER = 0x0391 B_PIC_AFFINE_TRANSLATE = 0x0391,
B_PIC_AFFINE_SCALE = 0x0392,
B_PIC_AFFINE_ROTATE = 0x0393,
B_PIC_BLEND_LAYER = 0x0394
}; };
+47
View File
@@ -183,6 +183,53 @@ PictureDataWriter::WriteSetTransform(BAffineTransform transform)
} }
status_t
PictureDataWriter::WriteTranslateBy(double x, double y)
{
try {
BeginOp(B_PIC_AFFINE_TRANSLATE);
Write<double>(x);
Write<double>(y);
EndOp();
} catch (status_t& status) {
return status;
}
return B_OK;
}
status_t
PictureDataWriter::WriteScaleBy(double x, double y)
{
try {
BeginOp(B_PIC_AFFINE_SCALE);
Write<double>(x);
Write<double>(y);
EndOp();
} catch (status_t& status) {
return status;
}
return B_OK;
}
status_t
PictureDataWriter::WriteRotateBy(double angleRadians)
{
try {
BeginOp(B_PIC_AFFINE_ROTATE);
Write<double>(angleRadians);
EndOp();
} catch (status_t& status) {
return status;
}
return B_OK;
}
status_t status_t
PictureDataWriter::WriteSetPattern(const ::pattern& pattern) PictureDataWriter::WriteSetPattern(const ::pattern& pattern)
{ {
+36
View File
@@ -1213,6 +1213,42 @@ PicturePlayer::_Play(const picture_player_callbacks& callbacks, void* userData,
break; break;
} }
case B_PIC_AFFINE_TRANSLATE:
{
const double* x;
const double* y;
if (callbacks.translate_by == NULL || !reader.Get(x)
|| !reader.Get(y)) {
break;
}
callbacks.translate_by(userData, *x, *y);
break;
}
case B_PIC_AFFINE_SCALE:
{
const double* x;
const double* y;
if (callbacks.scale_by == NULL || !reader.Get(x)
|| !reader.Get(y)) {
break;
}
callbacks.scale_by(userData, *x, *y);
break;
}
case B_PIC_AFFINE_ROTATE:
{
const double* angleRadians;
if (callbacks.rotate_by == NULL || !reader.Get(angleRadians))
break;
callbacks.rotate_by(userData, *angleRadians);
break;
}
case B_PIC_BLEND_LAYER: case B_PIC_BLEND_LAYER:
{ {
Layer* const* layer; Layer* const* layer;
+50
View File
@@ -1924,6 +1924,56 @@ BView::Transform() const
} }
void
BView::TranslateBy(double x, double y)
{
if (fOwner != NULL) {
_CheckLockAndSwitchCurrent();
fOwner->fLink->StartMessage(AS_VIEW_AFFINE_TRANSLATE);
fOwner->fLink->Attach<double>(x);
fOwner->fLink->Attach<double>(y);
fState->valid_flags &= ~B_VIEW_TRANSFORM_BIT;
}
fState->archiving_flags |= B_VIEW_TRANSFORM_BIT;
}
void
BView::ScaleBy(double x, double y)
{
if (fOwner != NULL) {
_CheckLockAndSwitchCurrent();
fOwner->fLink->StartMessage(AS_VIEW_AFFINE_SCALE);
fOwner->fLink->Attach<double>(x);
fOwner->fLink->Attach<double>(y);
fState->valid_flags &= ~B_VIEW_TRANSFORM_BIT;
}
fState->archiving_flags |= B_VIEW_TRANSFORM_BIT;
}
void
BView::RotateBy(double angleRadians)
{
if (fOwner != NULL) {
_CheckLockAndSwitchCurrent();
fOwner->fLink->StartMessage(AS_VIEW_AFFINE_ROTATE);
fOwner->fLink->Attach<double>(angleRadians);
fState->valid_flags &= ~B_VIEW_TRANSFORM_BIT;
}
fState->archiving_flags |= B_VIEW_TRANSFORM_BIT;
}
void void
BView::SetLineMode(cap_mode lineCap, join_mode lineJoin, float miterLimit) BView::SetLineMode(cap_mode lineCap, join_mode lineJoin, float miterLimit)
{ {
@@ -730,7 +730,42 @@ set_transform(void* _state, const BAffineTransform& transform)
TRACE_BB("%p transform\n", _state); TRACE_BB("%p transform\n", _state);
BoundingBoxState* const state = BoundingBoxState* const state =
reinterpret_cast<BoundingBoxState*>(_state); reinterpret_cast<BoundingBoxState*>(_state);
state->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();
transform.PreTranslateBy(x, y);
state->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();
transform.PreScaleBy(x, y);
state->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();
transform.PreRotateBy(angleRadians);
state->GetDrawState()->SetTransform(transform); state->GetDrawState()->SetTransform(transform);
} }
@@ -791,6 +826,9 @@ static const BPrivate::picture_player_callbacks
set_font_face, set_font_face,
set_blending_mode, set_blending_mode,
set_transform, set_transform,
translate_by,
scale_by,
rotate_by,
determine_bounds_nested_layer determine_bounds_nested_layer
}; };
+37
View File
@@ -749,6 +749,40 @@ set_transform(void* _canvas, const BAffineTransform& transform)
{ {
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
canvas->CurrentState()->SetTransform(transform); canvas->CurrentState()->SetTransform(transform);
canvas->GetDrawingEngine()->SetTransform(transform);
}
static void
translate_by(void* _canvas, double x, double y)
{
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
BAffineTransform transform = canvas->CurrentState()->Transform();
transform.PreTranslateBy(x, y);
canvas->CurrentState()->SetTransform(transform);
canvas->GetDrawingEngine()->SetTransform(transform);
}
static void
scale_by(void* _canvas, double x, double y)
{
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
BAffineTransform transform = canvas->CurrentState()->Transform();
transform.PreScaleBy(x, y);
canvas->CurrentState()->SetTransform(transform);
canvas->GetDrawingEngine()->SetTransform(transform);
}
static void
rotate_by(void* _canvas, double angleRadians)
{
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
BAffineTransform transform = canvas->CurrentState()->Transform();
transform.PreRotateBy(angleRadians);
canvas->CurrentState()->SetTransform(transform);
canvas->GetDrawingEngine()->SetTransform(transform);
} }
@@ -838,6 +872,9 @@ static const BPrivate::picture_player_callbacks kPicturePlayerCallbacks = {
set_font_face, set_font_face,
set_blending_mode, set_blending_mode,
set_transform, set_transform,
translate_by,
scale_by,
rotate_by,
blend_layer, blend_layer,
clip_to_rect, clip_to_rect,
clip_to_shape clip_to_shape
+68 -3
View File
@@ -1635,6 +1635,44 @@ fDesktop->LockSingleWindow();
fLink.Flush(); fLink.Flush();
break; break;
} }
case AS_VIEW_AFFINE_TRANSLATE:
{
double x, y;
link.Read<double>(&x);
link.Read<double>(&y);
BAffineTransform current =
fCurrentView->CurrentState()->Transform();
current.PreTranslateBy(x, y);
fCurrentView->CurrentState()->SetTransform(current);
_UpdateDrawState(fCurrentView);
break;
}
case AS_VIEW_AFFINE_SCALE:
{
double x, y;
link.Read<double>(&x);
link.Read<double>(&y);
BAffineTransform current =
fCurrentView->CurrentState()->Transform();
current.PreScaleBy(x, y);
fCurrentView->CurrentState()->SetTransform(current);
_UpdateDrawState(fCurrentView);
break;
}
case AS_VIEW_AFFINE_ROTATE:
{
double angleRadians;
link.Read<double>(&angleRadians);
BAffineTransform current =
fCurrentView->CurrentState()->Transform();
current.PreRotateBy(angleRadians);
fCurrentView->CurrentState()->SetTransform(current);
_UpdateDrawState(fCurrentView);
break;
}
case AS_VIEW_SET_PEN_LOC: case AS_VIEW_SET_PEN_LOC:
{ {
BPoint location; BPoint location;
@@ -3133,12 +3171,39 @@ ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver& link)
break; break;
picture->WriteSetTransform(transform); picture->WriteSetTransform(transform);
fCurrentView->CurrentState()->SetTransform(transform);
_UpdateDrawState(fCurrentView);
break; break;
} }
case AS_VIEW_AFFINE_TRANSLATE:
{
double x, y;
link.Read<double>(&x);
link.Read<double>(&y);
picture->WriteTranslateBy(x, y);
break;
}
case AS_VIEW_AFFINE_SCALE:
{
double x, y;
link.Read<double>(&x);
link.Read<double>(&y);
picture->WriteScaleBy(x, y);
break;
}
case AS_VIEW_AFFINE_ROTATE:
{
double angleRadians;
link.Read<double>(&angleRadians);
picture->WriteRotateBy(angleRadians);
break;
}
case AS_VIEW_SET_PATTERN: case AS_VIEW_SET_PATTERN:
{ {
pattern pat; pattern pat;
@@ -322,6 +322,13 @@ DrawingEngine::SetFont(const DrawState* state)
} }
void
DrawingEngine::SetTransform(const BAffineTransform& transform)
{
fPainter->SetTransform(transform);
}
// #pragma mark - // #pragma mark -
+1
View File
@@ -86,6 +86,7 @@ public:
alpha_function alphaFunc); alpha_function alphaFunc);
virtual void SetFont(const ServerFont& font); virtual void SetFont(const ServerFont& font);
virtual void SetFont(const DrawState* state); virtual void SetFont(const DrawState* state);
virtual void SetTransform(const BAffineTransform& transform);
void SuspendAutoSync(); void SuspendAutoSync();
void Sync(); void Sync();