* add more classes:

PathContainer - a list of VectorPath objects
  ShapeContainer - a list of Shape objects
  Icon - the object contains VectorPaths and Shapes using these paths
  IconRenderer - renders an Icon into a BBitmap using AGG compound shape
  rasterization with additional gamma correction
* Shape has a PathContainer instead of a single VectorPath
* Document has an Icon instance
* changed the inheritance of some classes to us Referenceable more


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17873 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus
2006-06-18 19:05:44 +00:00
parent 6ebf703166
commit 3639baa4b0
15 changed files with 849 additions and 32 deletions
+4
View File
@@ -33,6 +33,8 @@ UseLibraryHeaders agg ;
Application Icon-O-Matic :
#document
Document.cpp
Icon.cpp
IconRenderer.cpp
#generic/command
Command.cpp
CommandStack.cpp
@@ -58,8 +60,10 @@ Application Icon-O-Matic :
Style.cpp
StyleManager.cpp
#shape
PathContainer.cpp
PathManipulator.cpp
Shape.cpp
ShapeContainer.cpp
VectorPath.cpp
#shape/commands
AddPointCommand.cpp
@@ -13,6 +13,7 @@
#include <Entry.h>
#include "CommandStack.h"
#include "Icon.h"
#include "Selection.h"
using std::nothrow;
@@ -20,6 +21,7 @@ using std::nothrow;
// constructor
Document::Document(const char* name)
: RWLocker("document rw lock"),
fIcon(new (nothrow) ::Icon()),
fCommandStack(new (nothrow) ::CommandStack()),
fSelection(new (nothrow) ::Selection()),
+8 -3
View File
@@ -16,6 +16,7 @@
struct entry_ref;
class CommandStack;
class Icon;
class Selection;
class Document : public RWLocker {
@@ -23,20 +24,24 @@ class Document : public RWLocker {
Document(const char* name = NULL);
virtual ~Document();
::CommandStack* CommandStack() const
inline ::CommandStack* CommandStack() const
{ return fCommandStack; }
::Selection* Selection() const
inline ::Selection* Selection() const
{ return fSelection; }
void SetName(const char* name);
const char* Name() const;
void SetRef(const entry_ref& ref);
const entry_ref* Ref() const
inline const entry_ref* Ref() const
{ return fRef; }
inline ::Icon* Icon() const
{ return fIcon; }
private:
::Icon* fIcon;
::CommandStack* fCommandStack;
::Selection* fSelection;
+31
View File
@@ -0,0 +1,31 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#include "Icon.h"
#include <new>
#include "PathContainer.h"
#include "ShapeContainer.h"
using std::nothrow;
// constructor
Icon::Icon()
: fPaths(new (nothrow) PathContainer()),
fShapes(new (nothrow) ShapeContainer())
{
}
// destructor
Icon::~Icon()
{
delete fShapes;
delete fPaths;
}
+30
View File
@@ -0,0 +1,30 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#ifndef ICON_H
#define ICON_H
class PathContainer;
class ShapeContainer;
class Icon {
public:
Icon();
virtual ~Icon();
PathContainer* Paths() const
{ return fPaths; }
ShapeContainer* Shapes() const
{ return fShapes; }
private:
PathContainer* fPaths;
ShapeContainer* fShapes;
};
#endif // ICON_H
@@ -0,0 +1,139 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#include "IconRenderer.h"
#include <new>
#include <Bitmap.h>
#include "Icon.h"
#include "Style.h"
#include "StyleManager.h"
using std::nothrow;
class StyleHandler {
public:
StyleHandler(const StyleManager* styles,
GammaTable& gammaTable)
: fStyles(styles),
fGammaTable(gammaTable),
fTransparent(0, 0, 0, 0),
fColor(0, 0, 0, 0)
{}
bool is_solid(unsigned styleIndex) const
{
Style* style = fStyles->StyleAt(styleIndex);
if (!style)
return true;
return style->Gradient() != NULL;
}
const agg::rgba8& color(unsigned styleIndex)
{
Style* style = fStyles->StyleAt(styleIndex);
if (!style)
return fTransparent;
const rgb_color& c = style->Color();
fColor = agg::rgba8(fGammaTable.dir(c.red),
fGammaTable.dir(c.green),
fGammaTable.dir(c.blue),
c.alpha);
fColor.premultiply();
return fColor;
}
void generate_span(agg::rgba8* span, int x, int y,
unsigned len, unsigned styleIndex)
{
// TODO: render gradient of Style at styleIndex into span
}
private:
const StyleManager* fStyles;
GammaTable& fGammaTable;
agg::rgba8 fTransparent;
agg::rgba8 fColor;
};
// constructor
IconRenderer::IconRenderer(BBitmap* bitmap)
: fBitmap(bitmap),
fIcon(NULL),
fStyles(StyleManager::Default()),
fGammaTable(2.2),
fRenderingBuffer(),
fPixelFormat(fRenderingBuffer),
fPixelFormatPre(fRenderingBuffer),
fBaseRenderer(fPixelFormat),
fBaseRendererPre(fPixelFormatPre),
fScanline(),
fBinaryScanline(),
fSpanAllocator(),
fRasterizer()
{
// attach rendering buffer to bitmap
fRenderingBuffer.attach((uint8*)bitmap->Bits(),
bitmap->Bounds().IntegerWidth() + 1,
bitmap->Bounds().IntegerHeight() + 1,
bitmap->BytesPerRow());
// attach bitmap
}
// destructor
IconRenderer::~IconRenderer()
{
}
// SetIcon
void
IconRenderer::SetIcon(Icon* icon)
{
if (fIcon == icon)
return;
fIcon = icon;
// TODO: ... ?
}
// #pragma mark -
// _RenderIcon
void
IconRenderer::_RenderIcon()
{
fBaseRenderer.clear(agg::rgba8(0, 0, 0, 0));
if (!fIcon)
return;
// TODO: iterate over shapes in icon and
// add the vector paths to the rasterizer
StyleHandler styleHandler(fStyles, fGammaTable);
agg::render_scanlines_compound(fRasterizer,
fScanline,
fBinaryScanline,
fBaseRendererPre,
fSpanAllocator,
styleHandler);
fPixelFormat.apply_gamma_dir(fGammaTable);
}
@@ -0,0 +1,69 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#ifndef ICON_RENDERER_H
#define ICON_RENDERER_H
#include "agg_gamma_lut.h"
#include "agg_rendering_buffer.h"
#include "agg_rasterizer_compound_aa.h"
#include "agg_scanline_u.h"
#include "agg_scanline_bin.h"
#include "agg_renderer_scanline.h"
#include "agg_span_allocator.h"
#include "agg_pixfmt_rgba.h"
class BBitmap;
class Icon;
class StyleManager;
typedef agg::gamma_lut
<agg::int8u, agg::int8u> GammaTable;
typedef agg::rendering_buffer RenderingBuffer;
typedef agg::pixfmt_bgra32 PixelFormat;
typedef agg::pixfmt_bgra32_pre PixelFormatPre;
typedef agg::renderer_base<PixelFormat> BaseRenderer;
typedef agg::renderer_base<PixelFormatPre> BaseRendererPre;
typedef agg::scanline_u8 Scanline;
typedef agg::scanline_bin BinaryScanline;
typedef agg::span_allocator<agg::rgba8> SpanAllocator;
typedef agg::rasterizer_compound_aa
<agg::rasterizer_sl_clip_dbl> CompoundRasterizer;
class IconRenderer {
public:
IconRenderer(BBitmap* bitmap);
virtual ~IconRenderer();
void SetIcon(Icon* icon);
private:
void _RenderIcon();
BBitmap* fBitmap;
Icon* fIcon;
StyleManager* fStyles;
GammaTable fGammaTable;
RenderingBuffer fRenderingBuffer;
PixelFormat fPixelFormat;
PixelFormatPre fPixelFormatPre;
BaseRenderer fBaseRenderer;
BaseRendererPre fBaseRendererPre;
Scanline fScanline;
BinaryScanline fBinaryScanline;
SpanAllocator fSpanAllocator;
CompoundRasterizer fRasterizer;
};
#endif // ICON_RENDERER_H
@@ -0,0 +1,191 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#include "PathContainer.h"
#include <stdio.h>
#include <string.h>
#include <OS.h>
#include "VectorPath.h"
// constructor
PathContainerListener::PathContainerListener()
{
}
// destructor
PathContainerListener::~PathContainerListener()
{
}
// constructor
PathContainer::PathContainer()
: fPaths(16),
fListeners(2)
{
}
// destructor
PathContainer::~PathContainer()
{
int32 count = fListeners.CountItems();
if (count > 0) {
debugger("~PathContainer() - there are still"
"listeners attached\n");
}
_MakeEmpty();
}
// #pragma mark -
// AddPath
bool
PathContainer::AddPath(VectorPath* path)
{
if (!path)
return false;
// prevent adding the same path twice
if (HasPath(path))
return false;
if (fPaths.AddItem((void*)path)) {
_NotifyPathAdded(path);
return true;
}
fprintf(stderr, "PathContainer::AddPath() - out of memory!\n");
return false;
}
// RemovePath
bool
PathContainer::RemovePath(VectorPath* path)
{
if (fPaths.RemoveItem((void*)path)) {
_NotifyPathRemoved(path);
return true;
}
return false;
}
// RemovePath
VectorPath*
PathContainer::RemovePath(int32 index)
{
VectorPath* path = (VectorPath*)fPaths.RemoveItem(index);
if (path) {
_NotifyPathRemoved(path);
}
return path;
}
// MakeEmpty
void
PathContainer::MakeEmpty()
{
_MakeEmpty();
}
// #pragma mark -
// CountPaths
int32
PathContainer::CountPaths() const
{
return fPaths.CountItems();
}
// HasPath
bool
PathContainer::HasPath(VectorPath* path) const
{
return fPaths.HasItem((void*)path);
}
// PathAt
VectorPath*
PathContainer::PathAt(int32 index) const
{
return (VectorPath*)fPaths.ItemAt(index);
}
// PathAtFast
VectorPath*
PathContainer::PathAtFast(int32 index) const
{
return (VectorPath*)fPaths.ItemAtFast(index);
}
// #pragma mark -
// AddListener
bool
PathContainer::AddListener(PathContainerListener* listener)
{
if (listener && !fListeners.HasItem((void*)listener))
return fListeners.AddItem(listener);
return false;
}
// RemoveListener
bool
PathContainer::RemoveListener(PathContainerListener* listener)
{
return fListeners.RemoveItem(listener);
}
// #pragma mark -
// _MakeEmpty
void
PathContainer::_MakeEmpty()
{
int32 count = CountPaths();
for (int32 i = 0; i < count; i++) {
VectorPath* path = PathAtFast(i);
_NotifyPathRemoved(path);
path->Release();
}
fPaths.MakeEmpty();
}
// #pragma mark -
// _NotifyPathAdded
void
PathContainer::_NotifyPathAdded(VectorPath* path) const
{
BList listeners(fListeners);
int32 count = listeners.CountItems();
for (int32 i = 0; i < count; i++) {
PathContainerListener* listener
= (PathContainerListener*)listeners.ItemAtFast(i);
listener->PathAdded(path);
}
}
// _NotifyPathRemoved
void
PathContainer::_NotifyPathRemoved(VectorPath* path) const
{
BList listeners(fListeners);
int32 count = listeners.CountItems();
for (int32 i = 0; i < count; i++) {
PathContainerListener* listener
= (PathContainerListener*)listeners.ItemAtFast(i);
listener->PathRemoved(path);
}
}
@@ -0,0 +1,55 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#ifndef PATH_CONTAINER_H
#define PATH_CONTAINER_H
#include <List.h>
class VectorPath;
class PathContainerListener {
public:
PathContainerListener();
virtual ~PathContainerListener();
virtual void PathAdded(VectorPath* path) = 0;
virtual void PathRemoved(VectorPath* path) = 0;
};
class PathContainer {
public:
PathContainer();
virtual ~PathContainer();
bool AddPath(VectorPath* path);
bool RemovePath(VectorPath* path);
VectorPath* RemovePath(int32 index);
void MakeEmpty();
int32 CountPaths() const;
bool HasPath(VectorPath* path) const;
VectorPath* PathAt(int32 index) const;
VectorPath* PathAtFast(int32 index) const;
bool AddListener(PathContainerListener* listener);
bool RemoveListener(PathContainerListener* listener);
private:
void _MakeEmpty();
void _NotifyPathAdded(VectorPath* path) const;
void _NotifyPathRemoved(VectorPath* path) const;
BList fPaths;
BList fListeners;
};
#endif // PATH_CONTAINER_H
+40 -20
View File
@@ -1,15 +1,24 @@
#include "Shape.h"
#include <new>
#include <limits.h>
#include "Style.h"
#include "VectorPath.h"
using std::nothrow;
// constructor
Shape::Shape(VectorPath* path, ::Style* style)
: fPath(path),
Shape::Shape(::Style* style)
: Observable(),
Referenceable(),
PathContainerListener(),
fPaths(new (nothrow) PathContainer()),
fStyle(style)
{
if (fPath)
fPath->Acquire();
if (fPaths)
fPaths->AddListener(this);
if (fStyle)
fStyle->Acquire();
}
@@ -17,28 +26,35 @@ Shape::Shape(VectorPath* path, ::Style* style)
// destructor
Shape::~Shape()
{
if (fPath)
fPath->Release();
fPaths->MakeEmpty();
fPaths->RemoveListener(this);
delete fPaths;
if (fStyle)
fStyle->Release();
}
// SetPath
// PathAdded
void
Shape::SetPath(VectorPath* path)
Shape::PathAdded(VectorPath* path)
{
if (fPath == path)
return;
path->Acquire();
}
if (fPath)
fPath->Release();
// PathRemoved
void
Shape::PathRemoved(VectorPath* path)
{
path->Release();
}
fPath = path;
// #pragma mark -
if (fPath)
fPath->Acquire();
Notify();
// InitCheck
status_t
Shape::InitCheck() const
{
return fPaths ? B_OK : B_NO_MEMORY;
}
// SetStyle
@@ -63,7 +79,11 @@ Shape::SetStyle(::Style* style)
BRect
Shape::Bounds() const
{
if (fPath)
return fPath->Bounds();
return BRect(0, 0, -1, -1);
BRect bounds(LONG_MAX, LONG_MAX, LONG_MIN, LONG_MIN);
int32 count = fPaths->CountPaths();
for (int32 i = 0; i < count; i++)
bounds = bounds | fPaths->PathAtFast(i)->Bounds();
return bounds;
}
+16 -8
View File
@@ -4,19 +4,27 @@
#include <Rect.h>
#include "Observable.h"
#include "PathContainer.h"
#include "Referenceable.h"
class Style;
class VectorPath;
class Shape : public Observable {
class Shape : public Observable,
public Referenceable,
public PathContainerListener {
public:
Shape(VectorPath* path,
::Style* style);
Shape(::Style* style);
virtual ~Shape();
void SetPath(VectorPath* path);
inline VectorPath* Path() const
{ return fPath; }
// PathContainerListener interface
virtual void PathAdded(VectorPath* path);
virtual void PathRemoved(VectorPath* path);
// Shape
status_t InitCheck() const;
inline PathContainer* Paths() const
{ return fPaths; }
void SetStyle(::Style* style);
inline ::Style* Style() const
@@ -25,7 +33,7 @@ class Shape : public Observable {
BRect Bounds() const;
private:
VectorPath* fPath;
PathContainer* fPaths;
::Style* fStyle;
};
@@ -0,0 +1,191 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#include "ShapeContainer.h"
#include <stdio.h>
#include <string.h>
#include <OS.h>
#include "Shape.h"
// constructor
ShapeContainerListener::ShapeContainerListener()
{
}
// destructor
ShapeContainerListener::~ShapeContainerListener()
{
}
// constructor
ShapeContainer::ShapeContainer()
: fShapes(16),
fListeners(2)
{
}
// destructor
ShapeContainer::~ShapeContainer()
{
int32 count = fListeners.CountItems();
if (count > 0) {
debugger("~ShapeContainer() - there are still"
"listeners attached\n");
}
_MakeEmpty();
}
// #pragma mark -
// AddShape
bool
ShapeContainer::AddShape(Shape* shape)
{
if (!shape)
return false;
// prevent adding the same shape twice
if (HasShape(shape))
return false;
if (fShapes.AddItem((void*)shape)) {
_NotifyShapeAdded(shape);
return true;
}
fprintf(stderr, "ShapeContainer::AddShape() - out of memory!\n");
return false;
}
// RemoveShape
bool
ShapeContainer::RemoveShape(Shape* shape)
{
if (fShapes.RemoveItem((void*)shape)) {
_NotifyShapeRemoved(shape);
return true;
}
return false;
}
// RemoveShape
Shape*
ShapeContainer::RemoveShape(int32 index)
{
Shape* shape = (Shape*)fShapes.RemoveItem(index);
if (shape) {
_NotifyShapeRemoved(shape);
}
return shape;
}
// MakeEmpty
void
ShapeContainer::MakeEmpty()
{
_MakeEmpty();
}
// #pragma mark -
// CountShapes
int32
ShapeContainer::CountShapes() const
{
return fShapes.CountItems();
}
// HasShape
bool
ShapeContainer::HasShape(Shape* shape) const
{
return fShapes.HasItem((void*)shape);
}
// ShapeAt
Shape*
ShapeContainer::ShapeAt(int32 index) const
{
return (Shape*)fShapes.ItemAt(index);
}
// ShapeAtFast
Shape*
ShapeContainer::ShapeAtFast(int32 index) const
{
return (Shape*)fShapes.ItemAtFast(index);
}
// #pragma mark -
// AddListener
bool
ShapeContainer::AddListener(ShapeContainerListener* listener)
{
if (listener && !fListeners.HasItem((void*)listener))
return fListeners.AddItem(listener);
return false;
}
// RemoveListener
bool
ShapeContainer::RemoveListener(ShapeContainerListener* listener)
{
return fListeners.RemoveItem(listener);
}
// #pragma mark -
// _MakeEmpty
void
ShapeContainer::_MakeEmpty()
{
int32 count = CountShapes();
for (int32 i = 0; i < count; i++) {
Shape* shape = ShapeAtFast(i);
_NotifyShapeRemoved(shape);
shape->Release();
}
fShapes.MakeEmpty();
}
// #pragma mark -
// _NotifyShapeAdded
void
ShapeContainer::_NotifyShapeAdded(Shape* shape) const
{
BList listeners(fListeners);
int32 count = listeners.CountItems();
for (int32 i = 0; i < count; i++) {
ShapeContainerListener* listener
= (ShapeContainerListener*)listeners.ItemAtFast(i);
listener->ShapeAdded(shape);
}
}
// _NotifyShapeRemoved
void
ShapeContainer::_NotifyShapeRemoved(Shape* shape) const
{
BList listeners(fListeners);
int32 count = listeners.CountItems();
for (int32 i = 0; i < count; i++) {
ShapeContainerListener* listener
= (ShapeContainerListener*)listeners.ItemAtFast(i);
listener->ShapeRemoved(shape);
}
}
@@ -0,0 +1,56 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#ifndef SHAPE_CONTAINER_H
#define SHAPE_CONTAINER_H
#include <List.h>
class Shape;
class ShapeContainerListener {
public:
ShapeContainerListener();
virtual ~ShapeContainerListener();
virtual void ShapeAdded(Shape* shape) = 0;
virtual void ShapeRemoved(Shape* shape) = 0;
};
class ShapeContainer {
public:
ShapeContainer();
virtual ~ShapeContainer();
bool AddShape(Shape* shape);
bool RemoveShape(Shape* shape);
Shape* RemoveShape(int32 index);
void MakeEmpty();
int32 CountShapes() const;
bool HasShape(Shape* shape) const;
Shape* ShapeAt(int32 index) const;
Shape* ShapeAtFast(int32 index) const;
bool AddListener(ShapeContainerListener* listener);
bool RemoveListener(
ShapeContainerListener* listener);
private:
void _MakeEmpty();
void _NotifyShapeAdded(Shape* shape) const;
void _NotifyShapeRemoved(Shape* shape) const;
BList fShapes;
BList fListeners;
};
#endif // SHAPE_CONTAINER_H
+13 -1
View File
@@ -26,10 +26,16 @@ StyleManagerListener::~StyleManagerListener()
}
// init global StyleManager instance
StyleManager
StyleManager::fDefaultInstance;
// constructor
StyleManager::StyleManager()
: RWLocker()
: RWLocker(),
fStyles(32),
fListeners(2)
{
}
@@ -156,6 +162,12 @@ StyleManager::RemoveListener(StyleManagerListener* listener)
return fListeners.RemoveItem(listener);
}
StyleManager*
StyleManager::Default()
{
return &fDefaultInstance;
}
// #pragma mark -
// _StateChanged
@@ -46,6 +46,8 @@ class StyleManager : public RWLocker {
bool AddListener(StyleManagerListener* listener);
bool RemoveListener(StyleManagerListener* listener);
static StyleManager* Default();
private:
void _StateChanged();
void _MakeEmpty();
@@ -55,6 +57,8 @@ class StyleManager : public RWLocker {
BList fStyles;
BList fListeners;
static StyleManager fDefaultInstance;
};
#endif // STYLE_MANAGER_H