implemented a cool vertex transformation pipeline:

* VertexSource virtualizes the AGG "VertexSource" interface
* Transformer is an interface for building pipelines of
  VertexSource objects, each taking the output of the previous
  object and transforming it in some way
* StrokeTransformer is currently the only implementation and
  converts a path into an outline stroke
* PathSource implements the VertexSource interface on top of
  a VectorPath which it converts into an agg::path_storage
  and into an agg::conv_curve<agg::path_storage> to get smooth
  bezier curves
* added VertexSource() to Shape class, which returns the last
  object of the transformation pipeline, it uses a PathSource
  for the root object
* changed IconRenderer to use the new polymorphic VertexSource
  pipeline


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17896 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus
2006-06-21 14:38:13 +00:00
parent 954f408f50
commit 0199e126e2
11 changed files with 348 additions and 35 deletions
+22 -17
View File
@@ -20,6 +20,7 @@ local sourceDirs =
shape shape
shape/commands shape/commands
style style
transformer
; ;
local sourceDir ; local sourceDir ;
@@ -31,48 +32,52 @@ for sourceDir in $(sourceDirs) {
UseLibraryHeaders agg ; UseLibraryHeaders agg ;
Application Icon-O-Matic : Application Icon-O-Matic :
#document # document
Document.cpp Document.cpp
Icon.cpp Icon.cpp
IconRenderer.cpp IconRenderer.cpp
#generic/command # generic/command
Command.cpp Command.cpp
CommandStack.cpp CommandStack.cpp
Selectable.cpp Selectable.cpp
Selection.cpp Selection.cpp
#generic/gui # generic/gui
#generic/gui/panel # generic/gui/panel
#generic/gui/popup_control # generic/gui/popup_control
#generic/gui/scrollview # generic/gui/scrollview
#generic/gui/stateview # generic/gui/stateview
Manipulator.cpp Manipulator.cpp
MultipleManipulatorState.cpp MultipleManipulatorState.cpp
StateView.cpp StateView.cpp
ViewState.cpp ViewState.cpp
#generic/listener # generic/listener
Observable.cpp Observable.cpp
Observer.cpp Observer.cpp
#generic/selection # generic/selection
#generic/support # generic/support
RWLocker.cpp RWLocker.cpp
support.cpp support.cpp
#style # gradient
Style.cpp Gradient.cpp
StyleManager.cpp # shape
#shape
PathContainer.cpp PathContainer.cpp
PathManipulator.cpp PathManipulator.cpp
Shape.cpp Shape.cpp
ShapeContainer.cpp ShapeContainer.cpp
VectorPath.cpp VectorPath.cpp
#shape/commands # shape/commands
AddPointCommand.cpp AddPointCommand.cpp
ChangePointCommand.cpp ChangePointCommand.cpp
InsertPointCommand.cpp InsertPointCommand.cpp
PathCommand.cpp PathCommand.cpp
RemovePointsCommand.cpp RemovePointsCommand.cpp
#gradient # style
Gradient.cpp Style.cpp
StyleManager.cpp
# transformer
PathSource.cpp
StrokeTransformer.cpp
Transformer.cpp
# #
CanvasView.cpp CanvasView.cpp
IconEditorApp.cpp IconEditorApp.cpp
+19 -5
View File
@@ -23,6 +23,7 @@
#include "PathManipulator.h" #include "PathManipulator.h"
#include "Shape.h" #include "Shape.h"
#include "ShapeContainer.h" #include "ShapeContainer.h"
#include "StrokeTransformer.h"
#include "Style.h" #include "Style.h"
#include "StyleManager.h" #include "StyleManager.h"
#include "VectorPath.h" #include "VectorPath.h"
@@ -91,21 +92,34 @@ MainWindow::_Init()
fDocument->Icon()->Paths()->AddPath(path); fDocument->Icon()->Paths()->AddPath(path);
Style* style = new Style(); Style* style1 = new Style();
style->SetColor((rgb_color){ 255, 0, 0, 255 }); style1->SetColor((rgb_color){ 255, 255, 255, 255 });
StyleManager::Default()->AddStyle(style1);
Style* style2 = new Style();
Gradient* gradient = new Gradient(true); Gradient* gradient = new Gradient(true);
gradient->AddColor((rgb_color){ 255, 211, 6, 255 }, 0.0); gradient->AddColor((rgb_color){ 255, 211, 6, 255 }, 0.0);
gradient->AddColor((rgb_color){ 255, 238, 160, 255 }, 0.5); gradient->AddColor((rgb_color){ 255, 238, 160, 255 }, 0.5);
gradient->AddColor((rgb_color){ 208, 43, 92, 255 }, 1.0); gradient->AddColor((rgb_color){ 208, 43, 92, 255 }, 1.0);
style->SetGradient(gradient); style2->SetGradient(gradient);
StyleManager::Default()->AddStyle(style); StyleManager::Default()->AddStyle(style2);
Shape* shape = new Shape(style); Shape* shape = new Shape(style2);
shape->Paths()->AddPath(path); shape->Paths()->AddPath(path);
fDocument->Icon()->Shapes()->AddShape(shape); fDocument->Icon()->Shapes()->AddShape(shape);
shape = new Shape(style1);
shape->Paths()->AddPath(path);
StrokeTransformer* transformer
= new StrokeTransformer(shape->VertexSource());
transformer->width(5.0);
shape->AppendTransformer(transformer);
fDocument->Icon()->Shapes()->AddShape(shape);
PathManipulator* pathManipulator = new PathManipulator(path); PathManipulator* pathManipulator = new PathManipulator(path);
state->AddManipulator(pathManipulator); state->AddManipulator(pathManipulator);
// ---- // ----
@@ -13,7 +13,6 @@
#include <Bitmap.h> #include <Bitmap.h>
#include "agg_conv_curve.h"
#include "agg_span_gradient.h" #include "agg_span_gradient.h"
#include "agg_span_interpolator_linear.h" #include "agg_span_interpolator_linear.h"
@@ -254,19 +253,11 @@ IconRenderer::_Render(const BRect& r)
int32 shapeCount = fIcon->Shapes()->CountShapes(); int32 shapeCount = fIcon->Shapes()->CountShapes();
for (int32 s = 0; s < shapeCount; s++) { for (int32 s = 0; s < shapeCount; s++) {
Shape* shape = fIcon->Shapes()->ShapeAtFast(s); Shape* shape = fIcon->Shapes()->ShapeAtFast(s);
agg::path_storage aggPath;
int32 pathCount = shape->Paths()->CountPaths();
for (int32 p = 0; p < pathCount; p++) {
VectorPath* path = shape->Paths()->PathAtFast(p);
agg::path_storage subPath;
if (path->GetAGGPathStorage(subPath)) {
aggPath.concat_path(subPath);
}
}
int32 styleIndex = fStyles->IndexOf(shape->Style()); int32 styleIndex = fStyles->IndexOf(shape->Style());
fRasterizer.styles(styleIndex, -1); fRasterizer.styles(styleIndex, -1);
agg::conv_curve<agg::path_storage> curve(aggPath);
fRasterizer.add_path(curve); fRasterizer.add_path(shape->VertexSource());
} }
StyleHandler styleHandler(fStyles, fGammaTable); StyleHandler styleHandler(fStyles, fGammaTable);
+38 -1
View File
@@ -14,7 +14,9 @@ Shape::Shape(::Style* style)
Referenceable(), Referenceable(),
PathContainerListener(), PathContainerListener(),
fPaths(new (nothrow) PathContainer()), fPaths(new (nothrow) PathContainer()),
fStyle(style) fStyle(style),
fPathSource(fPaths),
fTransformers(4)
{ {
if (fPaths) if (fPaths)
fPaths->AddListener(this); fPaths->AddListener(this);
@@ -26,6 +28,10 @@ Shape::Shape(::Style* style)
// destructor // destructor
Shape::~Shape() Shape::~Shape()
{ {
int32 count = fTransformers.CountItems();
for (int32 i = 0; i < count; i++)
delete (Transformer*)fTransformers.ItemAtFast(i);
fPaths->MakeEmpty(); fPaths->MakeEmpty();
fPaths->RemoveListener(this); fPaths->RemoveListener(this);
delete fPaths; delete fPaths;
@@ -87,3 +93,34 @@ Shape::Bounds() const
return bounds; return bounds;
} }
// VertexSource
::VertexSource&
Shape::VertexSource()
{
fPathSource.Update();
::VertexSource* source = &fPathSource;
int32 count = fTransformers.CountItems();
for (int32 i = 0; i < count; i++) {
Transformer* t = (Transformer*)fTransformers.ItemAtFast(i);
t->SetSource(*source);
source = t;
}
return *source;
}
// AppendTransformer
bool
Shape::AppendTransformer(Transformer* transformer)
{
if (!transformer)
return false;
if (!fTransformers.AddItem((void*)transformer))
return false;
Notify();
return true;
}
+9
View File
@@ -1,10 +1,12 @@
#ifndef SHAPE_H #ifndef SHAPE_H
#define SHAPE_H #define SHAPE_H
#include <List.h>
#include <Rect.h> #include <Rect.h>
#include "Observable.h" #include "Observable.h"
#include "PathContainer.h" #include "PathContainer.h"
#include "PathSource.h"
#include "Referenceable.h" #include "Referenceable.h"
class Style; class Style;
@@ -32,9 +34,16 @@ class Shape : public Observable,
BRect Bounds() const; BRect Bounds() const;
::VertexSource& VertexSource();
bool AppendTransformer(
Transformer* transformer);
private: private:
PathContainer* fPaths; PathContainer* fPaths;
::Style* fStyle; ::Style* fStyle;
PathSource fPathSource;
BList fTransformers;
}; };
#endif // SHAPE_H #endif // SHAPE_H
@@ -0,0 +1,54 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#include "PathSource.h"
#include "PathContainer.h"
#include "VectorPath.h"
// constructor
PathSource::PathSource(PathContainer* paths)
: VertexSource(),
fPaths(paths),
fAGGPath(),
fAGGCurvedPath(fAGGPath)
{
}
// destructor
PathSource::~PathSource()
{
}
// rewind
void
PathSource::rewind(unsigned path_id)
{
fAGGCurvedPath.rewind(path_id);
}
// vertex
unsigned
PathSource::vertex(double* x, double* y)
{
return fAGGCurvedPath.vertex(x, y);
}
// Update
void
PathSource::Update()
{
fAGGPath.remove_all();
int32 count = fPaths->CountPaths();
for (int32 i = 0; i < count; i++) {
VectorPath* path = fPaths->PathAtFast(i);
fAGGPath.start_new_path();
path->GetAGGPathStorage(fAGGPath);
}
}
@@ -0,0 +1,39 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#ifndef PATH_SOURCE_H
#define PATH_SOURCE_H
#include "Transformer.h"
#include "agg_path_storage.h"
#include "agg_conv_curve.h"
class PathContainer;
class VectorPath;
typedef agg::path_storage AGGPath;
typedef agg::conv_curve<AGGPath> AGGCurvedPath;
class PathSource : public VertexSource {
public:
PathSource(PathContainer* paths);
virtual ~PathSource();
virtual void rewind(unsigned path_id);
virtual unsigned vertex(double* x, double* y);
void Update();
private:
PathContainer* fPaths;
AGGPath fAGGPath;
AGGCurvedPath fAGGCurvedPath;
};
#endif // PATH_SOURCE_H
@@ -0,0 +1,44 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#include "StrokeTransformer.h"
// constructor
StrokeTransformer::StrokeTransformer(VertexSource& source)
: Transformer(source),
Stroke(source)
{
}
// destructor
StrokeTransformer::~StrokeTransformer()
{
}
// rewind
void
StrokeTransformer::rewind(unsigned path_id)
{
Stroke::rewind(path_id);
}
// vertex
unsigned
StrokeTransformer::vertex(double* x, double* y)
{
return Stroke::vertex(x, y);
}
// SetSource
void
StrokeTransformer::SetSource(VertexSource& source)
{
Transformer::SetSource(source);
Stroke::attach(source);
}
@@ -0,0 +1,31 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#ifndef STROKE_TRANSFORMER_H
#define STROKE_TRANSFORMER_H
#include "agg_conv_stroke.h"
#include "Transformer.h"
typedef agg::conv_stroke<VertexSource> Stroke;
class StrokeTransformer : public Transformer,
public Stroke {
public:
StrokeTransformer(
VertexSource& source);
virtual ~StrokeTransformer();
virtual void rewind(unsigned path_id);
virtual unsigned vertex(double* x, double* y);
virtual void SetSource(VertexSource& source);
};
#endif // STROKE_TRANSFORMER_H
@@ -0,0 +1,53 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#include "Transformer.h"
// constructor
VertexSource::VertexSource()
{
}
// destructor
VertexSource::~VertexSource()
{
}
// #pragma mark -
// constructor
Transformer::Transformer(VertexSource& source)
: fSource(source)
{
}
// destructor
Transformer::~Transformer()
{
}
// 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;
}
@@ -0,0 +1,36 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#ifndef TRANSFORMER_H
#define TRANSFORMER_H
class VertexSource {
public:
VertexSource();
virtual ~VertexSource();
virtual void rewind(unsigned path_id) = 0;
virtual unsigned vertex(double* x, double* y) = 0;
};
class Transformer : public VertexSource {
public:
Transformer(VertexSource& source);
virtual ~Transformer();
virtual void rewind(unsigned path_id);
virtual unsigned vertex(double* x, double* y);
virtual void SetSource(VertexSource& source);
private:
VertexSource& fSource;
};
#endif // TRANSFORMER_H