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.
This commit is contained in:
Stephan Aßmus
2014-02-04 22:53:06 +01:00
parent 339a018112
commit a6db6bd40f
12 changed files with 258 additions and 61 deletions
+7
View File
@@ -6,6 +6,7 @@
#define _VIEW_H
#include <AffineTransform.h>
#include <Alignment.h>
#include <Font.h>
#include <Handler.h>
@@ -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();
+4
View File
@@ -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
};
@@ -9,6 +9,7 @@
#define APP_SERVER_PROTOCOL_STRUCTS_H
#include <AffineTransform.h>
#include <Rect.h>
@@ -21,6 +22,7 @@ struct ViewSetStateInfo {
drawing_mode drawingMode;
BPoint origin;
float scale;
BAffineTransform transform;
join_mode lineJoin;
cap_mode lineCap;
float miterLimit;
@@ -9,6 +9,7 @@
#define _PICTURE_DATA_WRITER_H
#include <AffineTransform.h>
#include <InterfaceDefs.h>
#include <Font.h>
#include <OS.h>
@@ -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 &region);
status_t WriteClearClipping();
+26 -25
View File
@@ -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
+6 -3
View File
@@ -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;
+14
View File
@@ -157,6 +157,20 @@ PictureDataWriter::WriteSetScale(const float &scale)
}
status_t
PictureDataWriter::WriteSetTransform(BAffineTransform transform)
{
try {
BeginOp(B_PIC_SET_TRANSFORM);
Write<BAffineTransform>(transform);
EndOp();
} catch (status_t &status) {
return status;
}
return B_OK;
}
status_t
PictureDataWriter::WriteSetPattern(const pattern &pat)
{
+14 -2
View File
@@ -10,16 +10,19 @@
/** PicturePlayer is used to play picture data. */
#include <PicturePlayer.h>
#include <stdio.h>
#include <string.h>
#include <PicturePlayer.h>
#include <AffineTransform.h>
#include <PictureProtocol.h>
#include <Shape.h>
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<const BAffineTransform *>(data));
break;
}
default:
break;
}
+65 -10
View File
@@ -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<BPoint>(&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<float>(&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<BAffineTransform>(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<BAffineTransform>(&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<ViewSetLineModeInfo>(&info);
+63 -19
View File
@@ -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);
+10 -1
View File
@@ -12,10 +12,11 @@
#define _DRAW_STATE_H_
#include <AffineTransform.h>
#include <GraphicsDefs.h>
#include <InterfaceDefs.h>
#include <Point.h>
#include <View.h> // for B_FONT_ALL
#include <View.h>
#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;
+45 -1
View File
@@ -1575,6 +1575,36 @@ fDesktop->LockSingleWindow();
fLink.Flush();
break;
}
case AS_VIEW_SET_TRANSFORM:
{
BAffineTransform transform;
if (link.Read<BAffineTransform>(&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<BAffineTransform>(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<float>(&scale);
if (link.Read<float>(&scale) != B_OK)
break;
picture->WriteSetScale(scale);
fCurrentView->SetScale(scale);
_UpdateDrawState(fCurrentView);
break;
}
case AS_VIEW_SET_TRANSFORM:
{
BAffineTransform transform;
if (link.Read<BAffineTransform>(&transform) != B_OK)
break;
picture->WriteSetTransform(transform);
fCurrentView->CurrentState()->SetTransform(transform);
_UpdateDrawState(fCurrentView);
break;
}
case AS_VIEW_SET_PATTERN:
{