Icon-O-Matic: Add perspective transformations
As part of adding perspective transformations, agg_trans_perspective.h was patched to fix a multiple definitions error. This change has been submitted for review to the "upstream" repositories at [1], [2], and [3]. Also includes various other improvements such as VertexSource being split into its own file, code style improvements, and documentation improvements. [1] https://sourceforge.net/p/agg/patches/6/ [2] https://github.com/ghaerr/agg-2.6/pull/9 [3] https://github.com/aggeom/agg-2.6/pull/7 Change-Id: I4bffd2f87354bde10155e23145a232a925be6ff3 Reviewed-on: https://review.haiku-os.org/c/haiku/+/6801 Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
committed by
Adrien Destugues
parent
a1c86e7ada
commit
c6c2c04284
@@ -502,7 +502,7 @@ namespace agg
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
const trans_perspective&
|
||||
inline const trans_perspective&
|
||||
trans_perspective::multiply_inv(const trans_perspective& m)
|
||||
{
|
||||
trans_perspective t = m;
|
||||
@@ -511,7 +511,7 @@ namespace agg
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
const trans_perspective&
|
||||
inline const trans_perspective&
|
||||
trans_perspective::multiply_inv(const trans_affine& m)
|
||||
{
|
||||
trans_affine t = m;
|
||||
@@ -520,7 +520,7 @@ namespace agg
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
const trans_perspective&
|
||||
inline const trans_perspective&
|
||||
trans_perspective::premultiply_inv(const trans_perspective& m)
|
||||
{
|
||||
trans_perspective t = m;
|
||||
@@ -529,7 +529,7 @@ namespace agg
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
const trans_perspective&
|
||||
inline const trans_perspective&
|
||||
trans_perspective::premultiply_inv(const trans_affine& m)
|
||||
{
|
||||
trans_perspective t(m);
|
||||
@@ -697,14 +697,14 @@ namespace agg
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void trans_perspective::translation(double* dx, double* dy) const
|
||||
inline void trans_perspective::translation(double* dx, double* dy) const
|
||||
{
|
||||
*dx = tx;
|
||||
*dy = ty;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void trans_perspective::scaling(double* x, double* y) const
|
||||
inline void trans_perspective::scaling(double* x, double* y) const
|
||||
{
|
||||
double x1 = 0.0;
|
||||
double y1 = 0.0;
|
||||
@@ -719,7 +719,7 @@ namespace agg
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void trans_perspective::scaling_abs(double* x, double* y) const
|
||||
inline void trans_perspective::scaling_abs(double* x, double* y) const
|
||||
{
|
||||
*x = std::sqrt(sx * sx + shx * shx);
|
||||
*y = std::sqrt(shy * shy + sy * sy);
|
||||
|
||||
@@ -95,11 +95,12 @@ Application Icon-O-Matic :
|
||||
|
||||
# icon/transformer
|
||||
AffineTransformer.cpp
|
||||
CompoundStyleTransformer.cpp
|
||||
ContourTransformer.cpp
|
||||
PathSource.cpp
|
||||
PerspectiveTransformer.cpp
|
||||
StrokeTransformer.cpp
|
||||
Transformer.cpp
|
||||
StyleTransformer.cpp
|
||||
TransformerFactory.cpp
|
||||
|
||||
# icon
|
||||
@@ -275,6 +276,9 @@ Application Icon-O-Matic :
|
||||
# transformable
|
||||
CanvasTransformBox.cpp
|
||||
ChannelTransform.cpp
|
||||
PerspectiveBox.cpp
|
||||
PerspectiveBoxStates.cpp
|
||||
PerspectiveCommand.cpp
|
||||
ResetTransformationCommand.cpp
|
||||
TransformBox.cpp
|
||||
TransformBoxStates.cpp
|
||||
@@ -349,6 +353,7 @@ DoCatalogs Icon-O-Matic :
|
||||
RemoveStylesCommand.cpp
|
||||
SetColorCommand.cpp
|
||||
SetGradientCommand.cpp
|
||||
PerspectiveCommand.cpp
|
||||
ResetTransformationCommand.cpp
|
||||
TransformBoxStates.cpp
|
||||
TransformerFactory.cpp
|
||||
|
||||
@@ -59,6 +59,8 @@
|
||||
#include "MessengerSaver.h"
|
||||
#include "NativeSaver.h"
|
||||
#include "PathListView.h"
|
||||
#include "PerspectiveBox.h"
|
||||
#include "PerspectiveTransformer.h"
|
||||
#include "RDefExporter.h"
|
||||
#include "ScrollView.h"
|
||||
#include "SimpleFileSaver.h"
|
||||
@@ -105,6 +107,7 @@ enum {
|
||||
MSG_PATH_SELECTED = 'vpsl',
|
||||
MSG_STYLE_SELECTED = 'stsl',
|
||||
MSG_SHAPE_SELECTED = 'spsl',
|
||||
MSG_TRANSFORMER_SELECTED = 'trsl',
|
||||
|
||||
MSG_SHAPE_RESET_TRANSFORMATION = 'rtsh',
|
||||
MSG_STYLE_RESET_TRANSFORMATION = 'rtst',
|
||||
@@ -562,6 +565,20 @@ case MSG_SHAPE_SELECTED: {
|
||||
fState->AddManipulator(transformBox);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_TRANSFORMER_SELECTED: {
|
||||
Transformer* transformer;
|
||||
if (message->FindPointer("transformer", (void**)&transformer) < B_OK)
|
||||
transformer = NULL;
|
||||
|
||||
fState->DeleteManipulators();
|
||||
PerspectiveTransformer* perspectiveTransformer =
|
||||
dynamic_cast<PerspectiveTransformer*>(transformer);
|
||||
if (perspectiveTransformer != NULL) {
|
||||
PerspectiveBox* transformBox = new (nothrow) PerspectiveBox(
|
||||
fCanvasView, perspectiveTransformer);
|
||||
fState->AddManipulator(transformBox);
|
||||
}
|
||||
}
|
||||
case MSG_RENAME_OBJECT:
|
||||
fPropertyListView->FocusNameProperty();
|
||||
@@ -1087,7 +1104,7 @@ MainWindow::_CreateGUI()
|
||||
fShapeListView = new ShapeListView(BRect(0, 0, splitWidth, 100),
|
||||
"shape list view", new BMessage(MSG_SHAPE_SELECTED), this);
|
||||
fTransformerListView = new TransformerListView(BRect(0, 0, splitWidth, 100),
|
||||
"transformer list view");
|
||||
"transformer list view", new BMessage(MSG_TRANSFORMER_SELECTED), this);
|
||||
fPropertyListView = new IconObjectListView();
|
||||
|
||||
BLayoutBuilder::Split<>(leftSideView)
|
||||
|
||||
@@ -43,6 +43,9 @@ class IconObject : public Observable,
|
||||
const char* Name() const
|
||||
{ return fName.String(); }
|
||||
|
||||
// TODO: let IconObject control its own manipulators?
|
||||
// This would allow VectorPaths to control their own PathManipulator,
|
||||
// Styles to control their own TransformGradientBox, etc.
|
||||
private:
|
||||
BString fName;
|
||||
};
|
||||
|
||||
@@ -201,8 +201,7 @@ TransformerListView::MessageReceived(BMessage* message)
|
||||
break;
|
||||
|
||||
Transformer* transformer
|
||||
= TransformerFactory::TransformerFor(type,
|
||||
fShape->VertexSource());
|
||||
= TransformerFactory::TransformerFor(type, fShape->VertexSource(), fShape);
|
||||
if (!transformer)
|
||||
break;
|
||||
|
||||
@@ -396,9 +395,9 @@ TransformerListView::SetMenu(BMenu* menu)
|
||||
message->AddInt32("type", STROKE_TRANSFORMER);
|
||||
fStrokeMI = new BMenuItem(B_TRANSLATE("Stroke"), message);
|
||||
|
||||
// message = new BMessage(MSG_ADD_TRANSFORMER);
|
||||
// message->AddInt32("type", PERSPECTIVE_TRANSFORMER);
|
||||
// fPerspectiveMI = new BMenuItem(B_TRANSLATE("Perspective"), message);
|
||||
message = new BMessage(MSG_ADD_TRANSFORMER);
|
||||
message->AddInt32("type", PERSPECTIVE_TRANSFORMER);
|
||||
fPerspectiveMI = new BMenuItem(B_TRANSLATE("Perspective"), message);
|
||||
|
||||
// message = new BMessage(MSG_ADD_TRANSFORMER);
|
||||
// message->AddInt32("type", AFFINE_TRANSFORMER);
|
||||
@@ -408,6 +407,7 @@ TransformerListView::SetMenu(BMenu* menu)
|
||||
|
||||
addMenu->AddItem(fContourMI);
|
||||
addMenu->AddItem(fStrokeMI);
|
||||
addMenu->AddItem(fPerspectiveMI);
|
||||
|
||||
addMenu->SetTargetForItems(this);
|
||||
fMenu->AddItem(addMenu);
|
||||
|
||||
@@ -82,6 +82,7 @@ class TransformerListView : public SimpleListView,
|
||||
BMenu* fMenu;
|
||||
BMenuItem* fContourMI;
|
||||
BMenuItem* fStrokeMI;
|
||||
BMenuItem* fPerspectiveMI;
|
||||
};
|
||||
|
||||
#endif // TRANSFORMER_LIST_VIEW_H
|
||||
|
||||
@@ -483,11 +483,17 @@ _WriteTransformer(LittleEndianBuffer& buffer, Transformer* t)
|
||||
|| !buffer.Write(miterLimit))
|
||||
return false;
|
||||
|
||||
} else if (dynamic_cast<PerspectiveTransformer*>(t)) {
|
||||
} else if (PerspectiveTransformer* perspective
|
||||
= dynamic_cast<PerspectiveTransformer*>(t)) {
|
||||
// perspective
|
||||
if (!buffer.Write((uint8)TRANSFORMER_TYPE_PERSPECTIVE))
|
||||
return false;
|
||||
// TODO: ... (upgrade AGG for storage support of trans_perspective)
|
||||
double matrix[9];
|
||||
perspective->store_to(matrix);
|
||||
for (int32 i = 0; i < 9; i++) {
|
||||
if (!write_float_24(buffer, (float)matrix[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (StrokeTransformer* stroke
|
||||
= dynamic_cast<StrokeTransformer*>(t)) {
|
||||
|
||||
@@ -29,7 +29,7 @@ struct style_map {
|
||||
|
||||
/*! Turns text into its associated paths and shapes.
|
||||
Coloring can also be imported from applications, such as StyledEdit, that
|
||||
specify it.
|
||||
specify it in a supported format.
|
||||
*/
|
||||
class StyledTextImporter : public Importer {
|
||||
public:
|
||||
|
||||
@@ -0,0 +1,449 @@
|
||||
/*
|
||||
* Copyright 2006-2009, 2023, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Zardshard
|
||||
*/
|
||||
|
||||
#include "PerspectiveBox.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <agg_trans_affine.h>
|
||||
#include <agg_math.h>
|
||||
|
||||
#include <View.h>
|
||||
|
||||
#include "CanvasView.h"
|
||||
#include "StateView.h"
|
||||
#include "support.h"
|
||||
#include "PerspectiveBoxStates.h"
|
||||
#include "PerspectiveCommand.h"
|
||||
#include "PerspectiveTransformer.h"
|
||||
|
||||
|
||||
#define INSET 8.0
|
||||
|
||||
|
||||
using std::nothrow;
|
||||
using namespace PerspectiveBoxStates;
|
||||
|
||||
|
||||
PerspectiveBox::PerspectiveBox(CanvasView* view,
|
||||
PerspectiveTransformer* parent)
|
||||
:
|
||||
Manipulator(NULL),
|
||||
|
||||
fLeftTop(parent->LeftTop()),
|
||||
fRightTop(parent->RightTop()),
|
||||
fLeftBottom(parent->LeftBottom()),
|
||||
fRightBottom(parent->RightBottom()),
|
||||
|
||||
fCurrentCommand(NULL),
|
||||
fCurrentState(NULL),
|
||||
|
||||
fDragging(false),
|
||||
fMousePos(-10000.0, -10000.0),
|
||||
fModifiers(0),
|
||||
|
||||
fPreviousBox(LONG_MAX, LONG_MAX, LONG_MIN, LONG_MIN),
|
||||
|
||||
fCanvasView(view),
|
||||
fPerspective(parent),
|
||||
|
||||
fDragLTState(new DragCornerState(this, &fLeftTop)),
|
||||
fDragRTState(new DragCornerState(this, &fRightTop)),
|
||||
fDragLBState(new DragCornerState(this, &fLeftBottom)),
|
||||
fDragRBState(new DragCornerState(this, &fRightBottom))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PerspectiveBox::~PerspectiveBox()
|
||||
{
|
||||
_NotifyDeleted();
|
||||
|
||||
delete fCurrentCommand;
|
||||
delete fDragLTState;
|
||||
delete fDragRTState;
|
||||
delete fDragLBState;
|
||||
delete fDragRBState;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PerspectiveBox::Draw(BView* into, BRect updateRect)
|
||||
{
|
||||
// convert to canvas view coordinates
|
||||
BPoint lt = fLeftTop;
|
||||
BPoint rt = fRightTop;
|
||||
BPoint lb = fLeftBottom;
|
||||
BPoint rb = fRightBottom;
|
||||
|
||||
fCanvasView->ConvertFromCanvas(<);
|
||||
fCanvasView->ConvertFromCanvas(&rt);
|
||||
fCanvasView->ConvertFromCanvas(&lb);
|
||||
fCanvasView->ConvertFromCanvas(&rb);
|
||||
|
||||
into->SetDrawingMode(B_OP_COPY);
|
||||
into->SetHighColor(255, 255, 255, 255);
|
||||
into->SetLowColor(0, 0, 0, 255);
|
||||
|
||||
_StrokeBWLine(into, lt, rt);
|
||||
_StrokeBWLine(into, rt, rb);
|
||||
_StrokeBWLine(into, rb, lb);
|
||||
_StrokeBWLine(into, lb, lt);
|
||||
|
||||
_StrokeBWPoint(into, lt, 0.0);
|
||||
_StrokeBWPoint(into, rt, 90.0);
|
||||
_StrokeBWPoint(into, rb, 180.0);
|
||||
_StrokeBWPoint(into, lb, 270.0);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
bool
|
||||
PerspectiveBox::MouseDown(BPoint where)
|
||||
{
|
||||
fCanvasView->FilterMouse(&where);
|
||||
fCanvasView->ConvertToCanvas(&where);
|
||||
|
||||
fDragging = true;
|
||||
if (fCurrentState) {
|
||||
fCurrentState->SetOrigin(where);
|
||||
|
||||
delete fCurrentCommand;
|
||||
fCurrentCommand = new (nothrow) PerspectiveCommand(this, fPerspective,
|
||||
fPerspective->LeftTop(), fPerspective->RightTop(),
|
||||
fPerspective->LeftBottom(), fPerspective->RightBottom());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PerspectiveBox::MouseMoved(BPoint where)
|
||||
{
|
||||
fCanvasView->FilterMouse(&where);
|
||||
fCanvasView->ConvertToCanvas(&where);
|
||||
|
||||
if (fMousePos != where) {
|
||||
fMousePos = where;
|
||||
if (fCurrentState) {
|
||||
fCurrentState->DragTo(fMousePos, fModifiers);
|
||||
fCurrentState->UpdateViewCursor(fCanvasView, fMousePos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Command*
|
||||
PerspectiveBox::MouseUp()
|
||||
{
|
||||
fDragging = false;
|
||||
return FinishTransaction();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
PerspectiveBox::MouseOver(BPoint where)
|
||||
{
|
||||
fCanvasView->ConvertToCanvas(&where);
|
||||
|
||||
fMousePos = where;
|
||||
fCurrentState = _DragStateFor(where, fCanvasView->ZoomLevel());
|
||||
|
||||
if (fCurrentState) {
|
||||
fCurrentState->UpdateViewCursor(fCanvasView, fMousePos);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
BRect
|
||||
PerspectiveBox::Bounds()
|
||||
{
|
||||
// convert from canvas view coordinates
|
||||
BPoint lt = fLeftTop;
|
||||
BPoint rt = fRightTop;
|
||||
BPoint lb = fLeftBottom;
|
||||
BPoint rb = fRightBottom;
|
||||
|
||||
fCanvasView->ConvertFromCanvas(<);
|
||||
fCanvasView->ConvertFromCanvas(&rt);
|
||||
fCanvasView->ConvertFromCanvas(&lb);
|
||||
fCanvasView->ConvertFromCanvas(&rb);
|
||||
|
||||
BRect bounds;
|
||||
bounds.left = min4(lt.x, rt.x, lb.x, rb.x);
|
||||
bounds.top = min4(lt.y, rt.y, lb.y, rb.y);
|
||||
bounds.right = max4(lt.x, rt.x, lb.x, rb.x);
|
||||
bounds.bottom = max4(lt.y, rt.y, lb.y, rb.y);
|
||||
return bounds;
|
||||
}
|
||||
|
||||
|
||||
BRect
|
||||
PerspectiveBox::TrackingBounds(BView* withinView)
|
||||
{
|
||||
return withinView->Bounds();
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
PerspectiveBox::ModifiersChanged(uint32 modifiers)
|
||||
{
|
||||
fModifiers = modifiers;
|
||||
if (fDragging && fCurrentState) {
|
||||
fCurrentState->DragTo(fMousePos, fModifiers);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
PerspectiveBox::UpdateCursor()
|
||||
{
|
||||
if (fCurrentState) {
|
||||
fCurrentState->UpdateViewCursor(fCanvasView, fMousePos);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
PerspectiveBox::AttachedToView(BView* view)
|
||||
{
|
||||
view->Invalidate(Bounds().InsetByCopy(-INSET, -INSET));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PerspectiveBox::DetachedFromView(BView* view)
|
||||
{
|
||||
view->Invalidate(Bounds().InsetByCopy(-INSET, -INSET));
|
||||
}
|
||||
|
||||
|
||||
// pragma mark -
|
||||
|
||||
|
||||
void
|
||||
PerspectiveBox::ObjectChanged(const Observable* object)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// pragma mark -
|
||||
|
||||
|
||||
void
|
||||
PerspectiveBox::TransformTo(
|
||||
BPoint leftTop, BPoint rightTop, BPoint leftBottom, BPoint rightBottom)
|
||||
{
|
||||
if (fLeftTop == leftTop
|
||||
&& fRightTop == rightTop
|
||||
&& fLeftBottom == leftBottom
|
||||
&& fRightBottom == rightBottom)
|
||||
return;
|
||||
|
||||
fLeftTop = leftTop;
|
||||
fRightTop = rightTop;
|
||||
fLeftBottom = leftBottom;
|
||||
fRightBottom = rightBottom;
|
||||
|
||||
Update();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PerspectiveBox::Update(bool deep)
|
||||
{
|
||||
BRect r = Bounds();
|
||||
BRect dirty(r | fPreviousBox);
|
||||
dirty.InsetBy(-INSET, -INSET);
|
||||
fCanvasView->Invalidate(dirty);
|
||||
fPreviousBox = r;
|
||||
|
||||
if (deep)
|
||||
fPerspective->TransformTo(fLeftTop, fRightTop, fLeftBottom, fRightBottom);
|
||||
}
|
||||
|
||||
|
||||
Command*
|
||||
PerspectiveBox::FinishTransaction()
|
||||
{
|
||||
Command* command = fCurrentCommand;
|
||||
if (fCurrentCommand) {
|
||||
fCurrentCommand->SetNewPerspective(
|
||||
fPerspective->LeftTop(), fPerspective->RightTop(),
|
||||
fPerspective->LeftBottom(), fPerspective->RightBottom());
|
||||
fCurrentCommand = NULL;
|
||||
}
|
||||
return command;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
bool
|
||||
PerspectiveBox::AddListener(PerspectiveBoxListener* listener)
|
||||
{
|
||||
if (listener && !fListeners.HasItem((void*)listener))
|
||||
return fListeners.AddItem((void*)listener);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
PerspectiveBox::RemoveListener(PerspectiveBoxListener* listener)
|
||||
{
|
||||
return fListeners.RemoveItem((void*)listener);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
PerspectiveBox::_NotifyDeleted() const
|
||||
{
|
||||
BList listeners(fListeners);
|
||||
int32 count = listeners.CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
PerspectiveBoxListener* listener
|
||||
= (PerspectiveBoxListener*)listeners.ItemAtFast(i);
|
||||
listener->PerspectiveBoxDeleted(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! where is expected in canvas view coordinates
|
||||
DragState*
|
||||
PerspectiveBox::_DragStateFor(BPoint where, float canvasZoom)
|
||||
{
|
||||
DragState* state = NULL;
|
||||
|
||||
// convert to canvas zoom level
|
||||
//
|
||||
// the conversion is necessary, because the "hot regions"
|
||||
// around a point should be the same size no matter what
|
||||
// zoom level the canvas is displayed at
|
||||
float inset = INSET / canvasZoom;
|
||||
|
||||
// check if the cursor is over the corners
|
||||
float dLT = point_point_distance(fLeftTop, where);
|
||||
float dRT = point_point_distance(fRightTop, where);
|
||||
float dLB = point_point_distance(fLeftBottom, where);
|
||||
float dRB = point_point_distance(fRightBottom, where);
|
||||
float d = min4(dLT, dRT, dLB, dRB);
|
||||
if (d < inset) {
|
||||
if (d == dLT)
|
||||
state = fDragLTState;
|
||||
else if (d == dRT)
|
||||
state = fDragRTState;
|
||||
else if (d == dLB)
|
||||
state = fDragLBState;
|
||||
else if (d == dRB)
|
||||
state = fDragRBState;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PerspectiveBox::_StrokeBWLine(BView* into, BPoint from, BPoint to) const
|
||||
{
|
||||
// find out how to offset the second line optimally
|
||||
BPoint offset(0.0, 0.0);
|
||||
// first, do we have a more horizontal line or a more vertical line?
|
||||
float xDiff = to.x - from.x;
|
||||
float yDiff = to.y - from.y;
|
||||
if (fabs(xDiff) > fabs(yDiff)) {
|
||||
// horizontal
|
||||
if (xDiff > 0.0) {
|
||||
offset.y = -1.0;
|
||||
} else {
|
||||
offset.y = 1.0;
|
||||
}
|
||||
} else {
|
||||
// vertical
|
||||
if (yDiff < 0.0) {
|
||||
offset.x = -1.0;
|
||||
} else {
|
||||
offset.x = 1.0;
|
||||
}
|
||||
}
|
||||
// stroke two lines in high and low color of the view
|
||||
into->StrokeLine(from, to, B_SOLID_LOW);
|
||||
from += offset;
|
||||
to += offset;
|
||||
into->StrokeLine(from, to, B_SOLID_HIGH);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PerspectiveBox::_StrokeBWPoint(BView* into, BPoint point, double angle) const
|
||||
{
|
||||
double x = point.x;
|
||||
double y = point.y;
|
||||
|
||||
double x1 = x;
|
||||
double y1 = y - 5.0;
|
||||
|
||||
double x2 = x - 5.0;
|
||||
double y2 = y - 5.0;
|
||||
|
||||
double x3 = x - 5.0;
|
||||
double y3 = y;
|
||||
|
||||
agg::trans_affine m;
|
||||
|
||||
double xOffset = -x;
|
||||
double yOffset = -y;
|
||||
|
||||
agg::trans_affine_rotation r(angle * M_PI / 180.0);
|
||||
|
||||
r.transform(&xOffset, &yOffset);
|
||||
xOffset = x + xOffset;
|
||||
yOffset = y + yOffset;
|
||||
|
||||
m.multiply(r);
|
||||
m.multiply(agg::trans_affine_translation(xOffset, yOffset));
|
||||
|
||||
m.transform(&x, &y);
|
||||
m.transform(&x1, &y1);
|
||||
m.transform(&x2, &y2);
|
||||
m.transform(&x3, &y3);
|
||||
|
||||
BPoint p[4];
|
||||
p[0] = BPoint(x, y);
|
||||
p[1] = BPoint(x1, y1);
|
||||
p[2] = BPoint(x2, y2);
|
||||
p[3] = BPoint(x3, y3);
|
||||
|
||||
into->FillPolygon(p, 4, B_SOLID_HIGH);
|
||||
|
||||
into->StrokeLine(p[0], p[1], B_SOLID_LOW);
|
||||
into->StrokeLine(p[1], p[2], B_SOLID_LOW);
|
||||
into->StrokeLine(p[2], p[3], B_SOLID_LOW);
|
||||
into->StrokeLine(p[3], p[0], B_SOLID_LOW);
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2006-2007, 2023, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Zardshard
|
||||
*/
|
||||
#ifndef PERSPECTIVE_BOX_H
|
||||
#define PERSPECTIVE_BOX_H
|
||||
|
||||
#include <List.h>
|
||||
#include <Point.h>
|
||||
#include <Referenceable.h>
|
||||
|
||||
#include "Manipulator.h"
|
||||
|
||||
|
||||
namespace PerspectiveBoxStates {
|
||||
class DragState;
|
||||
}
|
||||
|
||||
class CanvasView;
|
||||
class Command;
|
||||
class PerspectiveCommand;
|
||||
class PerspectiveBox;
|
||||
class PerspectiveTransformer;
|
||||
|
||||
|
||||
class PerspectiveBoxListener {
|
||||
public:
|
||||
PerspectiveBoxListener() {}
|
||||
virtual ~PerspectiveBoxListener() {}
|
||||
|
||||
virtual void PerspectiveBoxDeleted(
|
||||
const PerspectiveBox* box) = 0;
|
||||
};
|
||||
|
||||
|
||||
class PerspectiveBox : public Manipulator {
|
||||
public:
|
||||
PerspectiveBox(CanvasView* view,
|
||||
PerspectiveTransformer* parent);
|
||||
virtual ~PerspectiveBox();
|
||||
|
||||
// Manipulator interface
|
||||
virtual void Draw(BView* into, BRect updateRect);
|
||||
|
||||
virtual bool MouseDown(BPoint where);
|
||||
virtual void MouseMoved(BPoint where);
|
||||
virtual Command* MouseUp();
|
||||
virtual bool MouseOver(BPoint where);
|
||||
|
||||
virtual BRect Bounds();
|
||||
virtual BRect TrackingBounds(BView* withinView);
|
||||
|
||||
virtual void ModifiersChanged(uint32 modifiers);
|
||||
|
||||
virtual bool UpdateCursor();
|
||||
|
||||
virtual void AttachedToView(BView* view);
|
||||
virtual void DetachedFromView(BView* view);
|
||||
|
||||
// Observer interface
|
||||
virtual void ObjectChanged(const Observable* object);
|
||||
|
||||
// PerspectiveTransformBox
|
||||
void TransformTo(BPoint leftTop, BPoint rightTop,
|
||||
BPoint leftBottom, BPoint rightBottom);
|
||||
|
||||
virtual void Update(bool deep = true);
|
||||
|
||||
Command* FinishTransaction();
|
||||
|
||||
// Listener support
|
||||
bool AddListener(PerspectiveBoxListener* listener);
|
||||
bool RemoveListener(PerspectiveBoxListener* listener);
|
||||
|
||||
private:
|
||||
void _NotifyDeleted() const;
|
||||
PerspectiveBoxStates::DragState* _DragStateFor(
|
||||
BPoint canvasWhere, float canvasZoom);
|
||||
void _StrokeBWLine(BView* into,
|
||||
BPoint from, BPoint to) const;
|
||||
void _StrokeBWPoint(BView* into,
|
||||
BPoint point, double angle) const;
|
||||
|
||||
private:
|
||||
BPoint fLeftTop;
|
||||
BPoint fRightTop;
|
||||
BPoint fLeftBottom;
|
||||
BPoint fRightBottom;
|
||||
|
||||
PerspectiveCommand* fCurrentCommand;
|
||||
PerspectiveBoxStates::DragState* fCurrentState;
|
||||
|
||||
bool fDragging;
|
||||
BPoint fMousePos;
|
||||
uint32 fModifiers;
|
||||
|
||||
BList fListeners;
|
||||
|
||||
BRect fPreviousBox;
|
||||
|
||||
// "static" state objects
|
||||
CanvasView* fCanvasView;
|
||||
BReference<PerspectiveTransformer> fPerspective;
|
||||
|
||||
PerspectiveBoxStates::DragState* fDragLTState;
|
||||
PerspectiveBoxStates::DragState* fDragRTState;
|
||||
PerspectiveBoxStates::DragState* fDragLBState;
|
||||
PerspectiveBoxStates::DragState* fDragRBState;
|
||||
};
|
||||
|
||||
#endif // PERSPECTIVE_BOX_H
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2006-2009, 2023, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Zardshard
|
||||
*/
|
||||
|
||||
#include "PerspectiveBoxStates.h"
|
||||
|
||||
#include <Cursor.h>
|
||||
#include <View.h>
|
||||
|
||||
#include "cursors.h"
|
||||
#include "PerspectiveBox.h"
|
||||
|
||||
|
||||
using namespace PerspectiveBoxStates;
|
||||
|
||||
|
||||
DragState::DragState(PerspectiveBox* parent)
|
||||
:
|
||||
fOrigin(0.0, 0.0),
|
||||
fParent(parent)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DragState::_SetViewCursor(BView* view, const uchar* cursorData) const
|
||||
{
|
||||
BCursor cursor(cursorData);
|
||||
view->SetViewCursor(&cursor);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - DragCornerState
|
||||
|
||||
|
||||
DragCornerState::DragCornerState(PerspectiveBox* parent, BPoint* point)
|
||||
:
|
||||
DragState(parent),
|
||||
fPoint(point)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DragCornerState::SetOrigin(BPoint origin)
|
||||
{
|
||||
DragState::SetOrigin(origin);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DragCornerState::DragTo(BPoint current, uint32 modifiers)
|
||||
{
|
||||
*fPoint = current;
|
||||
fParent->Update(true);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DragCornerState::UpdateViewCursor(BView* view, BPoint current) const
|
||||
{
|
||||
_SetViewCursor(view, kPathMoveCursor);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2006, 2023, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Zardshard
|
||||
*/
|
||||
#ifndef PERSPECTIVE_BOX_STATES_H
|
||||
#define PERSPECTIVE_BOX_STATES_H
|
||||
|
||||
#include <Point.h>
|
||||
|
||||
|
||||
class BView;
|
||||
class PerspectiveBox;
|
||||
|
||||
|
||||
namespace PerspectiveBoxStates {
|
||||
|
||||
class DragState {
|
||||
public:
|
||||
DragState(PerspectiveBox* parent);
|
||||
virtual ~DragState() {}
|
||||
|
||||
virtual void SetOrigin(BPoint origin)
|
||||
{ fOrigin = origin; }
|
||||
virtual void DragTo(BPoint current, uint32 modifiers) = 0;
|
||||
virtual void UpdateViewCursor(BView* view, BPoint current) const = 0;
|
||||
|
||||
protected:
|
||||
void _SetViewCursor(BView* view,
|
||||
const uchar* cursorData) const;
|
||||
|
||||
BPoint fOrigin;
|
||||
PerspectiveBox* fParent;
|
||||
};
|
||||
|
||||
|
||||
class DragCornerState : public DragState {
|
||||
public:
|
||||
DragCornerState(
|
||||
PerspectiveBox* parent, BPoint* point);
|
||||
virtual ~DragCornerState() {}
|
||||
|
||||
virtual void SetOrigin(BPoint origin);
|
||||
virtual void DragTo(BPoint current, uint32 modifiers);
|
||||
virtual void UpdateViewCursor(BView* view, BPoint current) const;
|
||||
|
||||
private:
|
||||
BPoint* fPoint;
|
||||
|
||||
BPoint fOldOffset;
|
||||
};
|
||||
|
||||
} // PerspectiveBoxStates namespace
|
||||
|
||||
#endif // PERSPECTIVE_BOX_STATES_H
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright 2006-2010, Stephan Aßmus <superstippi@gmx.de>.
|
||||
* Copyright 2006-2009, 2023, Haiku.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Zardshard
|
||||
*/
|
||||
|
||||
|
||||
#include "PerspectiveCommand.h"
|
||||
|
||||
#include <Catalog.h>
|
||||
#include <Locale.h>
|
||||
|
||||
#include "PerspectiveTransformer.h"
|
||||
|
||||
|
||||
#undef B_TRANSLATION_CONTEXT
|
||||
#define B_TRANSLATION_CONTEXT "Icon-O-Matic-PerspectiveCommand"
|
||||
|
||||
|
||||
PerspectiveCommand::PerspectiveCommand(PerspectiveBox* box,
|
||||
PerspectiveTransformer* transformer, BPoint leftTop, BPoint rightTop
|
||||
, BPoint leftBottom, BPoint rightBottom)
|
||||
: fTransformBox(box),
|
||||
fTransformer(transformer),
|
||||
fOldLeftTop(leftTop),
|
||||
fOldRightTop(rightTop),
|
||||
fOldLeftBottom(leftBottom),
|
||||
fOldRightBottom(rightBottom),
|
||||
fNewLeftTop(leftTop),
|
||||
fNewRightTop(rightTop),
|
||||
fNewLeftBottom(leftBottom),
|
||||
fNewRightBottom(rightBottom)
|
||||
{
|
||||
if (fTransformer == NULL)
|
||||
return;
|
||||
|
||||
fTransformer->AcquireReference();
|
||||
|
||||
if (fTransformBox != NULL)
|
||||
fTransformBox->AddListener(this);
|
||||
}
|
||||
|
||||
|
||||
PerspectiveCommand::~PerspectiveCommand()
|
||||
{
|
||||
if (fTransformer != NULL)
|
||||
fTransformer->ReleaseReference();
|
||||
|
||||
if (fTransformBox != NULL)
|
||||
fTransformBox->RemoveListener(this);
|
||||
}
|
||||
|
||||
|
||||
// pragma mark -
|
||||
|
||||
|
||||
status_t
|
||||
PerspectiveCommand::InitCheck()
|
||||
{
|
||||
if (fTransformer != NULL
|
||||
&& (fOldLeftTop != fNewLeftTop
|
||||
|| fOldRightTop != fNewRightTop
|
||||
|| fOldLeftBottom != fNewLeftBottom
|
||||
|| fOldRightBottom != fNewRightBottom))
|
||||
return B_OK;
|
||||
|
||||
return B_NO_INIT;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PerspectiveCommand::Perform()
|
||||
{
|
||||
// objects are already transformed
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PerspectiveCommand::Undo()
|
||||
{
|
||||
if (fTransformBox != NULL) {
|
||||
fTransformBox->TransformTo(fOldLeftTop, fOldRightTop, fOldLeftBottom, fOldRightBottom);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
fTransformer->TransformTo(fOldLeftTop, fOldRightTop, fOldLeftBottom, fOldRightBottom);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PerspectiveCommand::Redo()
|
||||
{
|
||||
if (fTransformBox != NULL) {
|
||||
fTransformBox->TransformTo(fNewLeftTop, fNewRightTop, fNewLeftBottom, fNewRightBottom);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
fTransformer->TransformTo(fNewLeftTop, fNewRightTop, fNewLeftBottom, fNewRightBottom);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PerspectiveCommand::GetName(BString& name)
|
||||
{
|
||||
name << B_TRANSLATE("Change perspective");
|
||||
}
|
||||
|
||||
|
||||
// pragma mark -
|
||||
|
||||
|
||||
void
|
||||
PerspectiveCommand::PerspectiveBoxDeleted(const PerspectiveBox* box)
|
||||
{
|
||||
if (fTransformBox == box) {
|
||||
if (fTransformBox != NULL)
|
||||
fTransformBox->RemoveListener(this);
|
||||
fTransformBox = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
PerspectiveCommand::SetNewPerspective(
|
||||
BPoint leftTop, BPoint rightTop, BPoint leftBottom, BPoint rightBottom)
|
||||
{
|
||||
fNewLeftTop = leftTop;
|
||||
fNewRightTop = rightTop;
|
||||
fNewLeftBottom = leftBottom;
|
||||
fNewRightBottom = rightBottom;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2006, 2023, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Zardshard
|
||||
*/
|
||||
|
||||
#ifndef PERSPECTIVE_COMMAND_H
|
||||
#define PERSPECTIVE_COMMAND_H
|
||||
|
||||
|
||||
#include <Point.h>
|
||||
|
||||
#include "Command.h"
|
||||
#include "PerspectiveBox.h"
|
||||
|
||||
|
||||
class PerspectiveTransformer;
|
||||
|
||||
|
||||
class PerspectiveCommand : public Command, public PerspectiveBoxListener {
|
||||
public:
|
||||
PerspectiveCommand(PerspectiveBox* box,
|
||||
PerspectiveTransformer* transformer,
|
||||
BPoint leftTop, BPoint rightTop,
|
||||
BPoint leftBottom, BPoint rightBottom);
|
||||
virtual ~PerspectiveCommand();
|
||||
|
||||
// Command interface
|
||||
virtual status_t InitCheck();
|
||||
|
||||
virtual status_t Perform();
|
||||
virtual status_t Undo();
|
||||
virtual status_t Redo();
|
||||
|
||||
virtual void GetName(BString& name);
|
||||
|
||||
// TransformBoxListener interface
|
||||
virtual void PerspectiveBoxDeleted(const PerspectiveBox* box);
|
||||
|
||||
// PerspectiveCommand
|
||||
void SetNewPerspective(
|
||||
BPoint leftTop, BPoint rightTop,
|
||||
BPoint leftBottom, BPoint rightBottom);
|
||||
|
||||
private:
|
||||
PerspectiveBox* fTransformBox;
|
||||
PerspectiveTransformer* fTransformer;
|
||||
|
||||
BPoint fOldLeftTop;
|
||||
BPoint fOldRightTop;
|
||||
BPoint fOldLeftBottom;
|
||||
BPoint fOldRightBottom;
|
||||
|
||||
BPoint fNewLeftTop;
|
||||
BPoint fNewRightTop;
|
||||
BPoint fNewLeftBottom;
|
||||
BPoint fNewRightBottom;
|
||||
};
|
||||
|
||||
#endif // PERSPECTIVE_COMMAND_H
|
||||
@@ -25,17 +25,7 @@
|
||||
#define INSET 8.0
|
||||
|
||||
|
||||
TransformBoxListener::TransformBoxListener()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
TransformBoxListener::~TransformBoxListener()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
using namespace TransformBoxStates;
|
||||
|
||||
|
||||
// constructor
|
||||
@@ -152,7 +142,6 @@ bool
|
||||
TransformBox::MouseDown(BPoint where)
|
||||
{
|
||||
fView->FilterMouse(&where);
|
||||
// NOTE: filter mouse here and in MouseMoved only
|
||||
TransformToCanvas(where);
|
||||
|
||||
fDragging = true;
|
||||
@@ -172,7 +161,6 @@ void
|
||||
TransformBox::MouseMoved(BPoint where)
|
||||
{
|
||||
fView->FilterMouse(&where);
|
||||
// NOTE: filter mouse here and in MouseDown only
|
||||
TransformToCanvas(where);
|
||||
|
||||
if (fMousePos != where) {
|
||||
@@ -236,12 +224,12 @@ TransformBox::Bounds()
|
||||
TransformFromCanvas(rb);
|
||||
TransformFromCanvas(c);
|
||||
|
||||
BRect r;
|
||||
r.left = min5(lt.x, rt.x, lb.x, rb.x, c.x);
|
||||
r.top = min5(lt.y, rt.y, lb.y, rb.y, c.y);
|
||||
r.right = max5(lt.x, rt.x, lb.x, rb.x, c.x);
|
||||
r.bottom = max5(lt.y, rt.y, lb.y, rb.y, c.y);
|
||||
return r;
|
||||
BRect bounds;
|
||||
bounds.left = min5(lt.x, rt.x, lb.x, rb.x, c.x);
|
||||
bounds.top = min5(lt.y, rt.y, lb.y, rb.y, c.y);
|
||||
bounds.right = max5(lt.x, rt.x, lb.x, rb.x, c.x);
|
||||
bounds.bottom = max5(lt.y, rt.y, lb.y, rb.y, c.y);
|
||||
return bounds;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
*/
|
||||
|
||||
#ifndef TRANSFORM_BOX_H
|
||||
#define TRANSFORM_BOX_H
|
||||
|
||||
@@ -14,16 +13,21 @@
|
||||
#include "ChannelTransform.h"
|
||||
#include "Manipulator.h"
|
||||
|
||||
|
||||
namespace TransformBoxStates {
|
||||
class DragState;
|
||||
}
|
||||
|
||||
class Command;
|
||||
class StateView;
|
||||
class DragState;
|
||||
class TransformBox;
|
||||
class TransformCommand;
|
||||
|
||||
|
||||
class TransformBoxListener {
|
||||
public:
|
||||
TransformBoxListener();
|
||||
virtual ~TransformBoxListener();
|
||||
public:
|
||||
TransformBoxListener() {}
|
||||
virtual ~TransformBoxListener() {}
|
||||
|
||||
virtual void TransformBoxDeleted(
|
||||
const TransformBox* box) = 0;
|
||||
@@ -31,9 +35,8 @@ class TransformBoxListener {
|
||||
|
||||
class TransformBox : public ChannelTransform,
|
||||
public Manipulator {
|
||||
public:
|
||||
TransformBox(StateView* view,
|
||||
BRect box);
|
||||
public:
|
||||
TransformBox(StateView* view, BRect box);
|
||||
virtual ~TransformBox();
|
||||
|
||||
// Manipulator interface
|
||||
@@ -49,10 +52,10 @@ class TransformBox : public ChannelTransform,
|
||||
virtual BRect TrackingBounds(BView* withinView);
|
||||
|
||||
virtual void ModifiersChanged(uint32 modifiers);
|
||||
virtual bool HandleKeyDown(uint32 key, uint32 modifiers,
|
||||
Command** _command);
|
||||
virtual bool HandleKeyUp(uint32 key, uint32 modifiers,
|
||||
Command** _command);
|
||||
virtual bool HandleKeyDown(uint32 key,
|
||||
uint32 modifiers, Command** _command);
|
||||
virtual bool HandleKeyUp(uint32 key,
|
||||
uint32 modifiers, Command** _command);
|
||||
|
||||
virtual bool UpdateCursor();
|
||||
|
||||
@@ -90,15 +93,15 @@ class TransformBox : public ChannelTransform,
|
||||
bool AddListener(TransformBoxListener* listener);
|
||||
bool RemoveListener(TransformBoxListener* listener);
|
||||
|
||||
private:
|
||||
DragState* _DragStateFor(BPoint canvasWhere,
|
||||
float canvasZoom);
|
||||
private:
|
||||
TransformBoxStates::DragState* _DragStateFor(
|
||||
BPoint canvasWhere, float canvasZoom);
|
||||
void _StrokeBWLine(BView* into,
|
||||
BPoint from, BPoint to) const;
|
||||
BPoint from, BPoint to) const;
|
||||
void _StrokeBWPoint(BView* into,
|
||||
BPoint point,
|
||||
double angle) const;
|
||||
BPoint point, double angle) const;
|
||||
|
||||
private:
|
||||
BRect fOriginalBox;
|
||||
|
||||
BPoint fLeftTop;
|
||||
@@ -110,7 +113,7 @@ class TransformBox : public ChannelTransform,
|
||||
BPoint fPivotOffset;
|
||||
|
||||
TransformCommand* fCurrentCommand;
|
||||
DragState* fCurrentState;
|
||||
TransformBoxStates::DragState* fCurrentState;
|
||||
|
||||
bool fDragging;
|
||||
BPoint fMousePos;
|
||||
@@ -120,25 +123,25 @@ class TransformBox : public ChannelTransform,
|
||||
|
||||
BList fListeners;
|
||||
|
||||
protected:
|
||||
protected:
|
||||
void _NotifyDeleted() const;
|
||||
|
||||
// "static" state objects
|
||||
StateView* fView;
|
||||
|
||||
DragState* fDragLTState;
|
||||
DragState* fDragRTState;
|
||||
DragState* fDragLBState;
|
||||
DragState* fDragRBState;
|
||||
TransformBoxStates::DragState* fDragLTState;
|
||||
TransformBoxStates::DragState* fDragRTState;
|
||||
TransformBoxStates::DragState* fDragLBState;
|
||||
TransformBoxStates::DragState* fDragRBState;
|
||||
|
||||
DragState* fDragLState;
|
||||
DragState* fDragRState;
|
||||
DragState* fDragTState;
|
||||
DragState* fDragBState;
|
||||
TransformBoxStates::DragState* fDragLState;
|
||||
TransformBoxStates::DragState* fDragRState;
|
||||
TransformBoxStates::DragState* fDragTState;
|
||||
TransformBoxStates::DragState* fDragBState;
|
||||
|
||||
DragState* fRotateState;
|
||||
DragState* fTranslateState;
|
||||
DragState* fOffsetCenterState;
|
||||
TransformBoxStates::DragState* fRotateState;
|
||||
TransformBoxStates::DragState* fTranslateState;
|
||||
TransformBoxStates::DragState* fOffsetCenterState;
|
||||
};
|
||||
|
||||
#endif // TRANSFORM_BOX_H
|
||||
|
||||
@@ -10,17 +10,14 @@
|
||||
#include "TransformBoxStates.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <Catalog.h>
|
||||
#include <Cursor.h>
|
||||
#include <InterfaceDefs.h>
|
||||
#include <Locale.h>
|
||||
#include <View.h>
|
||||
|
||||
#include "cursors.h"
|
||||
#include "support.h"
|
||||
|
||||
#include "TransformBox.h"
|
||||
|
||||
|
||||
@@ -28,6 +25,9 @@
|
||||
#define B_TRANSLATION_CONTEXT "Icon-O-Matic-TransformationBoxStates"
|
||||
|
||||
|
||||
using namespace TransformBoxStates;
|
||||
|
||||
|
||||
DragState::DragState(TransformBox* parent)
|
||||
:
|
||||
fOrigin(0.0, 0.0),
|
||||
@@ -36,13 +36,6 @@ DragState::DragState(TransformBox* parent)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DragState::SetOrigin(BPoint origin)
|
||||
{
|
||||
fOrigin = origin;
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
DragState::ActionName() const
|
||||
{
|
||||
|
||||
@@ -14,16 +14,21 @@
|
||||
|
||||
#include <agg_trans_affine.h>
|
||||
|
||||
|
||||
class BView;
|
||||
class TransformBox;
|
||||
|
||||
|
||||
namespace TransformBoxStates {
|
||||
|
||||
// base class
|
||||
class DragState {
|
||||
public:
|
||||
DragState(TransformBox* parent);
|
||||
virtual ~DragState() {}
|
||||
|
||||
virtual void SetOrigin(BPoint origin);
|
||||
virtual void SetOrigin(BPoint origin)
|
||||
{ fOrigin = origin; }
|
||||
virtual void DragTo(BPoint current, uint32 modifiers) = 0;
|
||||
virtual void UpdateViewCursor(BView* view, BPoint current) const = 0;
|
||||
|
||||
@@ -142,4 +147,6 @@ class OffsetCenterState : public DragState {
|
||||
virtual const char* ActionName() const;
|
||||
};
|
||||
|
||||
} // TransformBoxStates namespace
|
||||
|
||||
#endif // TRANSFORM_BOX_STATES_H
|
||||
|
||||
@@ -52,11 +52,12 @@ BuildPlatformMergeObjectPIC <libbe_build>icon_kit.o :
|
||||
|
||||
# transformer
|
||||
AffineTransformer.cpp
|
||||
CompoundStyleTransformer.cpp
|
||||
ContourTransformer.cpp
|
||||
PathSource.cpp
|
||||
PerspectiveTransformer.cpp
|
||||
StrokeTransformer.cpp
|
||||
Transformer.cpp
|
||||
StyleTransformer.cpp
|
||||
TransformerFactory.cpp
|
||||
|
||||
Icon.cpp
|
||||
|
||||
@@ -50,11 +50,12 @@ BuildPlatformStaticLibrary libicon_build.a :
|
||||
|
||||
# transformer
|
||||
AffineTransformer.cpp
|
||||
CompoundStyleTransformer.cpp
|
||||
ContourTransformer.cpp
|
||||
PathSource.cpp
|
||||
PerspectiveTransformer.cpp
|
||||
StrokeTransformer.cpp
|
||||
Transformer.cpp
|
||||
StyleTransformer.cpp
|
||||
TransformerFactory.cpp
|
||||
|
||||
Icon.cpp
|
||||
|
||||
+210
-112
@@ -20,108 +20,142 @@
|
||||
#include <agg_span_image_filter_rgba.h>
|
||||
#include <agg_span_gradient.h>
|
||||
#include <agg_span_interpolator_linear.h>
|
||||
#include <agg_span_interpolator_trans.h>
|
||||
|
||||
#include "CompoundStyleTransformer.h"
|
||||
#include "GradientTransformable.h"
|
||||
#include "Icon.h"
|
||||
#include "Shape.h"
|
||||
#include "Style.h"
|
||||
#include "StyleTransformer.h"
|
||||
#include "VectorPath.h"
|
||||
|
||||
using std::nothrow;
|
||||
|
||||
class IconRenderer::StyleHandler {
|
||||
struct StyleItem {
|
||||
Style* style;
|
||||
Transformation transformation;
|
||||
const Style* style;
|
||||
StyleTransformer* transformer;
|
||||
};
|
||||
|
||||
public:
|
||||
#ifdef ICON_O_MATIC
|
||||
StyleHandler(::GammaTable& gammaTable, bool showReferences)
|
||||
: fStyles(20),
|
||||
fGammaTable(gammaTable),
|
||||
fShowReferences(showReferences),
|
||||
fTransparent(0, 0, 0, 0),
|
||||
fColor(0, 0, 0, 0)
|
||||
{}
|
||||
StyleHandler(::GammaTable& gammaTable,
|
||||
bool showReferences);
|
||||
#else
|
||||
StyleHandler(::GammaTable& gammaTable)
|
||||
: fStyles(20),
|
||||
fGammaTable(gammaTable),
|
||||
fTransparent(0, 0, 0, 0),
|
||||
fColor(0, 0, 0, 0)
|
||||
{}
|
||||
#endif // ICON_O_MATIC
|
||||
|
||||
~StyleHandler()
|
||||
{
|
||||
int32 count = fStyles.CountItems();
|
||||
for (int32 i = 0; i < count; i++)
|
||||
delete (StyleItem*)fStyles.ItemAtFast(i);
|
||||
}
|
||||
|
||||
bool is_solid(unsigned styleIndex) const
|
||||
{
|
||||
StyleItem* styleItem = (StyleItem*)fStyles.ItemAt(styleIndex);
|
||||
if (!styleItem)
|
||||
return true;
|
||||
|
||||
if (styleItem->style->Gradient())
|
||||
return false;
|
||||
|
||||
#ifdef ICON_O_MATIC
|
||||
if (styleItem->style->Bitmap() && fShowReferences)
|
||||
return false;
|
||||
#endif // ICON_O_MATIC
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const agg::rgba8& color(unsigned styleIndex);
|
||||
|
||||
void generate_span(agg::rgba8* span, int x, int y,
|
||||
unsigned len, unsigned styleIndex);
|
||||
|
||||
bool AddStyle(Style* style, const Transformation& transformation)
|
||||
{
|
||||
if (!style)
|
||||
return false;
|
||||
StyleItem* item = new (nothrow) StyleItem;
|
||||
if (!item)
|
||||
return false;
|
||||
item->style = style;
|
||||
// if the style uses a gradient, the transformation
|
||||
// is based on the gradient transformation
|
||||
if (Gradient* gradient = style->Gradient()) {
|
||||
item->transformation = *gradient;
|
||||
item->transformation.multiply(transformation);
|
||||
} else {
|
||||
item->transformation = transformation;
|
||||
}
|
||||
item->transformation.invert();
|
||||
return fStyles.AddItem((void*)item);
|
||||
}
|
||||
|
||||
private:
|
||||
template<class GradientFunction>
|
||||
void _GenerateGradient(agg::rgba8* span, int x, int y, unsigned len,
|
||||
GradientFunction function, int32 start, int32 end,
|
||||
const agg::rgba8* gradientColors, Transformation& gradientTransform);
|
||||
#ifdef ICON_O_MATIC
|
||||
void _GenerateImage(agg::rgba8* span, int x, int y,
|
||||
unsigned len, Style* style, Transformation& transform);
|
||||
StyleHandler(::GammaTable& gammaTable);
|
||||
#endif
|
||||
|
||||
BList fStyles;
|
||||
::GammaTable& fGammaTable;
|
||||
~StyleHandler();
|
||||
|
||||
bool AddStyle(const Style* style,
|
||||
const Transformable& transformation,
|
||||
const Container<Transformer>* transformers);
|
||||
|
||||
bool is_solid(unsigned styleIndex) const;
|
||||
const agg::rgba8& color(unsigned styleIndex);
|
||||
void generate_span(agg::rgba8* span, int x, int y,
|
||||
unsigned len, unsigned styleIndex);
|
||||
private:
|
||||
StyleTransformer* _MergeTransformers(
|
||||
const Transformable* styleTransformation,
|
||||
const Container<Transformer>* transformers,
|
||||
const Transformable* shapeTransformation);
|
||||
|
||||
template<class GradientFunction>
|
||||
void _GenerateGradient(agg::rgba8* span,
|
||||
int x, int y, unsigned len,
|
||||
GradientFunction function,
|
||||
int32 start, int32 end,
|
||||
const agg::rgba8* gradientColors,
|
||||
StyleTransformer* transformer);
|
||||
#ifdef ICON_O_MATIC
|
||||
bool fShowReferences;
|
||||
void _GenerateImage(agg::rgba8* span,
|
||||
int x, int y, unsigned len,
|
||||
const Style* style,
|
||||
StyleTransformer* transformer);
|
||||
#endif
|
||||
agg::rgba8 fTransparent;
|
||||
agg::rgba8 fColor;
|
||||
|
||||
private:
|
||||
BList fStyles;
|
||||
::GammaTable& fGammaTable;
|
||||
#ifdef ICON_O_MATIC
|
||||
bool fShowReferences;
|
||||
#endif
|
||||
agg::rgba8 fTransparent;
|
||||
agg::rgba8 fColor;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef ICON_O_MATIC
|
||||
IconRenderer::StyleHandler::StyleHandler(::GammaTable& gammaTable, bool showReferences)
|
||||
: fStyles(20),
|
||||
fGammaTable(gammaTable),
|
||||
fShowReferences(showReferences),
|
||||
fTransparent(0, 0, 0, 0),
|
||||
fColor(0, 0, 0, 0)
|
||||
{}
|
||||
#else
|
||||
IconRenderer::StyleHandler::StyleHandler(::GammaTable& gammaTable)
|
||||
: fStyles(20),
|
||||
fGammaTable(gammaTable),
|
||||
fTransparent(0, 0, 0, 0),
|
||||
fColor(0, 0, 0, 0)
|
||||
{}
|
||||
#endif
|
||||
|
||||
|
||||
IconRenderer::StyleHandler::~StyleHandler()
|
||||
{
|
||||
int32 count = fStyles.CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
StyleItem* item = (StyleItem*)fStyles.ItemAtFast(i);
|
||||
delete item->transformer;
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
IconRenderer::StyleHandler::AddStyle(const Style* style,
|
||||
const Transformable& transformation, const Container<Transformer>* transformers)
|
||||
{
|
||||
if (!style)
|
||||
return false;
|
||||
|
||||
StyleItem* item = new (nothrow) StyleItem;
|
||||
if (!item)
|
||||
return false;
|
||||
|
||||
item->style = style;
|
||||
|
||||
item->transformer = _MergeTransformers(style->Gradient(), transformers, &transformation);
|
||||
item->transformer->Invert();
|
||||
|
||||
return fStyles.AddItem((void*)item);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
IconRenderer::StyleHandler::is_solid(unsigned styleIndex) const
|
||||
{
|
||||
StyleItem* styleItem = (StyleItem*)fStyles.ItemAt(styleIndex);
|
||||
if (!styleItem)
|
||||
return true;
|
||||
|
||||
if (styleItem->style->Gradient())
|
||||
return false;
|
||||
|
||||
#ifdef ICON_O_MATIC
|
||||
if (styleItem->style->Bitmap() && fShowReferences)
|
||||
return false;
|
||||
#endif // ICON_O_MATIC
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const agg::rgba8&
|
||||
IconRenderer::StyleHandler::color(unsigned styleIndex)
|
||||
{
|
||||
@@ -164,12 +198,12 @@ IconRenderer::StyleHandler::generate_span(agg::rgba8* span, int x, int y,
|
||||
|
||||
#ifdef ICON_O_MATIC
|
||||
if (styleItem->style->Bitmap()) {
|
||||
_GenerateImage(span, x, y, len, styleItem->style, styleItem->transformation);
|
||||
_GenerateImage(span, x, y, len, styleItem->style, styleItem->transformer);
|
||||
return;
|
||||
}
|
||||
#endif // ICON_O_MATIC
|
||||
|
||||
Style* style = styleItem->style;
|
||||
const Style* style = styleItem->style;
|
||||
Gradient* gradient = style->Gradient();
|
||||
const agg::rgba8* colors = style->GammaCorrectedColors(fGammaTable);
|
||||
|
||||
@@ -177,70 +211,132 @@ IconRenderer::StyleHandler::generate_span(agg::rgba8* span, int x, int y,
|
||||
case GRADIENT_LINEAR: {
|
||||
agg::gradient_x function;
|
||||
_GenerateGradient(span, x, y, len, function, -64, 64, colors,
|
||||
styleItem->transformation);
|
||||
styleItem->transformer);
|
||||
break;
|
||||
}
|
||||
case GRADIENT_CIRCULAR: {
|
||||
agg::gradient_radial function;
|
||||
_GenerateGradient(span, x, y, len, function, 0, 64, colors,
|
||||
styleItem->transformation);
|
||||
styleItem->transformer);
|
||||
break;
|
||||
}
|
||||
case GRADIENT_DIAMOND: {
|
||||
agg::gradient_diamond function;
|
||||
_GenerateGradient(span, x, y, len, function, 0, 64, colors,
|
||||
styleItem->transformation);
|
||||
styleItem->transformer);
|
||||
break;
|
||||
}
|
||||
case GRADIENT_CONIC: {
|
||||
agg::gradient_conic function;
|
||||
_GenerateGradient(span, x, y, len, function, 0, 64, colors,
|
||||
styleItem->transformation);
|
||||
styleItem->transformer);
|
||||
break;
|
||||
}
|
||||
case GRADIENT_XY: {
|
||||
agg::gradient_xy function;
|
||||
_GenerateGradient(span, x, y, len, function, 0, 64, colors,
|
||||
styleItem->transformation);
|
||||
styleItem->transformer);
|
||||
break;
|
||||
}
|
||||
case GRADIENT_SQRT_XY: {
|
||||
agg::gradient_sqrt_xy function;
|
||||
_GenerateGradient(span, x, y, len, function, 0, 64, colors,
|
||||
styleItem->transformation);
|
||||
styleItem->transformer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
StyleTransformer*
|
||||
IconRenderer::StyleHandler::_MergeTransformers(const Transformable* styleTransformation,
|
||||
const Container<Transformer>* transformers, const Transformable* shapeTransformation)
|
||||
{
|
||||
// Figure out how large to make the array
|
||||
int32 count = 0;
|
||||
if (styleTransformation != NULL)
|
||||
count++;
|
||||
for (int i = 0; i < transformers->CountItems(); i++) {
|
||||
if (dynamic_cast<StyleTransformer*>(transformers->ItemAtFast(i)))
|
||||
count++;
|
||||
}
|
||||
count++;
|
||||
|
||||
// Populate the array
|
||||
StyleTransformer** styleTransformers = new (nothrow) StyleTransformer*[count];
|
||||
if (styleTransformers == NULL)
|
||||
return NULL;
|
||||
|
||||
int i = 0;
|
||||
if (styleTransformation != NULL)
|
||||
styleTransformers[i++] = new (nothrow) Transformable(*styleTransformation);
|
||||
for (int j = 0; j < transformers->CountItems(); j++) {
|
||||
Transformer* transformer = transformers->ItemAtFast(j);
|
||||
if (dynamic_cast<StyleTransformer*>(transformer) != NULL) {
|
||||
styleTransformers[i++]
|
||||
= dynamic_cast<StyleTransformer*>(transformer->Clone());
|
||||
}
|
||||
}
|
||||
styleTransformers[i++] = new (nothrow) Transformable(*shapeTransformation);
|
||||
|
||||
CompoundStyleTransformer* styleTransformer
|
||||
= new (nothrow) CompoundStyleTransformer(styleTransformers, count);
|
||||
if (styleTransformer == NULL) {
|
||||
delete[] styleTransformers;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return styleTransformer;
|
||||
}
|
||||
|
||||
|
||||
template<class GradientFunction>
|
||||
void
|
||||
IconRenderer::StyleHandler::_GenerateGradient(agg::rgba8* span, int x, int y,
|
||||
unsigned len, GradientFunction function, int32 start, int32 end,
|
||||
const agg::rgba8* gradientColors, Transformation& gradientTransform)
|
||||
const agg::rgba8* gradientColors, StyleTransformer* transformer)
|
||||
{
|
||||
// TODO: performance could potentially be improved by avoiding recreating
|
||||
// these objects on every span
|
||||
typedef agg::pod_auto_array<agg::rgba8, 256> ColorArray;
|
||||
typedef agg::span_interpolator_linear<> Interpolator;
|
||||
typedef agg::span_gradient<agg::rgba8,
|
||||
Interpolator,
|
||||
GradientFunction,
|
||||
ColorArray> GradientGenerator;
|
||||
|
||||
Interpolator interpolator(gradientTransform);
|
||||
|
||||
ColorArray array(gradientColors);
|
||||
GradientGenerator gradientGenerator(interpolator, function, array,
|
||||
start, end);
|
||||
|
||||
gradientGenerator.generate(span, x, y, len);
|
||||
if (transformer->IsLinear()) {
|
||||
typedef agg::span_interpolator_linear
|
||||
<StyleTransformer> Interpolator;
|
||||
typedef agg::span_gradient<agg::rgba8,
|
||||
Interpolator,
|
||||
GradientFunction,
|
||||
ColorArray> GradientGenerator;
|
||||
|
||||
Interpolator interpolator(*transformer);
|
||||
|
||||
GradientGenerator gradientGenerator(interpolator, function, array,
|
||||
start, end);
|
||||
|
||||
gradientGenerator.generate(span, x, y, len);
|
||||
} else {
|
||||
typedef agg::span_interpolator_trans
|
||||
<StyleTransformer> Interpolator;
|
||||
typedef agg::span_gradient<agg::rgba8,
|
||||
Interpolator,
|
||||
GradientFunction,
|
||||
ColorArray> GradientGenerator;
|
||||
|
||||
Interpolator interpolator(*transformer);
|
||||
|
||||
GradientGenerator gradientGenerator(interpolator, function, array,
|
||||
start, end);
|
||||
|
||||
gradientGenerator.generate(span, x, y, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef ICON_O_MATIC
|
||||
void
|
||||
IconRenderer::StyleHandler::_GenerateImage(agg::rgba8* span, int x, int y,
|
||||
unsigned len, Style* style, Transformation& transform)
|
||||
unsigned len, const Style* style, StyleTransformer* transformer)
|
||||
{
|
||||
// bitmap
|
||||
BBitmap* bbitmap = style->Bitmap();
|
||||
@@ -252,13 +348,16 @@ IconRenderer::StyleHandler::_GenerateImage(agg::rgba8* span, int x, int y,
|
||||
PixelFormat pixf_img(bitmap);
|
||||
|
||||
// image interpolator
|
||||
typedef agg::span_interpolator_linear<> interpolator_type;
|
||||
interpolator_type interpolator(transform);
|
||||
// TODO: performance could be improved by using agg_interpolator_linear
|
||||
// where possible, similar to what _GenerateGradient does.
|
||||
typedef agg::span_interpolator_trans<StyleTransformer>
|
||||
interpolator_type;
|
||||
interpolator_type interpolator(*transformer);
|
||||
|
||||
// image accessor attached to pixel format of bitmap
|
||||
typedef agg::image_accessor_wrap<PixelFormat,
|
||||
agg::wrap_mode_repeat, agg::wrap_mode_repeat> source_type;
|
||||
source_type source(pixf_img);
|
||||
typedef agg::image_accessor_clip<PixelFormat> source_type;
|
||||
agg::rgba8 background(0, 0, 0, 0);
|
||||
source_type source(pixf_img, background);
|
||||
|
||||
// image filter (nearest neighbor)
|
||||
typedef agg::span_image_filter_rgba_nn<
|
||||
@@ -424,7 +523,7 @@ IconRenderer::Demultiply()
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
typedef agg::conv_transform<VertexSource, Transformation> ScaledPath;
|
||||
typedef agg::conv_transform<VertexSource, Transformable> ScaledPath;
|
||||
typedef agg::conv_transform<ScaledPath, HintingTransformer> HintedPath;
|
||||
|
||||
|
||||
@@ -467,11 +566,8 @@ IconRenderer::_Render(const BRect& r)
|
||||
continue;
|
||||
}
|
||||
|
||||
Transformation transform(*shape);
|
||||
Transformable transform(*shape);
|
||||
transform.multiply(fGlobalTransform);
|
||||
// NOTE: this works only because "agg::trans_affine",
|
||||
// "Transformable" and "Transformation" are all the
|
||||
// same thing
|
||||
|
||||
Style* style = shape->Style();
|
||||
if (!style)
|
||||
@@ -483,9 +579,11 @@ IconRenderer::_Render(const BRect& r)
|
||||
Gradient* gradient = style->Gradient();
|
||||
bool styleAdded = false;
|
||||
if (gradient && !gradient->InheritTransformation()) {
|
||||
styleAdded = styleHandler.AddStyle(style, fGlobalTransform);
|
||||
styleAdded = styleHandler.AddStyle(
|
||||
style, fGlobalTransform, NULL);
|
||||
} else {
|
||||
styleAdded = styleHandler.AddStyle(style, transform);
|
||||
styleAdded = styleHandler.AddStyle(
|
||||
style, transform, shape->Transformers());
|
||||
}
|
||||
|
||||
if (!styleAdded) {
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <agg_trans_affine.h>
|
||||
|
||||
#include "IconBuild.h"
|
||||
#include "Transformable.h"
|
||||
|
||||
|
||||
class BBitmap;
|
||||
@@ -47,8 +48,6 @@ typedef agg::span_allocator<agg::rgba8> SpanAllocator;
|
||||
typedef agg::rasterizer_compound_aa
|
||||
<agg::rasterizer_sl_clip_dbl> CompoundRasterizer;
|
||||
|
||||
typedef agg::trans_affine Transformation;
|
||||
|
||||
class IconRenderer {
|
||||
public:
|
||||
IconRenderer(BBitmap* bitmap);
|
||||
@@ -110,7 +109,7 @@ class IconRenderer {
|
||||
|
||||
CompoundRasterizer fRasterizer;
|
||||
|
||||
Transformation fGlobalTransform;
|
||||
Transformable fGlobalTransform;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -59,11 +59,12 @@ for architectureObject in [ MultiArchSubDirSetup ] {
|
||||
|
||||
# transformer
|
||||
AffineTransformer.cpp
|
||||
CompoundStyleTransformer.cpp
|
||||
ContourTransformer.cpp
|
||||
PathSource.cpp
|
||||
PerspectiveTransformer.cpp
|
||||
StrokeTransformer.cpp
|
||||
Transformer.cpp
|
||||
StyleTransformer.cpp
|
||||
TransformerFactory.cpp
|
||||
|
||||
Icon.cpp
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
/*
|
||||
* Copyright 2006, Haiku. All rights reserved.
|
||||
* Copyright 2006, 2023, Haiku. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Zardshard
|
||||
*/
|
||||
|
||||
#include "FlatIconImporter.h"
|
||||
@@ -435,7 +436,7 @@ FlatIconImporter::_ParsePaths(LittleEndianBuffer& buffer,
|
||||
|
||||
// _ReadTransformer
|
||||
static Transformer*
|
||||
_ReadTransformer(LittleEndianBuffer& buffer, VertexSource& source)
|
||||
_ReadTransformer(LittleEndianBuffer& buffer, VertexSource& source, Shape* shape)
|
||||
{
|
||||
uint8 transformerType;
|
||||
if (!buffer.Read(transformerType))
|
||||
@@ -479,9 +480,19 @@ _ReadTransformer(LittleEndianBuffer& buffer, VertexSource& source)
|
||||
}
|
||||
case TRANSFORMER_TYPE_PERSPECTIVE: {
|
||||
PerspectiveTransformer* perspective
|
||||
= new (nothrow) PerspectiveTransformer(source);
|
||||
// TODO: upgrade AGG to be able to support storage of
|
||||
// trans_perspective
|
||||
= new (nothrow) PerspectiveTransformer(source, shape);
|
||||
if (!perspective)
|
||||
return NULL;
|
||||
double matrix[9];
|
||||
for (int32 i = 0; i < 9; i++) {
|
||||
float value;
|
||||
if (!read_float_24(buffer, value)) {
|
||||
delete perspective;
|
||||
return NULL;
|
||||
}
|
||||
matrix[i] = value;
|
||||
}
|
||||
perspective->load_from(matrix);
|
||||
return perspective;
|
||||
}
|
||||
case TRANSFORMER_TYPE_STROKE: {
|
||||
@@ -601,7 +612,7 @@ FlatIconImporter::_ReadPathSourceShape(LittleEndianBuffer& buffer,
|
||||
return NULL;
|
||||
for (uint32 i = 0; i < transformerCount; i++) {
|
||||
Transformer* transformer
|
||||
= _ReadTransformer(buffer, shape->VertexSource());
|
||||
= _ReadTransformer(buffer, shape->VertexSource(), shape);
|
||||
if (transformer && !shape->Transformers()->AddItem(transformer)) {
|
||||
delete transformer;
|
||||
return NULL;
|
||||
@@ -651,7 +662,3 @@ FlatIconImporter::_ParseShapes(LittleEndianBuffer& buffer,
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2006-2007, 2023, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Zardshard
|
||||
*/
|
||||
#ifndef VERTEX_SOURCE_H
|
||||
#define VERTEX_SOURCE_H
|
||||
|
||||
|
||||
#include "IconBuild.h"
|
||||
|
||||
|
||||
_BEGIN_ICON_NAMESPACE
|
||||
|
||||
|
||||
class VertexSource {
|
||||
public:
|
||||
VertexSource() {}
|
||||
virtual ~VertexSource() {}
|
||||
|
||||
virtual void rewind(unsigned path_id) = 0;
|
||||
virtual unsigned vertex(double* x, double* y) = 0;
|
||||
|
||||
/*! Determines whether open paths should be closed or left open. */
|
||||
virtual bool WantsOpenPaths() const = 0;
|
||||
virtual double ApproximationScale() const = 0;
|
||||
};
|
||||
|
||||
|
||||
_END_ICON_NAMESPACE
|
||||
|
||||
|
||||
#endif // VERTEX_SOURCE_H
|
||||
@@ -24,6 +24,7 @@
|
||||
# include "PropertyObject.h"
|
||||
#endif // ICON_O_MATIC
|
||||
#include "Container.h"
|
||||
#include "PathTransformer.h"
|
||||
#include "Style.h"
|
||||
#include "TransformerFactory.h"
|
||||
#include "VectorPath.h"
|
||||
@@ -130,7 +131,7 @@ Shape::Shape(const Shape& other)
|
||||
int32 count = other.Transformers()->CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
Transformer* original = other.Transformers()->ItemAtFast(i);
|
||||
Transformer* cloned = original->Clone(fPathSource);
|
||||
Transformer* cloned = original->Clone();
|
||||
if (!fTransformers.AddItem(cloned)) {
|
||||
delete cloned;
|
||||
break;
|
||||
@@ -181,7 +182,7 @@ Shape::Unarchive(BMessage* archive)
|
||||
i++) {
|
||||
Transformer* transformer
|
||||
= TransformerFactory::TransformerFor(
|
||||
&transformerArchive, VertexSource());
|
||||
&transformerArchive, VertexSource(), this);
|
||||
if (!transformer || !fTransformers.AddItem(transformer)) {
|
||||
delete transformer;
|
||||
}
|
||||
@@ -452,9 +453,11 @@ Shape::VertexSource()
|
||||
|
||||
int32 count = fTransformers.CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
Transformer* t = (Transformer*)fTransformers.ItemAtFast(i);
|
||||
t->SetSource(*source);
|
||||
source = t;
|
||||
PathTransformer* t = dynamic_cast<PathTransformer*>(fTransformers.ItemAtFast(i));
|
||||
if (t != NULL) {
|
||||
t->SetSource(*source);
|
||||
source = t;
|
||||
}
|
||||
}
|
||||
|
||||
if (fNeedsUpdate) {
|
||||
|
||||
@@ -86,7 +86,7 @@ class Style {
|
||||
// alpha only applies to bitmaps
|
||||
void SetAlpha(uint8 alpha)
|
||||
{ fAlpha = alpha; Notify(); }
|
||||
uint8 Alpha()
|
||||
uint8 Alpha() const
|
||||
{ return fAlpha; }
|
||||
#endif // ICON_O_MATIC
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
/*
|
||||
* Copyright 2006-2009, Haiku.
|
||||
* Copyright 2006-2009, 2023, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Zardshard
|
||||
*/
|
||||
|
||||
#include "Transformable.h"
|
||||
@@ -11,31 +12,78 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
// constructor
|
||||
|
||||
Transformable::Transformable()
|
||||
: agg::trans_affine()
|
||||
{
|
||||
}
|
||||
|
||||
// copy constructor
|
||||
|
||||
Transformable::Transformable(const Transformable& other)
|
||||
: agg::trans_affine(other)
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
|
||||
Transformable::~Transformable()
|
||||
{
|
||||
}
|
||||
|
||||
// StoreTo
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
Transformable::Invert()
|
||||
{
|
||||
if (!IsIdentity()) {
|
||||
invert();
|
||||
TransformationChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
Transformable::InverseTransform(double* x, double* y) const
|
||||
{
|
||||
inverse_transform(x, y);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Transformable::InverseTransform(BPoint* point) const
|
||||
{
|
||||
if (point) {
|
||||
double x = point->x;
|
||||
double y = point->y;
|
||||
|
||||
inverse_transform(&x, &y);
|
||||
|
||||
point->x = x;
|
||||
point->y = y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BPoint
|
||||
Transformable::InverseTransform(const BPoint& point) const
|
||||
{
|
||||
BPoint p(point);
|
||||
InverseTransform(&p);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Transformable::StoreTo(double matrix[matrix_size]) const
|
||||
{
|
||||
store_to(matrix);
|
||||
}
|
||||
|
||||
// LoadFrom
|
||||
|
||||
void
|
||||
Transformable::LoadFrom(const double matrix[matrix_size])
|
||||
{
|
||||
@@ -50,7 +98,7 @@ Transformable::LoadFrom(const double matrix[matrix_size])
|
||||
}
|
||||
}
|
||||
|
||||
// SetTransform
|
||||
|
||||
void
|
||||
Transformable::SetTransform(const Transformable& other)
|
||||
{
|
||||
@@ -60,7 +108,7 @@ Transformable::SetTransform(const Transformable& other)
|
||||
}
|
||||
}
|
||||
|
||||
// operator=
|
||||
|
||||
Transformable&
|
||||
Transformable::operator=(const Transformable& other)
|
||||
{
|
||||
@@ -72,7 +120,7 @@ Transformable::operator=(const Transformable& other)
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Multiply
|
||||
|
||||
Transformable&
|
||||
Transformable::Multiply(const Transformable& other)
|
||||
{
|
||||
@@ -83,7 +131,7 @@ Transformable::Multiply(const Transformable& other)
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Reset
|
||||
|
||||
void
|
||||
Transformable::Reset()
|
||||
{
|
||||
@@ -93,17 +141,7 @@ Transformable::Reset()
|
||||
}
|
||||
}
|
||||
|
||||
// Invert
|
||||
void
|
||||
Transformable::Invert()
|
||||
{
|
||||
if (!IsIdentity()) {
|
||||
invert();
|
||||
TransformationChanged();
|
||||
}
|
||||
}
|
||||
|
||||
// IsIdentity
|
||||
bool
|
||||
Transformable::IsIdentity() const
|
||||
{
|
||||
@@ -119,7 +157,7 @@ Transformable::IsIdentity() const
|
||||
return false;
|
||||
}
|
||||
|
||||
// IsTranslationOnly
|
||||
|
||||
bool
|
||||
Transformable::IsTranslationOnly() const
|
||||
{
|
||||
@@ -133,7 +171,7 @@ Transformable::IsTranslationOnly() const
|
||||
return false;
|
||||
}
|
||||
|
||||
// IsNotDistorted
|
||||
|
||||
bool
|
||||
Transformable::IsNotDistorted() const
|
||||
{
|
||||
@@ -142,7 +180,7 @@ Transformable::IsNotDistorted() const
|
||||
return (m[0] == m[3]);
|
||||
}
|
||||
|
||||
// IsValid
|
||||
|
||||
bool
|
||||
Transformable::IsValid() const
|
||||
{
|
||||
@@ -151,7 +189,7 @@ Transformable::IsValid() const
|
||||
return ((m[0] * m[3] - m[1] * m[2]) != 0.0);
|
||||
}
|
||||
|
||||
// operator==
|
||||
|
||||
bool
|
||||
Transformable::operator==(const Transformable& other) const
|
||||
{
|
||||
@@ -162,74 +200,13 @@ Transformable::operator==(const Transformable& other) const
|
||||
return memcmp(m1, m2, sizeof(m1)) == 0;
|
||||
}
|
||||
|
||||
// operator!=
|
||||
|
||||
bool
|
||||
Transformable::operator!=(const Transformable& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
// Transform
|
||||
void
|
||||
Transformable::Transform(double* x, double* y) const
|
||||
{
|
||||
transform(x, y);
|
||||
}
|
||||
|
||||
// Transform
|
||||
void
|
||||
Transformable::Transform(BPoint* point) const
|
||||
{
|
||||
if (point) {
|
||||
double x = point->x;
|
||||
double y = point->y;
|
||||
|
||||
transform(&x, &y);
|
||||
|
||||
point->x = x;
|
||||
point->y = y;
|
||||
}
|
||||
}
|
||||
|
||||
// Transform
|
||||
BPoint
|
||||
Transformable::Transform(const BPoint& point) const
|
||||
{
|
||||
BPoint p(point);
|
||||
Transform(&p);
|
||||
return p;
|
||||
}
|
||||
|
||||
// InverseTransform
|
||||
void
|
||||
Transformable::InverseTransform(double* x, double* y) const
|
||||
{
|
||||
inverse_transform(x, y);
|
||||
}
|
||||
|
||||
// InverseTransform
|
||||
void
|
||||
Transformable::InverseTransform(BPoint* point) const
|
||||
{
|
||||
if (point) {
|
||||
double x = point->x;
|
||||
double y = point->y;
|
||||
|
||||
inverse_transform(&x, &y);
|
||||
|
||||
point->x = x;
|
||||
point->y = y;
|
||||
}
|
||||
}
|
||||
|
||||
// InverseTransform
|
||||
BPoint
|
||||
Transformable::InverseTransform(const BPoint& point) const
|
||||
{
|
||||
BPoint p(point);
|
||||
InverseTransform(&p);
|
||||
return p;
|
||||
}
|
||||
|
||||
inline float
|
||||
min4(float a, float b, float c, float d)
|
||||
@@ -237,13 +214,14 @@ min4(float a, float b, float c, float d)
|
||||
return min_c(a, min_c(b, min_c(c, d)));
|
||||
}
|
||||
|
||||
|
||||
inline float
|
||||
max4(float a, float b, float c, float d)
|
||||
{
|
||||
return max_c(a, max_c(b, max_c(c, d)));
|
||||
}
|
||||
|
||||
// TransformBounds
|
||||
|
||||
BRect
|
||||
Transformable::TransformBounds(BRect bounds) const
|
||||
{
|
||||
@@ -253,10 +231,10 @@ Transformable::TransformBounds(BRect bounds) const
|
||||
BPoint lb(bounds.left, bounds.bottom);
|
||||
BPoint rb(bounds.right, bounds.bottom);
|
||||
|
||||
Transform(<);
|
||||
Transform(&rt);
|
||||
Transform(&lb);
|
||||
Transform(&rb);
|
||||
StyleTransformer::Transform(<);
|
||||
StyleTransformer::Transform(&rt);
|
||||
StyleTransformer::Transform(&lb);
|
||||
StyleTransformer::Transform(&rb);
|
||||
|
||||
return BRect(floorf(min4(lt.x, rt.x, lb.x, rb.x)),
|
||||
floorf(min4(lt.y, rt.y, lb.y, rb.y)),
|
||||
@@ -266,7 +244,7 @@ Transformable::TransformBounds(BRect bounds) const
|
||||
return bounds;
|
||||
}
|
||||
|
||||
// TranslateBy
|
||||
|
||||
void
|
||||
Transformable::TranslateBy(BPoint offset)
|
||||
{
|
||||
@@ -276,7 +254,7 @@ Transformable::TranslateBy(BPoint offset)
|
||||
}
|
||||
}
|
||||
|
||||
// RotateBy
|
||||
|
||||
void
|
||||
Transformable::RotateBy(BPoint origin, double degrees)
|
||||
{
|
||||
@@ -288,7 +266,7 @@ Transformable::RotateBy(BPoint origin, double degrees)
|
||||
}
|
||||
}
|
||||
|
||||
// ScaleBy
|
||||
|
||||
void
|
||||
Transformable::ScaleBy(BPoint origin, double xScale, double yScale)
|
||||
{
|
||||
@@ -300,7 +278,7 @@ Transformable::ScaleBy(BPoint origin, double xScale, double yScale)
|
||||
}
|
||||
}
|
||||
|
||||
// ShearBy
|
||||
|
||||
void
|
||||
Transformable::ShearBy(BPoint origin, double xShear, double yShear)
|
||||
{
|
||||
@@ -312,7 +290,7 @@ Transformable::ShearBy(BPoint origin, double xShear, double yShear)
|
||||
}
|
||||
}
|
||||
|
||||
// TransformationChanged
|
||||
|
||||
void
|
||||
Transformable::TransformationChanged()
|
||||
{
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
/*
|
||||
* Copyright 2006, Haiku.
|
||||
* Copyright 2006, 2023, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Zardshard
|
||||
*/
|
||||
|
||||
#ifndef TRANSFORMABLE_H
|
||||
@@ -14,12 +15,17 @@
|
||||
#include <agg_trans_affine.h>
|
||||
|
||||
#include "IconBuild.h"
|
||||
#include "StyleTransformer.h"
|
||||
#include "Transformer.h"
|
||||
|
||||
|
||||
_BEGIN_ICON_NAMESPACE
|
||||
|
||||
|
||||
class Transformable : public agg::trans_affine {
|
||||
/*! The standard affine transformation. */
|
||||
// TODO: combine with AffineTransformer
|
||||
class Transformable : public StyleTransformer,
|
||||
public agg::trans_affine {
|
||||
public:
|
||||
enum {
|
||||
matrix_size = 6,
|
||||
@@ -29,6 +35,18 @@ class Transformable : public agg::trans_affine {
|
||||
Transformable(const Transformable& other);
|
||||
virtual ~Transformable();
|
||||
|
||||
// StyleTransformer interface
|
||||
virtual void transform(double* x, double* y) const
|
||||
{ return agg::trans_affine::transform(x, y); }
|
||||
virtual void Invert();
|
||||
virtual bool IsLinear()
|
||||
{ return true; }
|
||||
|
||||
// Transformable
|
||||
void InverseTransform(double* x, double* y) const;
|
||||
void InverseTransform(BPoint* point) const;
|
||||
BPoint InverseTransform(const BPoint& point) const;
|
||||
|
||||
void StoreTo(double matrix[matrix_size]) const;
|
||||
void LoadFrom(const double matrix[matrix_size]);
|
||||
|
||||
@@ -38,8 +56,6 @@ class Transformable : public agg::trans_affine {
|
||||
Transformable& Multiply(const Transformable& other);
|
||||
virtual void Reset();
|
||||
|
||||
void Invert();
|
||||
|
||||
bool IsIdentity() const;
|
||||
bool IsTranslationOnly() const;
|
||||
bool IsNotDistorted() const;
|
||||
@@ -48,15 +64,6 @@ class Transformable : public agg::trans_affine {
|
||||
bool operator==(const Transformable& other) const;
|
||||
bool operator!=(const Transformable& other) const;
|
||||
|
||||
// transforms coordiantes
|
||||
void Transform(double* x, double* y) const;
|
||||
void Transform(BPoint* point) const;
|
||||
BPoint Transform(const BPoint& point) const;
|
||||
|
||||
void InverseTransform(double* x, double* y) const;
|
||||
void InverseTransform(BPoint* point) const;
|
||||
BPoint InverseTransform(const BPoint& point) const;
|
||||
|
||||
// transforms the rectangle "bounds" and
|
||||
// returns the *bounding box* of that
|
||||
BRect TransformBounds(BRect bounds) const;
|
||||
@@ -82,4 +89,3 @@ _USING_ICON_NAMESPACE
|
||||
|
||||
|
||||
#endif // TRANSFORMABLE_H
|
||||
|
||||
|
||||
@@ -26,7 +26,8 @@ using std::nothrow;
|
||||
|
||||
// constructor
|
||||
AffineTransformer::AffineTransformer(VertexSource& source)
|
||||
: Transformer(source, "Transformation"),
|
||||
: Transformer("Transformation"),
|
||||
PathTransformer(source),
|
||||
Affine(source, *this)
|
||||
{
|
||||
}
|
||||
@@ -34,7 +35,8 @@ AffineTransformer::AffineTransformer(VertexSource& source)
|
||||
// constructor
|
||||
AffineTransformer::AffineTransformer(VertexSource& source,
|
||||
BMessage* archive)
|
||||
: Transformer(source, archive),
|
||||
: Transformer(archive),
|
||||
PathTransformer(source),
|
||||
Affine(source, *this)
|
||||
{
|
||||
if (!archive)
|
||||
@@ -57,9 +59,9 @@ AffineTransformer::~AffineTransformer()
|
||||
|
||||
// Clone
|
||||
Transformer*
|
||||
AffineTransformer::Clone(VertexSource& source) const
|
||||
AffineTransformer::Clone() const
|
||||
{
|
||||
AffineTransformer* clone = new (nothrow) AffineTransformer(source);
|
||||
AffineTransformer* clone = new (nothrow) AffineTransformer(fSource);
|
||||
if (clone)
|
||||
clone->multiply(*this);
|
||||
return clone;
|
||||
@@ -83,7 +85,7 @@ AffineTransformer::vertex(double* x, double* y)
|
||||
void
|
||||
AffineTransformer::SetSource(VertexSource& source)
|
||||
{
|
||||
Transformer::SetSource(source);
|
||||
PathTransformer::SetSource(source);
|
||||
Affine::attach(source);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
|
||||
#include "IconBuild.h"
|
||||
#include "PathTransformer.h"
|
||||
#include "Transformer.h"
|
||||
|
||||
#include <agg_conv_transform.h>
|
||||
@@ -23,6 +24,7 @@ typedef agg::conv_transform<VertexSource,
|
||||
agg::trans_affine> Affine;
|
||||
|
||||
class AffineTransformer : public Transformer,
|
||||
public PathTransformer,
|
||||
public Affine,
|
||||
public agg::trans_affine {
|
||||
public:
|
||||
@@ -38,8 +40,10 @@ class AffineTransformer : public Transformer,
|
||||
|
||||
virtual ~AffineTransformer();
|
||||
|
||||
virtual Transformer* Clone(VertexSource& source) const;
|
||||
// Transformer interface
|
||||
virtual Transformer* Clone() const;
|
||||
|
||||
// PathTransformer interface
|
||||
virtual void rewind(unsigned path_id);
|
||||
virtual unsigned vertex(double* x, double* y);
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2023, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Zardshard
|
||||
*/
|
||||
|
||||
|
||||
#include "CompoundStyleTransformer.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
_USING_ICON_NAMESPACE
|
||||
|
||||
|
||||
CompoundStyleTransformer::CompoundStyleTransformer(
|
||||
StyleTransformer** transformers, int32 count)
|
||||
:
|
||||
fTransformers(transformers),
|
||||
fCount(count)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
CompoundStyleTransformer::~CompoundStyleTransformer()
|
||||
{
|
||||
for (int i = 0; i < fCount; i++)
|
||||
delete fTransformers[i];
|
||||
delete[] fTransformers;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CompoundStyleTransformer::transform(double* x, double* y) const
|
||||
{
|
||||
for (int i = 0; i < fCount; i++) {
|
||||
if (fTransformers[i] != NULL)
|
||||
fTransformers[i]->transform(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CompoundStyleTransformer::Invert()
|
||||
{
|
||||
// reverse order of pipeline
|
||||
StyleTransformer* oldOrder[fCount];
|
||||
memcpy(oldOrder, fTransformers, fCount * sizeof(StyleTransformer*));
|
||||
for (int i = 0; i < fCount; i++) {
|
||||
fTransformers[fCount-i-1] = oldOrder[i];
|
||||
}
|
||||
|
||||
// invert individual transformations
|
||||
for (int i = 0; i < fCount; i++) {
|
||||
if (fTransformers[i] != NULL)
|
||||
fTransformers[i]->Invert();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CompoundStyleTransformer::IsLinear()
|
||||
{
|
||||
bool linear = true;
|
||||
for (int i = 0; i < fCount; i++) {
|
||||
if (fTransformers[i] != NULL)
|
||||
linear &= fTransformers[i]->IsLinear();
|
||||
}
|
||||
return linear;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2023, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Zardshard
|
||||
*/
|
||||
#ifndef COMPOUND_STYLE_TRANSFORMER_H
|
||||
#define COMPOUND_STYLE_TRANSFORMER_H
|
||||
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include "IconBuild.h"
|
||||
#include "StyleTransformer.h"
|
||||
|
||||
|
||||
_BEGIN_ICON_NAMESPACE
|
||||
|
||||
class VertexSource;
|
||||
class StyleTransformer;
|
||||
|
||||
|
||||
/*! Allows turning an array of StyleTransformers into a single StyleTransformer.
|
||||
|
||||
\note This class is not meant to be exposed to the GUI or saved in a file. It
|
||||
is currently only used for rendering.
|
||||
*/
|
||||
class CompoundStyleTransformer : public StyleTransformer {
|
||||
public:
|
||||
CompoundStyleTransformer(
|
||||
StyleTransformer** transformers,
|
||||
int32 count);
|
||||
virtual ~CompoundStyleTransformer();
|
||||
|
||||
// StyleTransformer interface
|
||||
virtual void transform(double* x, double* y) const;
|
||||
virtual void Invert();
|
||||
|
||||
virtual bool IsLinear();
|
||||
|
||||
private:
|
||||
StyleTransformer** fTransformers;
|
||||
int32 fCount;
|
||||
};
|
||||
|
||||
|
||||
_END_ICON_NAMESPACE
|
||||
|
||||
|
||||
#endif // COMPOUND_STYLE_TRANSFORMER_H
|
||||
@@ -27,7 +27,8 @@ using std::nothrow;
|
||||
|
||||
// constructor
|
||||
ContourTransformer::ContourTransformer(VertexSource& source)
|
||||
: Transformer(source, "Contour"),
|
||||
: Transformer("Contour"),
|
||||
PathTransformer(source),
|
||||
Contour(source)
|
||||
{
|
||||
auto_detect_orientation(true);
|
||||
@@ -36,7 +37,8 @@ ContourTransformer::ContourTransformer(VertexSource& source)
|
||||
// constructor
|
||||
ContourTransformer::ContourTransformer(VertexSource& source,
|
||||
BMessage* archive)
|
||||
: Transformer(source, archive),
|
||||
: Transformer(archive),
|
||||
PathTransformer(source),
|
||||
Contour(source)
|
||||
{
|
||||
auto_detect_orientation(true);
|
||||
@@ -69,9 +71,9 @@ ContourTransformer::~ContourTransformer()
|
||||
|
||||
// Clone
|
||||
Transformer*
|
||||
ContourTransformer::Clone(VertexSource& source) const
|
||||
ContourTransformer::Clone() const
|
||||
{
|
||||
ContourTransformer* clone = new (nothrow) ContourTransformer(source);
|
||||
ContourTransformer* clone = new (nothrow) ContourTransformer(fSource);
|
||||
if (clone) {
|
||||
clone->line_join(line_join());
|
||||
clone->inner_join(inner_join());
|
||||
@@ -101,7 +103,7 @@ ContourTransformer::vertex(double* x, double* y)
|
||||
void
|
||||
ContourTransformer::SetSource(VertexSource& source)
|
||||
{
|
||||
Transformer::SetSource(source);
|
||||
PathTransformer::SetSource(source);
|
||||
Contour::attach(source);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
|
||||
#include "IconBuild.h"
|
||||
#include "PathTransformer.h"
|
||||
#include "Transformer.h"
|
||||
|
||||
#include <agg_conv_contour.h>
|
||||
@@ -21,6 +22,7 @@ _BEGIN_ICON_NAMESPACE
|
||||
typedef agg::conv_contour<VertexSource> Contour;
|
||||
|
||||
class ContourTransformer : public Transformer,
|
||||
public PathTransformer,
|
||||
public Contour {
|
||||
public:
|
||||
enum {
|
||||
@@ -35,10 +37,12 @@ class ContourTransformer : public Transformer,
|
||||
|
||||
virtual ~ContourTransformer();
|
||||
|
||||
virtual Transformer* Clone(VertexSource& source) const;
|
||||
// Transformer interface
|
||||
virtual Transformer* Clone() const;
|
||||
|
||||
// PathTransformer interface
|
||||
virtual void rewind(unsigned path_id);
|
||||
virtual unsigned vertex(double* x, double* y);
|
||||
virtual unsigned vertex(double* x, double* y);
|
||||
|
||||
virtual void SetSource(VertexSource& source);
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2006-2007, 2023, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Zardshard
|
||||
*/
|
||||
#ifndef PATH_TRANSFORMER_H
|
||||
#define PATH_TRANSFORMER_H
|
||||
|
||||
|
||||
#include "IconBuild.h"
|
||||
#include "VertexSource.h"
|
||||
|
||||
|
||||
_BEGIN_ICON_NAMESPACE
|
||||
|
||||
|
||||
/*! A transformation to a VertexSource.
|
||||
It can add points, move them around, turn them to curves, etc.
|
||||
*/
|
||||
class PathTransformer : public VertexSource
|
||||
{
|
||||
public:
|
||||
PathTransformer(VertexSource& source)
|
||||
: fSource(source) {}
|
||||
virtual ~PathTransformer() {}
|
||||
|
||||
// PathTransformer
|
||||
virtual void rewind(unsigned path_id)
|
||||
{ fSource.rewind(path_id); }
|
||||
virtual unsigned vertex(double* x, double* y)
|
||||
{ return fSource.vertex(x, y); }
|
||||
|
||||
virtual void SetSource(VertexSource& source)
|
||||
{ fSource = source; }
|
||||
|
||||
virtual bool WantsOpenPaths() const
|
||||
{ return fSource.WantsOpenPaths(); }
|
||||
virtual double ApproximationScale() const
|
||||
{ return fSource.ApproximationScale(); }
|
||||
|
||||
protected:
|
||||
VertexSource& fSource;
|
||||
};
|
||||
|
||||
|
||||
_END_ICON_NAMESPACE
|
||||
|
||||
#endif // PATH_TRANSFORMER_H
|
||||
@@ -1,108 +1,341 @@
|
||||
/*
|
||||
* Copyright 2006-2007, Haiku.
|
||||
* Copyright 2006-2007, 2023, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Zardshard
|
||||
*/
|
||||
|
||||
|
||||
#include "PerspectiveTransformer.h"
|
||||
|
||||
#ifdef ICON_O_MATIC
|
||||
# include <Message.h>
|
||||
#endif
|
||||
|
||||
#include <new>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <agg_basics.h>
|
||||
#include <agg_bounding_rect.h>
|
||||
#include <Message.h>
|
||||
|
||||
#include "Shape.h"
|
||||
|
||||
|
||||
_USING_ICON_NAMESPACE
|
||||
using std::nothrow;
|
||||
|
||||
|
||||
// constructor
|
||||
PerspectiveTransformer::PerspectiveTransformer(VertexSource& source)
|
||||
: Transformer(source, "Perspective"),
|
||||
Perspective(source, *this)
|
||||
PerspectiveTransformer::PerspectiveTransformer(VertexSource& source, Shape* shape)
|
||||
: Transformer("Perspective"),
|
||||
PathTransformer(source),
|
||||
Perspective(source, *this),
|
||||
fShape(shape)
|
||||
#ifdef ICON_O_MATIC
|
||||
, fInverted(false)
|
||||
#endif
|
||||
{
|
||||
#ifdef ICON_O_MATIC
|
||||
if (fShape != NULL) {
|
||||
fShape->AcquireReference();
|
||||
fShape->AddObserver(this);
|
||||
ObjectChanged(fShape); // finish initialization
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// constructor
|
||||
PerspectiveTransformer::PerspectiveTransformer(VertexSource& source,
|
||||
BMessage* archive)
|
||||
: Transformer(source, archive),
|
||||
Perspective(source, *this)
|
||||
|
||||
PerspectiveTransformer::PerspectiveTransformer(
|
||||
VertexSource& source, Shape* shape, BMessage* archive)
|
||||
: Transformer(archive),
|
||||
PathTransformer(source),
|
||||
Perspective(source, *this),
|
||||
fShape(shape)
|
||||
#ifdef ICON_O_MATIC
|
||||
, fInverted(false)
|
||||
#endif
|
||||
{
|
||||
// TODO: upgrade AGG to be able to use load_from() etc
|
||||
double matrix[9];
|
||||
for (int i = 0; i < 9; i++) {
|
||||
if (archive->FindDouble("matrix", i, &matrix[i]) != B_OK)
|
||||
matrix[i] = 0;
|
||||
}
|
||||
load_from(matrix);
|
||||
|
||||
#ifdef ICON_O_MATIC
|
||||
if (fShape != NULL) {
|
||||
fShape->AcquireReference();
|
||||
fShape->AddObserver(this);
|
||||
ObjectChanged(fShape); // finish initialization
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// destructor
|
||||
|
||||
PerspectiveTransformer::PerspectiveTransformer(const PerspectiveTransformer& other)
|
||||
#ifdef ICON_O_MATIC
|
||||
: Transformer(other.Name()),
|
||||
#else
|
||||
: Transformer(""),
|
||||
#endif
|
||||
PathTransformer(other.fSource),
|
||||
Perspective(fSource, *this),
|
||||
fShape(other.fShape)
|
||||
#ifdef ICON_O_MATIC
|
||||
, fInverted(other.fInverted),
|
||||
fFromBox(other.fFromBox),
|
||||
fToLeftTop(other.fToLeftTop),
|
||||
fToRightTop(other.fToRightTop),
|
||||
fToLeftBottom(other.fToLeftBottom),
|
||||
fToRightBottom(other.fToRightBottom),
|
||||
fValid(other.fValid)
|
||||
#endif
|
||||
{
|
||||
double matrix[9];
|
||||
other.store_to(matrix);
|
||||
load_from(matrix);
|
||||
|
||||
#ifdef ICON_O_MATIC
|
||||
if (fShape != NULL) {
|
||||
fShape->AcquireReference();
|
||||
fShape->AddObserver(this);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
PerspectiveTransformer::~PerspectiveTransformer()
|
||||
{
|
||||
}
|
||||
|
||||
// Clone
|
||||
Transformer*
|
||||
PerspectiveTransformer::Clone(VertexSource& source) const
|
||||
{
|
||||
PerspectiveTransformer* clone
|
||||
= new (nothrow) PerspectiveTransformer(source);
|
||||
if (clone) {
|
||||
// TODO: upgrade AGG
|
||||
// clone->multiply(*this);
|
||||
#ifdef ICON_O_MATIC
|
||||
if (fShape != NULL) {
|
||||
fShape->RemoveObserver(this);
|
||||
fShape->ReleaseReference();
|
||||
}
|
||||
return clone;
|
||||
#endif
|
||||
}
|
||||
|
||||
// rewind
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
Transformer*
|
||||
PerspectiveTransformer::Clone() const
|
||||
{
|
||||
return new (nothrow) PerspectiveTransformer(*this);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
PerspectiveTransformer::rewind(unsigned path_id)
|
||||
{
|
||||
Perspective::rewind(path_id);
|
||||
}
|
||||
|
||||
// vertex
|
||||
|
||||
unsigned
|
||||
PerspectiveTransformer::vertex(double* x, double* y)
|
||||
{
|
||||
#ifdef ICON_O_MATIC
|
||||
if (fValid)
|
||||
return Perspective::vertex(x, y);
|
||||
else
|
||||
return agg::path_cmd_stop;
|
||||
#else
|
||||
return Perspective::vertex(x, y);
|
||||
#endif
|
||||
}
|
||||
|
||||
// SetSource
|
||||
|
||||
void
|
||||
PerspectiveTransformer::SetSource(VertexSource& source)
|
||||
{
|
||||
Transformer::SetSource(source);
|
||||
PathTransformer::SetSource(source);
|
||||
Perspective::attach(source);
|
||||
|
||||
#ifdef ICON_O_MATIC
|
||||
ObjectChanged(fShape);
|
||||
#endif
|
||||
}
|
||||
|
||||
// ApproximationScale
|
||||
|
||||
double
|
||||
PerspectiveTransformer::ApproximationScale() const
|
||||
{
|
||||
// TODO: upgrade AGG
|
||||
return fSource.ApproximationScale();// * scale();
|
||||
return fSource.ApproximationScale() * scale();
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
PerspectiveTransformer::Invert()
|
||||
{
|
||||
#ifdef ICON_O_MATIC
|
||||
fInverted = !fInverted;
|
||||
|
||||
// TODO: degenerate matrices may not be adequately handled
|
||||
bool degenerate = !invert();
|
||||
fValid = fValid && !degenerate;
|
||||
#else
|
||||
invert();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
#ifdef ICON_O_MATIC
|
||||
|
||||
// Archive
|
||||
status_t
|
||||
PerspectiveTransformer::Archive(BMessage* into, bool deep) const
|
||||
{
|
||||
status_t ret = Transformer::Archive(into, deep);
|
||||
|
||||
if (ret == B_OK)
|
||||
into->what = archive_code;
|
||||
into->what = archive_code;
|
||||
|
||||
// TODO: upgrade AGG to be able to use store_to()
|
||||
double matrix[9];
|
||||
store_to(matrix);
|
||||
|
||||
for (int i = 0; i < 9; i++) {
|
||||
if (ret == B_OK)
|
||||
ret = into->AddDouble("matrix", matrix[i]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// #prama mark -
|
||||
|
||||
|
||||
void
|
||||
PerspectiveTransformer::ObjectChanged(const Observable* object)
|
||||
{
|
||||
if (fInverted) {
|
||||
printf("calculating the validity or bounding box of an inverted "
|
||||
"perspective transformer is currently unsupported.");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 pathID[1];
|
||||
pathID[0] = 0;
|
||||
double left, top, right, bottom;
|
||||
agg::bounding_rect(fSource, pathID, 0, 1, &left, &top, &right, &bottom);
|
||||
BRect newFromBox = BRect(left, top, right, bottom);
|
||||
|
||||
// Stop if nothing we care about has changed
|
||||
// TODO: Can this be done earlier? It would be nice to avoid having to
|
||||
// recalculate the bounding box before realizing nothing needs to be done.
|
||||
if (fFromBox == newFromBox)
|
||||
return;
|
||||
|
||||
fFromBox = newFromBox;
|
||||
|
||||
_CheckValidity();
|
||||
|
||||
double x = fFromBox.left; double y = fFromBox.top;
|
||||
Transform(&x, &y);
|
||||
fToLeftTop = BPoint(x, y);
|
||||
|
||||
x = fFromBox.right; y = fFromBox.top;
|
||||
Transform(&x, &y);
|
||||
fToRightTop = BPoint(x, y);
|
||||
|
||||
x = fFromBox.left; y = fFromBox.bottom;
|
||||
Transform(&x, &y);
|
||||
fToLeftBottom = BPoint(x, y);
|
||||
|
||||
x = fFromBox.right; y = fFromBox.bottom;
|
||||
Transform(&x, &y);
|
||||
fToRightBottom = BPoint(x, y);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
PerspectiveTransformer::TransformTo(
|
||||
BPoint leftTop, BPoint rightTop, BPoint leftBottom, BPoint rightBottom)
|
||||
{
|
||||
fToLeftTop = leftTop;
|
||||
fToRightTop = rightTop;
|
||||
fToLeftBottom = leftBottom;
|
||||
fToRightBottom = rightBottom;
|
||||
|
||||
double quad[8] = {
|
||||
fToLeftTop.x, fToLeftTop.y,
|
||||
fToRightTop.x, fToRightTop.y,
|
||||
fToRightBottom.x, fToRightBottom.y,
|
||||
fToLeftBottom.x, fToLeftBottom.y
|
||||
};
|
||||
|
||||
if (!fInverted) {
|
||||
rect_to_quad(
|
||||
fFromBox.left, fFromBox.top,
|
||||
fFromBox.right, fFromBox.bottom, quad);
|
||||
} else {
|
||||
quad_to_rect(quad,
|
||||
fFromBox.left, fFromBox.top,
|
||||
fFromBox.right, fFromBox.bottom);
|
||||
}
|
||||
|
||||
_CheckValidity();
|
||||
Notify();
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
PerspectiveTransformer::_CheckValidity()
|
||||
{
|
||||
// Checks that none of the points are too close to the camera. These tend to
|
||||
// lead to very big numbers or a divide by zero error. Also checks that all
|
||||
// points are on the same side of the camera. Transformations with points on
|
||||
// different sides of the camera look weird and tend to cause crashes.
|
||||
|
||||
fValid = true;
|
||||
double w;
|
||||
bool positive;
|
||||
|
||||
if (!fInverted) {
|
||||
w = fFromBox.left * w0 + fFromBox.top * w1 + w2;
|
||||
fValid &= (fabs(w) > 0.00001);
|
||||
positive = w > 0;
|
||||
|
||||
w = fFromBox.right * w0 + fFromBox.top * w1 + w2;
|
||||
fValid &= (fabs(w) > 0.00001);
|
||||
fValid &= (w>0)==positive;
|
||||
|
||||
w = fFromBox.left * w0 + fFromBox.bottom * w1 + w2;
|
||||
fValid &= (fabs(w) > 0.00001);
|
||||
fValid &= (w>0)==positive;
|
||||
|
||||
w = fFromBox.right * w0 + fFromBox.bottom * w1 + w2;
|
||||
fValid &= (fabs(w) > 0.00001);
|
||||
fValid &= (w>0)==positive;
|
||||
} else {
|
||||
w = fToLeftTop.x * w0 + fToLeftTop.y * w1 + w2;
|
||||
fValid &= (fabs(w) > 0.00001);
|
||||
positive = w > 0;
|
||||
|
||||
w = fToRightTop.x * w0 + fToRightTop.y * w1 + w2;
|
||||
fValid &= (fabs(w) > 0.00001);
|
||||
fValid &= (w>0)==positive;
|
||||
|
||||
w = fToLeftBottom.x * w0 + fToLeftBottom.y * w1 + w2;
|
||||
fValid &= (fabs(w) > 0.00001);
|
||||
fValid &= (w>0)==positive;
|
||||
|
||||
w = fToRightBottom.x * w0 + fToRightBottom.y * w1 + w2;
|
||||
fValid &= (fabs(w) > 0.00001);
|
||||
fValid &= (w>0)==positive;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ICON_O_MATIC
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,46 +1,76 @@
|
||||
/*
|
||||
* Copyright 2006-2007, Haiku.
|
||||
* Copyright 2006-2007, 2023, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Zardshard
|
||||
*/
|
||||
#ifndef PERSPECTIVE_TRANSFORMER_H
|
||||
#define PERSPECTIVE_TRANSFORMER_H
|
||||
|
||||
|
||||
#include "IconBuild.h"
|
||||
#include "Transformer.h"
|
||||
#include <Rect.h>
|
||||
#include <Point.h>
|
||||
|
||||
#include <agg_conv_transform.h>
|
||||
#include <agg_trans_perspective.h>
|
||||
|
||||
#include "IconBuild.h"
|
||||
#include "Transformer.h"
|
||||
#ifdef ICON_O_MATIC
|
||||
#include "Observer.h"
|
||||
#endif
|
||||
#include "PathTransformer.h"
|
||||
#include "StyleTransformer.h"
|
||||
#include "VertexSource.h"
|
||||
|
||||
|
||||
_BEGIN_ICON_NAMESPACE
|
||||
|
||||
class Shape;
|
||||
|
||||
typedef agg::conv_transform<VertexSource,
|
||||
agg::trans_perspective> Perspective;
|
||||
|
||||
typedef agg::conv_transform<VertexSource, agg::trans_perspective> Perspective;
|
||||
|
||||
/*! Transforms from the VertexSource's bounding rect to the specified
|
||||
quadrilateral. This class watches out for invalid transformations if
|
||||
\c ICON_O_MATIC is set.
|
||||
*/
|
||||
class PerspectiveTransformer : public Transformer,
|
||||
public PathTransformer,
|
||||
public StyleTransformer,
|
||||
#ifdef ICON_O_MATIC
|
||||
public Observer,
|
||||
#endif
|
||||
public Perspective,
|
||||
public agg::trans_perspective {
|
||||
public:
|
||||
public:
|
||||
enum {
|
||||
archive_code = 'prsp',
|
||||
};
|
||||
|
||||
PerspectiveTransformer(
|
||||
VertexSource& source);
|
||||
/*! Initializes starting with the identity transformation.
|
||||
A valid perspective transformation can be rendered invalid if the shape
|
||||
changes. Listens to \a shape for updates and determines if the
|
||||
transformation is still valid if \c ICON_O_MATIC is set.
|
||||
*/
|
||||
PerspectiveTransformer(
|
||||
VertexSource& source,
|
||||
Shape* shape);
|
||||
PerspectiveTransformer(
|
||||
VertexSource& source,
|
||||
Shape* shape,
|
||||
BMessage* archive);
|
||||
PerspectiveTransformer(
|
||||
const PerspectiveTransformer& other);
|
||||
|
||||
virtual ~PerspectiveTransformer();
|
||||
|
||||
// Transformer interface
|
||||
virtual Transformer* Clone(VertexSource& source) const;
|
||||
virtual Transformer* Clone() const;
|
||||
|
||||
// PathTransformer interface
|
||||
virtual void rewind(unsigned path_id);
|
||||
virtual unsigned vertex(double* x, double* y);
|
||||
|
||||
@@ -48,11 +78,55 @@ class PerspectiveTransformer : public Transformer,
|
||||
|
||||
virtual double ApproximationScale() const;
|
||||
|
||||
// StyleTransformer interface
|
||||
virtual void transform(double* x, double* y) const
|
||||
#ifdef ICON_O_MATIC
|
||||
{ if (fValid) agg::trans_perspective::transform(x, y); }
|
||||
#else
|
||||
{ agg::trans_perspective::transform(x, y); }
|
||||
#endif
|
||||
|
||||
/*! Inverts the perspective transformation.
|
||||
\warning This class can mostly only transform points when inverted. Most
|
||||
other features either have not been tested or are missing.
|
||||
*/
|
||||
virtual void Invert();
|
||||
|
||||
#ifdef ICON_O_MATIC
|
||||
// IconObject interface
|
||||
virtual status_t Archive(BMessage* into,
|
||||
bool deep = true) const;
|
||||
|
||||
// Observer interface
|
||||
virtual void ObjectChanged(const Observable* object);
|
||||
|
||||
// PerspectiveTransformer
|
||||
void TransformTo(BPoint leftTop, BPoint rightTop,
|
||||
BPoint leftBottom, BPoint rightBottom);
|
||||
|
||||
BPoint LeftTop()
|
||||
{ return fToLeftTop; }
|
||||
BPoint RightTop()
|
||||
{ return fToRightTop; }
|
||||
BPoint LeftBottom()
|
||||
{ return fToLeftBottom; }
|
||||
BPoint RightBottom()
|
||||
{ return fToRightBottom; }
|
||||
|
||||
private:
|
||||
void _CheckValidity();
|
||||
#endif // ICON_O_MATIC
|
||||
|
||||
private:
|
||||
Shape* fShape;
|
||||
#ifdef ICON_O_MATIC
|
||||
bool fInverted;
|
||||
BRect fFromBox;
|
||||
BPoint fToLeftTop;
|
||||
BPoint fToRightTop;
|
||||
BPoint fToLeftBottom;
|
||||
BPoint fToRightBottom;
|
||||
bool fValid;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -27,7 +27,8 @@ using std::nothrow;
|
||||
|
||||
// constructor
|
||||
StrokeTransformer::StrokeTransformer(VertexSource& source)
|
||||
: Transformer(source, "Stroke"),
|
||||
: Transformer("Stroke"),
|
||||
PathTransformer(source),
|
||||
Stroke(source)
|
||||
{
|
||||
}
|
||||
@@ -35,7 +36,8 @@ StrokeTransformer::StrokeTransformer(VertexSource& source)
|
||||
// constructor
|
||||
StrokeTransformer::StrokeTransformer(VertexSource& source,
|
||||
BMessage* archive)
|
||||
: Transformer(source, archive),
|
||||
: Transformer(archive),
|
||||
PathTransformer(source),
|
||||
Stroke(source)
|
||||
{
|
||||
if (!archive)
|
||||
@@ -72,9 +74,9 @@ StrokeTransformer::~StrokeTransformer()
|
||||
|
||||
// Clone
|
||||
Transformer*
|
||||
StrokeTransformer::Clone(VertexSource& source) const
|
||||
StrokeTransformer::Clone() const
|
||||
{
|
||||
StrokeTransformer* clone = new (nothrow) StrokeTransformer(source);
|
||||
StrokeTransformer* clone = new (nothrow) StrokeTransformer(fSource);
|
||||
if (clone) {
|
||||
clone->line_cap(line_cap());
|
||||
clone->line_join(line_join());
|
||||
@@ -105,7 +107,7 @@ StrokeTransformer::vertex(double* x, double* y)
|
||||
void
|
||||
StrokeTransformer::SetSource(VertexSource& source)
|
||||
{
|
||||
Transformer::SetSource(source);
|
||||
PathTransformer::SetSource(source);
|
||||
Stroke::attach(source);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
|
||||
#include "IconBuild.h"
|
||||
#include "PathTransformer.h"
|
||||
#include "Transformer.h"
|
||||
|
||||
#include <agg_conv_stroke.h>
|
||||
@@ -21,6 +22,7 @@ _BEGIN_ICON_NAMESPACE
|
||||
typedef agg::conv_stroke<VertexSource> Stroke;
|
||||
|
||||
class StrokeTransformer : public Transformer,
|
||||
public PathTransformer,
|
||||
public Stroke {
|
||||
public:
|
||||
enum {
|
||||
@@ -36,8 +38,9 @@ class StrokeTransformer : public Transformer,
|
||||
virtual ~StrokeTransformer();
|
||||
|
||||
// Transformer interface
|
||||
virtual Transformer* Clone(VertexSource& source) const;
|
||||
virtual Transformer* Clone() const;
|
||||
|
||||
// PathTransformer interface
|
||||
virtual void rewind(unsigned path_id);
|
||||
virtual unsigned vertex(double* x, double* y);
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2023, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Zardshard
|
||||
*/
|
||||
|
||||
#include "StyleTransformer.h"
|
||||
|
||||
#include <Point.h>
|
||||
|
||||
|
||||
_USING_ICON_NAMESPACE
|
||||
|
||||
|
||||
StyleTransformer::~StyleTransformer()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StyleTransformer::Transform(BPoint* point) const
|
||||
{
|
||||
if (point) {
|
||||
double x = point->x;
|
||||
double y = point->y;
|
||||
|
||||
Transform(&x, &y);
|
||||
|
||||
point->x = x;
|
||||
point->y = y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BPoint
|
||||
StyleTransformer::Transform(const BPoint& point) const
|
||||
{
|
||||
BPoint p(point);
|
||||
Transform(&p);
|
||||
return p;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2023, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Zardshard
|
||||
*/
|
||||
#ifndef STYLE_TRANSFORMER_H
|
||||
#define STYLE_TRANSFORMER_H
|
||||
|
||||
|
||||
#include "IconBuild.h"
|
||||
|
||||
|
||||
class BPoint;
|
||||
|
||||
_BEGIN_ICON_NAMESPACE
|
||||
|
||||
|
||||
/*! Warps a shape's style.
|
||||
Implements the same interface as any other class of the agg:trans_ series.
|
||||
This class can be used wherever AGG needs a transformer (for example,
|
||||
agg::span_interpolator_linear<StyleTransformer> is valid).
|
||||
*/
|
||||
class StyleTransformer {
|
||||
public:
|
||||
StyleTransformer() {}
|
||||
virtual ~StyleTransformer();
|
||||
|
||||
/*! Transform a single point of the shape's style.
|
||||
This function should be fast since it will be called many times.
|
||||
|
||||
\note This function is lowercase so that it satisfies the role of an agg
|
||||
transformer
|
||||
*/
|
||||
virtual void transform(double* x, double* y) const = 0;
|
||||
|
||||
/*! Alias of \c transform.
|
||||
Use of this in our code is preffered because it follows the normal
|
||||
capitalization scheme.
|
||||
*/
|
||||
void Transform(double* x, double* y) const
|
||||
{ transform(x, y); }
|
||||
void Transform(BPoint* point) const;
|
||||
BPoint Transform(const BPoint& point) const;
|
||||
|
||||
virtual void Invert() = 0;
|
||||
|
||||
/*! Is the transformation a linear transformation?
|
||||
This allows using linear interpolation instead of calling \c transform
|
||||
for each point. */
|
||||
virtual bool IsLinear()
|
||||
{ return false; }
|
||||
};
|
||||
|
||||
|
||||
_END_ICON_NAMESPACE
|
||||
|
||||
|
||||
#endif // STYLE_TRANSFORMER_H
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Copyright 2006-2007, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
*/
|
||||
|
||||
|
||||
#include "Transformer.h"
|
||||
|
||||
|
||||
_USING_ICON_NAMESPACE
|
||||
|
||||
|
||||
// constructor
|
||||
VertexSource::VertexSource()
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
VertexSource::~VertexSource()
|
||||
{
|
||||
}
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// constructor
|
||||
Transformer::Transformer(VertexSource& source, const char* name)
|
||||
#ifdef ICON_O_MATIC
|
||||
: IconObject(name),
|
||||
#else
|
||||
:
|
||||
#endif
|
||||
fSource(source)
|
||||
{
|
||||
}
|
||||
|
||||
// constructor
|
||||
Transformer::Transformer(VertexSource& source,
|
||||
BMessage* archive)
|
||||
#ifdef ICON_O_MATIC
|
||||
: IconObject(archive),
|
||||
#else
|
||||
:
|
||||
#endif
|
||||
fSource(source)
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
Transformer::~Transformer()
|
||||
{
|
||||
}
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// rewind
|
||||
void
|
||||
Transformer::rewind(unsigned path_id)
|
||||
{
|
||||
fSource.rewind(path_id);
|
||||
}
|
||||
|
||||
// vertex
|
||||
unsigned
|
||||
Transformer::vertex(double* x, double* y)
|
||||
{
|
||||
return fSource.vertex(x, y);
|
||||
}
|
||||
|
||||
// SetSource
|
||||
void
|
||||
Transformer::SetSource(VertexSource& source)
|
||||
{
|
||||
fSource = source;
|
||||
}
|
||||
|
||||
// WantsOpenPaths
|
||||
bool
|
||||
Transformer::WantsOpenPaths() const
|
||||
{
|
||||
return fSource.WantsOpenPaths();
|
||||
}
|
||||
|
||||
// ApproximationScale
|
||||
double
|
||||
Transformer::ApproximationScale() const
|
||||
{
|
||||
return fSource.ApproximationScale();
|
||||
}
|
||||
|
||||
@@ -17,52 +17,35 @@
|
||||
#endif
|
||||
|
||||
#include "IconBuild.h"
|
||||
#include "VertexSource.h"
|
||||
|
||||
|
||||
_BEGIN_ICON_NAMESPACE
|
||||
|
||||
|
||||
class VertexSource {
|
||||
public:
|
||||
VertexSource();
|
||||
virtual ~VertexSource();
|
||||
|
||||
virtual void rewind(unsigned path_id) = 0;
|
||||
virtual unsigned vertex(double* x, double* y) = 0;
|
||||
|
||||
/*! Determines whether open paths should be closed or left open. */
|
||||
virtual bool WantsOpenPaths() const = 0;
|
||||
virtual double ApproximationScale() const = 0;
|
||||
};
|
||||
|
||||
|
||||
/*! Base class for all transformers.
|
||||
All child classes should inherit either PathTransformer, StyleTransformer,
|
||||
or both.
|
||||
*/
|
||||
#ifdef ICON_O_MATIC
|
||||
class Transformer : public VertexSource,
|
||||
public IconObject {
|
||||
class Transformer : public IconObject {
|
||||
#else
|
||||
class Transformer : public VertexSource {
|
||||
class Transformer {
|
||||
#endif
|
||||
public:
|
||||
#ifdef ICON_O_MATIC
|
||||
Transformer(const char* name)
|
||||
: IconObject(name) {}
|
||||
Transformer(BMessage* archive)
|
||||
: IconObject(archive) {}
|
||||
#else
|
||||
Transformer(const char* name) {}
|
||||
Transformer(BMessage* archive) {}
|
||||
#endif
|
||||
public:
|
||||
Transformer(VertexSource& source,
|
||||
const char* name);
|
||||
Transformer(VertexSource& source,
|
||||
BMessage* archive);
|
||||
|
||||
virtual ~Transformer();
|
||||
virtual ~Transformer() {}
|
||||
|
||||
// Transformer
|
||||
virtual Transformer* Clone(VertexSource& source) const = 0;
|
||||
|
||||
virtual void rewind(unsigned path_id);
|
||||
virtual unsigned vertex(double* x, double* y);
|
||||
|
||||
virtual void SetSource(VertexSource& source);
|
||||
|
||||
virtual bool WantsOpenPaths() const;
|
||||
virtual double ApproximationScale() const;
|
||||
|
||||
protected:
|
||||
VertexSource& fSource;
|
||||
virtual Transformer* Clone() const = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "AffineTransformer.h"
|
||||
#include "ContourTransformer.h"
|
||||
#include "PerspectiveTransformer.h"
|
||||
#include "Shape.h"
|
||||
#include "StrokeTransformer.h"
|
||||
|
||||
#ifdef ICON_O_MATIC
|
||||
@@ -24,13 +25,13 @@ _USING_ICON_NAMESPACE
|
||||
|
||||
// TransformerFor
|
||||
Transformer*
|
||||
TransformerFactory::TransformerFor(uint32 type, VertexSource& source)
|
||||
TransformerFactory::TransformerFor(uint32 type, VertexSource& source, Shape* shape)
|
||||
{
|
||||
switch (type) {
|
||||
case AFFINE_TRANSFORMER:
|
||||
return new AffineTransformer(source);
|
||||
case PERSPECTIVE_TRANSFORMER:
|
||||
return new PerspectiveTransformer(source);
|
||||
return new PerspectiveTransformer(source, shape);
|
||||
case CONTOUR_TRANSFORMER:
|
||||
return new ContourTransformer(source);
|
||||
case STROKE_TRANSFORMER:
|
||||
@@ -42,14 +43,13 @@ TransformerFactory::TransformerFor(uint32 type, VertexSource& source)
|
||||
|
||||
// TransformerFor
|
||||
Transformer*
|
||||
TransformerFactory::TransformerFor(BMessage* message,
|
||||
VertexSource& source)
|
||||
TransformerFactory::TransformerFor(BMessage* message, VertexSource& source, Shape* shape)
|
||||
{
|
||||
switch (message->what) {
|
||||
case AffineTransformer::archive_code:
|
||||
return new AffineTransformer(source, message);
|
||||
case PerspectiveTransformer::archive_code:
|
||||
return new PerspectiveTransformer(source, message);
|
||||
return new PerspectiveTransformer(source, shape, message);
|
||||
case ContourTransformer::archive_code:
|
||||
return new ContourTransformer(source, message);
|
||||
case StrokeTransformer::archive_code:
|
||||
|
||||
@@ -20,6 +20,7 @@ class BMessage;
|
||||
_BEGIN_ICON_NAMESPACE
|
||||
|
||||
|
||||
class Shape;
|
||||
class Transformer;
|
||||
class VertexSource;
|
||||
|
||||
@@ -35,10 +36,12 @@ class TransformerFactory {
|
||||
public:
|
||||
|
||||
static Transformer* TransformerFor(uint32 type,
|
||||
VertexSource& source);
|
||||
VertexSource& source,
|
||||
Shape* shape);
|
||||
|
||||
static Transformer* TransformerFor(BMessage* archive,
|
||||
VertexSource& source);
|
||||
VertexSource& source,
|
||||
Shape* shape);
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user