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:
@@ -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();
|
||||||
|
|||||||
@@ -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[],
|
||||||
|
|||||||
@@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 -
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user