* moved all the classes actually needed for reading a
vector icon to this place, #ifdef'd out all the editing features (listening, referencing, converting to PropertyObject... etc) * TODO: put into BPrivate namespace... git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18396 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -5,6 +5,7 @@ SubInclude HAIKU_TOP src libs bsd ;
|
|||||||
#SubInclude HAIKU_TOP src libs edit ;
|
#SubInclude HAIKU_TOP src libs edit ;
|
||||||
SubInclude HAIKU_TOP src libs fluidsynth ;
|
SubInclude HAIKU_TOP src libs fluidsynth ;
|
||||||
SubInclude HAIKU_TOP src libs freetype2 ;
|
SubInclude HAIKU_TOP src libs freetype2 ;
|
||||||
|
SubInclude HAIKU_TOP src libs icon ;
|
||||||
#SubInclude HAIKU_TOP src libs ncurses ;
|
#SubInclude HAIKU_TOP src libs ncurses ;
|
||||||
SubInclude HAIKU_TOP src libs pdflib ;
|
SubInclude HAIKU_TOP src libs pdflib ;
|
||||||
SubInclude HAIKU_TOP src libs png ;
|
SubInclude HAIKU_TOP src libs png ;
|
||||||
|
|||||||
@@ -0,0 +1,206 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Icon.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "PathContainer.h"
|
||||||
|
#include "Shape.h"
|
||||||
|
#include "Style.h"
|
||||||
|
#include "StyleContainer.h"
|
||||||
|
|
||||||
|
using std::nothrow;
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
IconListener::IconListener() {}
|
||||||
|
IconListener::~IconListener() {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
Icon::Icon()
|
||||||
|
: fStyles(new (nothrow) StyleContainer()),
|
||||||
|
fPaths(new (nothrow) PathContainer(true)),
|
||||||
|
fShapes(new (nothrow) ShapeContainer())
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
, fListeners(2)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
if (fShapes)
|
||||||
|
fShapes->AddListener(this);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
Icon::Icon(const Icon& other)
|
||||||
|
: fStyles(new (nothrow) StyleContainer()),
|
||||||
|
fPaths(new (nothrow) PathContainer(true)),
|
||||||
|
fShapes(new (nothrow) ShapeContainer())
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
, fListeners(2)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (!fStyles || !fPaths || !fShapes)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
fShapes->AddListener(this);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int32 styleCount = other.fStyles->CountStyles();
|
||||||
|
for (int32 i = 0; i < styleCount; i++) {
|
||||||
|
Style* style = other.fStyles->StyleAtFast(i);
|
||||||
|
Style* clone = new (nothrow) Style(*style);
|
||||||
|
if (!clone || !fStyles->AddStyle(clone)) {
|
||||||
|
delete clone;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 pathCount = other.fPaths->CountPaths();
|
||||||
|
for (int32 i = 0; i < pathCount; i++) {
|
||||||
|
VectorPath* path = other.fPaths->PathAtFast(i);
|
||||||
|
VectorPath* clone = new (nothrow) VectorPath(*path);
|
||||||
|
if (!clone || !fPaths->AddPath(clone)) {
|
||||||
|
delete clone;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 shapeCount = other.fShapes->CountShapes();
|
||||||
|
for (int32 i = 0; i < shapeCount; i++) {
|
||||||
|
Shape* shape = other.fShapes->ShapeAtFast(i);
|
||||||
|
Shape* clone = new (nothrow) Shape(*shape);
|
||||||
|
if (!clone || !fShapes->AddShape(clone)) {
|
||||||
|
delete clone;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// the cloned shape references styles and paths in
|
||||||
|
// the "other" icon, replace them with "local" styles
|
||||||
|
// and paths
|
||||||
|
int32 styleIndex = other.fStyles->IndexOf(shape->Style());
|
||||||
|
clone->SetStyle(fStyles->StyleAt(styleIndex));
|
||||||
|
|
||||||
|
clone->Paths()->MakeEmpty();
|
||||||
|
pathCount = shape->Paths()->CountPaths();
|
||||||
|
for (int32 j = 0; j < pathCount; j++) {
|
||||||
|
VectorPath* remote = shape->Paths()->PathAtFast(j);
|
||||||
|
int32 index = other.fPaths->IndexOf(remote);
|
||||||
|
VectorPath* local = fPaths->PathAt(index);
|
||||||
|
if (!local) {
|
||||||
|
printf("failed to match remote and "
|
||||||
|
"local paths while cloning icon\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!clone->Paths()->AddPath(local)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
Icon::~Icon()
|
||||||
|
{
|
||||||
|
if (fShapes) {
|
||||||
|
fShapes->MakeEmpty();
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
fShapes->RemoveListener(this);
|
||||||
|
#endif
|
||||||
|
delete fShapes;
|
||||||
|
}
|
||||||
|
delete fPaths;
|
||||||
|
delete fStyles;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// ShapeAdded
|
||||||
|
void
|
||||||
|
Icon::ShapeAdded(Shape* shape, int32 index)
|
||||||
|
{
|
||||||
|
shape->AddObserver(this);
|
||||||
|
_NotifyAreaInvalidated(shape->Bounds(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShapeRemoved
|
||||||
|
void
|
||||||
|
Icon::ShapeRemoved(Shape* shape)
|
||||||
|
{
|
||||||
|
shape->RemoveObserver(this);
|
||||||
|
_NotifyAreaInvalidated(shape->Bounds(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObjectChanged
|
||||||
|
void
|
||||||
|
Icon::ObjectChanged(const Observable* object)
|
||||||
|
{
|
||||||
|
const Shape* shape = dynamic_cast<const Shape*>(object);
|
||||||
|
if (shape) {
|
||||||
|
BRect area = shape->LastBounds();
|
||||||
|
area = area | shape->Bounds(true);
|
||||||
|
area.InsetBy(-1, -1);
|
||||||
|
_NotifyAreaInvalidated(area);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddListener
|
||||||
|
bool
|
||||||
|
Icon::AddListener(IconListener* listener)
|
||||||
|
{
|
||||||
|
if (listener && !fListeners.HasItem((void*)listener))
|
||||||
|
return fListeners.AddItem((void*)listener);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveListener
|
||||||
|
bool
|
||||||
|
Icon::RemoveListener(IconListener* listener)
|
||||||
|
{
|
||||||
|
return fListeners.RemoveItem((void*)listener);
|
||||||
|
}
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
|
||||||
|
// Clone
|
||||||
|
Icon*
|
||||||
|
Icon::Clone() const
|
||||||
|
{
|
||||||
|
return new (nothrow) Icon(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeEmpty
|
||||||
|
void
|
||||||
|
Icon::MakeEmpty()
|
||||||
|
{
|
||||||
|
fShapes->MakeEmpty();
|
||||||
|
fPaths->MakeEmpty();
|
||||||
|
fStyles->MakeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// _NotifyAreaInvalidated
|
||||||
|
void
|
||||||
|
Icon::_NotifyAreaInvalidated(const BRect& area) const
|
||||||
|
{
|
||||||
|
BList listeners(fListeners);
|
||||||
|
int32 count = listeners.CountItems();
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
IconListener* listener
|
||||||
|
= (IconListener*)listeners.ItemAtFast(i);
|
||||||
|
listener->AreaInvalidated(area);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ICON_H
|
||||||
|
#define ICON_H
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
#include <List.h>
|
||||||
|
|
||||||
|
# include "Observer.h"
|
||||||
|
#else
|
||||||
|
# include <SupportDefs.h>
|
||||||
|
#endif
|
||||||
|
#include "ShapeContainer.h"
|
||||||
|
|
||||||
|
class BRect;
|
||||||
|
class PathContainer;
|
||||||
|
class StyleContainer;
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
class IconListener {
|
||||||
|
public:
|
||||||
|
IconListener();
|
||||||
|
virtual ~IconListener();
|
||||||
|
|
||||||
|
virtual void AreaInvalidated(const BRect& area) = 0;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
class Icon : public ShapeContainerListener,
|
||||||
|
public Observer {
|
||||||
|
#else
|
||||||
|
class Icon {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
|
Icon();
|
||||||
|
Icon(const Icon& other);
|
||||||
|
virtual ~Icon();
|
||||||
|
|
||||||
|
StyleContainer* Styles() const
|
||||||
|
{ return fStyles; }
|
||||||
|
PathContainer* Paths() const
|
||||||
|
{ return fPaths; }
|
||||||
|
ShapeContainer* Shapes() const
|
||||||
|
{ return fShapes; }
|
||||||
|
|
||||||
|
Icon* Clone() const;
|
||||||
|
void MakeEmpty();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
StyleContainer* fStyles;
|
||||||
|
PathContainer* fPaths;
|
||||||
|
ShapeContainer* fShapes;
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
public:
|
||||||
|
// ShapeContainerListener interface
|
||||||
|
virtual void ShapeAdded(Shape* shape, int32 index);
|
||||||
|
virtual void ShapeRemoved(Shape* shape);
|
||||||
|
|
||||||
|
// Observer interface
|
||||||
|
virtual void ObjectChanged(const Observable* object);
|
||||||
|
|
||||||
|
// Icon
|
||||||
|
bool AddListener(IconListener* listener);
|
||||||
|
bool RemoveListener(IconListener* listener);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _NotifyAreaInvalidated(
|
||||||
|
const BRect& area) const;
|
||||||
|
BList fListeners;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ICON_H
|
||||||
@@ -0,0 +1,428 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "IconRenderer.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <Bitmap.h>
|
||||||
|
#include <List.h>
|
||||||
|
|
||||||
|
#include <agg_span_gradient.h>
|
||||||
|
#include <agg_span_interpolator_linear.h>
|
||||||
|
|
||||||
|
#include "Gradient.h"
|
||||||
|
#include "Icon.h"
|
||||||
|
#include "Shape.h"
|
||||||
|
#include "ShapeContainer.h"
|
||||||
|
#include "Style.h"
|
||||||
|
#include "VectorPath.h"
|
||||||
|
|
||||||
|
using std::nothrow;
|
||||||
|
|
||||||
|
class StyleHandler {
|
||||||
|
struct StyleItem {
|
||||||
|
Style* style;
|
||||||
|
Transformation transformation;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
StyleHandler(::GammaTable& gammaTable)
|
||||||
|
: fStyles(20),
|
||||||
|
fGammaTable(gammaTable),
|
||||||
|
fTransparent(0, 0, 0, 0),
|
||||||
|
fColor(0, 0, 0, 0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
~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;
|
||||||
|
|
||||||
|
return styleItem->style->Gradient() == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
BList fStyles;
|
||||||
|
::GammaTable& fGammaTable;
|
||||||
|
agg::rgba8 fTransparent;
|
||||||
|
agg::rgba8 fColor;
|
||||||
|
};
|
||||||
|
|
||||||
|
// color
|
||||||
|
const agg::rgba8&
|
||||||
|
StyleHandler::color(unsigned styleIndex)
|
||||||
|
{
|
||||||
|
StyleItem* styleItem = (StyleItem*)fStyles.ItemAt(styleIndex);
|
||||||
|
if (!styleItem) {
|
||||||
|
printf("no style at index: %d!\n", styleIndex);
|
||||||
|
return fTransparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rgb_color& c = styleItem->style->Color();
|
||||||
|
fColor = agg::rgba8(fGammaTable.dir(c.red),
|
||||||
|
fGammaTable.dir(c.green),
|
||||||
|
fGammaTable.dir(c.blue),
|
||||||
|
c.alpha);
|
||||||
|
fColor.premultiply();
|
||||||
|
return fColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate_span
|
||||||
|
void
|
||||||
|
StyleHandler::generate_span(agg::rgba8* span, int x, int y,
|
||||||
|
unsigned len, unsigned styleIndex)
|
||||||
|
{
|
||||||
|
StyleItem* styleItem = (StyleItem*)fStyles.ItemAt(styleIndex);
|
||||||
|
if (!styleItem || !styleItem->style->Gradient()) {
|
||||||
|
printf("no style/gradient at index: %d!\n", styleIndex);
|
||||||
|
// TODO: memset() span?
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Style* style = styleItem->style;
|
||||||
|
Gradient* gradient = style->Gradient();
|
||||||
|
const agg::rgba8* colors = style->GammaCorrectedColors(fGammaTable);
|
||||||
|
|
||||||
|
switch (gradient->Type()) {
|
||||||
|
case GRADIENT_LINEAR: {
|
||||||
|
agg::gradient_x function;
|
||||||
|
_GenerateGradient(span, x, y, len, function, -64, 64, colors,
|
||||||
|
styleItem->transformation);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GRADIENT_CIRCULAR: {
|
||||||
|
agg::gradient_radial function;
|
||||||
|
_GenerateGradient(span, x, y, len, function, 0, 64, colors,
|
||||||
|
styleItem->transformation);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GRADIENT_DIAMONT: {
|
||||||
|
agg::gradient_diamond function;
|
||||||
|
_GenerateGradient(span, x, y, len, function, 0, 64, colors,
|
||||||
|
styleItem->transformation);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GRADIENT_CONIC: {
|
||||||
|
agg::gradient_conic function;
|
||||||
|
_GenerateGradient(span, x, y, len, function, 0, 64, colors,
|
||||||
|
styleItem->transformation);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GRADIENT_XY: {
|
||||||
|
agg::gradient_xy function;
|
||||||
|
_GenerateGradient(span, x, y, len, function, 0, 64, colors,
|
||||||
|
styleItem->transformation);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GRADIENT_SQRT_XY: {
|
||||||
|
agg::gradient_sqrt_xy function;
|
||||||
|
_GenerateGradient(span, x, y, len, function, 0, 64, colors,
|
||||||
|
styleItem->transformation);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// _GenerateGradient
|
||||||
|
template<class GradientFunction>
|
||||||
|
void
|
||||||
|
StyleHandler::_GenerateGradient(agg::rgba8* span, int x, int y, unsigned len,
|
||||||
|
GradientFunction function,
|
||||||
|
int32 start, int32 end,
|
||||||
|
const agg::rgba8* gradientColors,
|
||||||
|
Transformation& gradientTransform)
|
||||||
|
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
class HintingTransformer {
|
||||||
|
public:
|
||||||
|
|
||||||
|
void transform(double* x, double* y) const
|
||||||
|
{
|
||||||
|
*x = floor(*x + 0.5);
|
||||||
|
*y = floor(*y + 0.5);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
IconRenderer::IconRenderer(BBitmap* bitmap)
|
||||||
|
: fBitmap(bitmap),
|
||||||
|
fBackground(NULL),
|
||||||
|
fBackgroundColor(0, 0, 0, 0),
|
||||||
|
fIcon(NULL),
|
||||||
|
|
||||||
|
fGammaTable(2.2),
|
||||||
|
|
||||||
|
fRenderingBuffer(),
|
||||||
|
fPixelFormat(fRenderingBuffer),
|
||||||
|
fPixelFormatPre(fRenderingBuffer),
|
||||||
|
fBaseRenderer(fPixelFormat),
|
||||||
|
fBaseRendererPre(fPixelFormatPre),
|
||||||
|
|
||||||
|
fScanline(),
|
||||||
|
fBinaryScanline(),
|
||||||
|
fSpanAllocator(),
|
||||||
|
|
||||||
|
fRasterizer(),
|
||||||
|
|
||||||
|
fGlobalTransform()
|
||||||
|
{
|
||||||
|
// attach rendering buffer to bitmap
|
||||||
|
fRenderingBuffer.attach((uint8*)bitmap->Bits(),
|
||||||
|
bitmap->Bounds().IntegerWidth() + 1,
|
||||||
|
bitmap->Bounds().IntegerHeight() + 1,
|
||||||
|
bitmap->BytesPerRow());
|
||||||
|
|
||||||
|
fBaseRendererPre.clip_box(0,
|
||||||
|
0,
|
||||||
|
fBitmap->Bounds().IntegerWidth(),
|
||||||
|
fBitmap->Bounds().IntegerHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
IconRenderer::~IconRenderer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetIcon
|
||||||
|
void
|
||||||
|
IconRenderer::SetIcon(const Icon* icon)
|
||||||
|
{
|
||||||
|
if (fIcon == icon)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fIcon = icon;
|
||||||
|
// TODO: ... ?
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render
|
||||||
|
void
|
||||||
|
IconRenderer::Render()
|
||||||
|
{
|
||||||
|
_Render(fBitmap->Bounds());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render
|
||||||
|
void
|
||||||
|
IconRenderer::Render(const BRect& area)
|
||||||
|
{
|
||||||
|
_Render(fBitmap->Bounds() & area);
|
||||||
|
}
|
||||||
|
|
||||||
|
//SetScale
|
||||||
|
void
|
||||||
|
IconRenderer::SetScale(double scale)
|
||||||
|
{
|
||||||
|
fGlobalTransform.reset();
|
||||||
|
fGlobalTransform.multiply(agg::trans_affine_scaling(scale));
|
||||||
|
}
|
||||||
|
|
||||||
|
//SetBackground
|
||||||
|
void
|
||||||
|
IconRenderer::SetBackground(const BBitmap* background)
|
||||||
|
{
|
||||||
|
fBackground = background;
|
||||||
|
}
|
||||||
|
|
||||||
|
//SetBackground
|
||||||
|
void
|
||||||
|
IconRenderer::SetBackground(const agg::rgba8& background)
|
||||||
|
{
|
||||||
|
fBackgroundColor.r = fGammaTable.dir(background.r);
|
||||||
|
fBackgroundColor.g = fGammaTable.dir(background.g);
|
||||||
|
fBackgroundColor.b = fGammaTable.dir(background.b);
|
||||||
|
fBackgroundColor.a = background.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Demultiply
|
||||||
|
void
|
||||||
|
IconRenderer::Demultiply()
|
||||||
|
{
|
||||||
|
uint8* bits = (uint8*)fBitmap->Bits();
|
||||||
|
uint32 bpr = fBitmap->BytesPerRow();
|
||||||
|
uint32 width = fBitmap->Bounds().IntegerWidth() + 1;
|
||||||
|
uint32 height = fBitmap->Bounds().IntegerHeight() + 1;
|
||||||
|
|
||||||
|
for (uint32 y = 0; y < height; y++) {
|
||||||
|
uint8* b = bits;
|
||||||
|
for (uint32 x = 0; x < width; x++) {
|
||||||
|
if (b[3] < 255 && b[3] > 0) {
|
||||||
|
b[0] = (uint8)((int)b[0] * 255 / b[3]);
|
||||||
|
b[1] = (uint8)((int)b[1] * 255 / b[3]);
|
||||||
|
b[2] = (uint8)((int)b[2] * 255 / b[3]);
|
||||||
|
}
|
||||||
|
b += 4;
|
||||||
|
}
|
||||||
|
bits += bpr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
typedef agg::conv_transform<VertexSource, Transformation> ScaledPath;
|
||||||
|
typedef agg::conv_transform<ScaledPath, HintingTransformer> HintedPath;
|
||||||
|
|
||||||
|
// _Render
|
||||||
|
void
|
||||||
|
IconRenderer::_Render(const BRect& r)
|
||||||
|
{
|
||||||
|
if (!fIcon)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// TODO: fix clip box for "clear" and "apply_gamma_inv"
|
||||||
|
// fBaseRendererPre.clip_box((int)floorf(r.left),
|
||||||
|
// (int)floorf(r.top),
|
||||||
|
// (int)ceilf(r.right),
|
||||||
|
// (int)ceilf(r.bottom));
|
||||||
|
|
||||||
|
if (fBackground)
|
||||||
|
memcpy(fBitmap->Bits(), fBackground->Bits(), fBitmap->BitsLength());
|
||||||
|
else
|
||||||
|
fBaseRendererPre.clear(fBackgroundColor);
|
||||||
|
|
||||||
|
//bigtime_t start = system_time();
|
||||||
|
StyleHandler styleHandler(fGammaTable);
|
||||||
|
|
||||||
|
fRasterizer.reset();
|
||||||
|
// iterate over the shapes in the icon,
|
||||||
|
// add the vector paths to the rasterizer
|
||||||
|
// and associate each shapes style
|
||||||
|
int32 shapeCount = fIcon->Shapes()->CountShapes();
|
||||||
|
int32 styleIndex = 0;
|
||||||
|
for (int32 i = 0; i < shapeCount; i++) {
|
||||||
|
Shape* shape = fIcon->Shapes()->ShapeAtFast(i);
|
||||||
|
|
||||||
|
Transformation transform(*shape);
|
||||||
|
transform.multiply(fGlobalTransform);
|
||||||
|
// NOTE: this works only because "agg::trans_affine",
|
||||||
|
// "Transformable" and "Transformation" are all the
|
||||||
|
// same thing
|
||||||
|
|
||||||
|
// don't render shape if the Level Of Detail falls
|
||||||
|
// out of range
|
||||||
|
if (transform.scale() <= shape->MinVisibilityScale()
|
||||||
|
|| transform.scale() > shape->MaxVisibilityScale())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Style* style = shape->Style();
|
||||||
|
if (!style)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// add the style either with global transformation or with
|
||||||
|
// the shapes transformation, depending on wether there
|
||||||
|
// is a gradient and its settings
|
||||||
|
Gradient* gradient = style->Gradient();
|
||||||
|
bool styleAdded = false;
|
||||||
|
if (gradient && !gradient->InheritTransformation()) {
|
||||||
|
styleAdded = styleHandler.AddStyle(shape->Style(),
|
||||||
|
fGlobalTransform);
|
||||||
|
} else {
|
||||||
|
styleAdded = styleHandler.AddStyle(shape->Style(),
|
||||||
|
transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!styleAdded) {
|
||||||
|
printf("IconRenderer::_Render() - out of memory\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fRasterizer.styles(styleIndex, -1);
|
||||||
|
styleIndex++;
|
||||||
|
|
||||||
|
// global scale
|
||||||
|
ScaledPath scaledPath(shape->VertexSource(), transform);
|
||||||
|
if (shape->Hinting()) {
|
||||||
|
// additional hinting
|
||||||
|
HintingTransformer hinter;
|
||||||
|
HintedPath hintedPath(scaledPath, hinter);
|
||||||
|
fRasterizer.add_path(hintedPath);
|
||||||
|
} else {
|
||||||
|
fRasterizer.add_path(scaledPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
agg::render_scanlines_compound(fRasterizer,
|
||||||
|
fScanline,
|
||||||
|
fBinaryScanline,
|
||||||
|
fBaseRendererPre,
|
||||||
|
fSpanAllocator,
|
||||||
|
styleHandler);
|
||||||
|
|
||||||
|
if (fGammaTable.gamma() != 1.0)
|
||||||
|
fPixelFormat.apply_gamma_inv(fGammaTable);
|
||||||
|
|
||||||
|
//if (fRenderingBuffer.width() == 64)
|
||||||
|
//printf("rendering 64x64: %lld\n", system_time() - start);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* 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_pixfmt_rgba.h>
|
||||||
|
#include <agg_rasterizer_compound_aa.h>
|
||||||
|
#include <agg_rendering_buffer.h>
|
||||||
|
#include <agg_renderer_scanline.h>
|
||||||
|
#include <agg_scanline_bin.h>
|
||||||
|
#include <agg_scanline_u.h>
|
||||||
|
#include <agg_span_allocator.h>
|
||||||
|
#include <agg_trans_affine.h>
|
||||||
|
|
||||||
|
class BBitmap;
|
||||||
|
class BRect;
|
||||||
|
class Icon;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
typedef agg::trans_affine Transformation;
|
||||||
|
|
||||||
|
class IconRenderer {
|
||||||
|
public:
|
||||||
|
IconRenderer(BBitmap* bitmap);
|
||||||
|
virtual ~IconRenderer();
|
||||||
|
|
||||||
|
void SetIcon(const Icon* icon);
|
||||||
|
|
||||||
|
void Render();
|
||||||
|
void Render(const BRect& area);
|
||||||
|
|
||||||
|
void SetScale(double scale);
|
||||||
|
void SetBackground(const BBitmap* background);
|
||||||
|
// background is not copied,
|
||||||
|
// ownership stays with the caller
|
||||||
|
// colorspace and size need to
|
||||||
|
// be the same as bitmap passed
|
||||||
|
// to constructor
|
||||||
|
void SetBackground(const agg::rgba8& color);
|
||||||
|
// used when no background bitmap
|
||||||
|
// is set
|
||||||
|
|
||||||
|
const ::GammaTable& GammaTable() const
|
||||||
|
{ return fGammaTable; }
|
||||||
|
|
||||||
|
void Demultiply();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _Render(const BRect& area);
|
||||||
|
|
||||||
|
BBitmap* fBitmap;
|
||||||
|
const BBitmap* fBackground;
|
||||||
|
agg::rgba8 fBackgroundColor;
|
||||||
|
const Icon* fIcon;
|
||||||
|
|
||||||
|
::GammaTable fGammaTable;
|
||||||
|
|
||||||
|
RenderingBuffer fRenderingBuffer;
|
||||||
|
PixelFormat fPixelFormat;
|
||||||
|
PixelFormatPre fPixelFormatPre;
|
||||||
|
BaseRenderer fBaseRenderer;
|
||||||
|
BaseRendererPre fBaseRendererPre;
|
||||||
|
|
||||||
|
Scanline fScanline;
|
||||||
|
BinaryScanline fBinaryScanline;
|
||||||
|
SpanAllocator fSpanAllocator;
|
||||||
|
|
||||||
|
CompoundRasterizer fRasterizer;
|
||||||
|
|
||||||
|
Transformation fGlobalTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ICON_RENDERER_H
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
SubDir HAIKU_TOP src libs icon ;
|
||||||
|
|
||||||
|
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||||
|
AddSubDirSupportedPlatforms libbe_test ;
|
||||||
|
|
||||||
|
# source directories
|
||||||
|
local sourceDirs =
|
||||||
|
flat_icon
|
||||||
|
shape
|
||||||
|
style
|
||||||
|
transformable
|
||||||
|
transformer
|
||||||
|
;
|
||||||
|
|
||||||
|
local sourceDir ;
|
||||||
|
for sourceDir in $(sourceDirs) {
|
||||||
|
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src libs icon $(sourceDir) ] ;
|
||||||
|
}
|
||||||
|
|
||||||
|
# system headers
|
||||||
|
UseLibraryHeaders agg ;
|
||||||
|
|
||||||
|
UsePrivateHeaders shared ;
|
||||||
|
|
||||||
|
StaticLibrary libicon.a :
|
||||||
|
# flat_icon
|
||||||
|
FlatIconFormat.cpp
|
||||||
|
FlatIconImporter.cpp
|
||||||
|
LittleEndianBuffer.cpp
|
||||||
|
PathCommandQueue.cpp
|
||||||
|
|
||||||
|
# shape
|
||||||
|
PathContainer.cpp
|
||||||
|
Shape.cpp
|
||||||
|
ShapeContainer.cpp
|
||||||
|
VectorPath.cpp
|
||||||
|
|
||||||
|
# style
|
||||||
|
Gradient.cpp
|
||||||
|
Style.cpp
|
||||||
|
StyleContainer.cpp
|
||||||
|
|
||||||
|
# transformable
|
||||||
|
Transformable.cpp
|
||||||
|
|
||||||
|
# transformer
|
||||||
|
AffineTransformer.cpp
|
||||||
|
ContourTransformer.cpp
|
||||||
|
PathSource.cpp
|
||||||
|
PerspectiveTransformer.cpp
|
||||||
|
StrokeTransformer.cpp
|
||||||
|
Transformer.cpp
|
||||||
|
TransformerFactory.cpp
|
||||||
|
|
||||||
|
Icon.cpp
|
||||||
|
IconRenderer.cpp
|
||||||
|
;
|
||||||
|
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "FlatIconFormat.h"
|
||||||
|
|
||||||
|
#include "LittleEndianBuffer.h"
|
||||||
|
|
||||||
|
const uint32 FLAT_ICON_MAGIC = 'ficn';
|
||||||
|
|
||||||
|
const char* kVectorAttrNodeName = "BEOS:I:STD_ICON";
|
||||||
|
const char* kVectorAttrMimeName = "META:I:STD_ICON";
|
||||||
|
|
||||||
|
// read_coord
|
||||||
|
bool
|
||||||
|
read_coord(LittleEndianBuffer& buffer, float& coord)
|
||||||
|
{
|
||||||
|
uint8 value;
|
||||||
|
if (!buffer.Read(value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (value & 128) {
|
||||||
|
// high bit set, the next byte is part of the coord
|
||||||
|
uint8 lowValue;
|
||||||
|
if (!buffer.Read(lowValue))
|
||||||
|
return false;
|
||||||
|
value &= 127;
|
||||||
|
uint16 coordValue = (value << 8) | lowValue;
|
||||||
|
coord = (float)coordValue / 102.0 - 128.0;
|
||||||
|
} else {
|
||||||
|
// simple coord
|
||||||
|
coord = (float)value - 32.0;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write_coord
|
||||||
|
bool
|
||||||
|
write_coord(LittleEndianBuffer& buffer, float coord)
|
||||||
|
{
|
||||||
|
// clamp coord
|
||||||
|
if (coord < -128.0)
|
||||||
|
coord = -128.0;
|
||||||
|
if (coord > 192.0)
|
||||||
|
coord = 192.0;
|
||||||
|
|
||||||
|
if (int(coord * 100.0) == (int)coord * 100
|
||||||
|
&& coord >= - 32.0 && coord <= 96.0) {
|
||||||
|
// saving coord in 7 bit is sufficient
|
||||||
|
uint8 value = (uint8)(coord + 32.0);
|
||||||
|
return buffer.Write(value);
|
||||||
|
} else {
|
||||||
|
// needing to save coord in 15 bits
|
||||||
|
uint16 value = (uint16)((coord + 128.0) * 102.0);
|
||||||
|
// set high bit to indicate there is only one byte
|
||||||
|
value |= 32768;
|
||||||
|
uint8 highValue = value >> 8;
|
||||||
|
uint8 lowValue = value & 255;
|
||||||
|
return buffer.Write(highValue) && buffer.Write(lowValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// read_float_24
|
||||||
|
bool
|
||||||
|
read_float_24(LittleEndianBuffer& buffer, float& _value)
|
||||||
|
{
|
||||||
|
uint8 bufferValue[3];
|
||||||
|
if (!buffer.Read(bufferValue[0]) || !buffer.Read(bufferValue[1])
|
||||||
|
|| !buffer.Read(bufferValue[2]))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int shortValue = (bufferValue[0] << 16)
|
||||||
|
| (bufferValue[1] << 8) | bufferValue[2];
|
||||||
|
|
||||||
|
int sign = (shortValue & 0x800000) >> 23;
|
||||||
|
int exponent = ((shortValue & 0x7e0000) >> 17) - 32;
|
||||||
|
int mantissa = (shortValue & 0x01ffff) << 6;
|
||||||
|
|
||||||
|
if (shortValue == 0)
|
||||||
|
_value = 0.0;
|
||||||
|
else {
|
||||||
|
uint32 value = (sign << 31) | ((exponent + 127) << 23) | mantissa;
|
||||||
|
|
||||||
|
_value = (float&)value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write_float_24
|
||||||
|
bool
|
||||||
|
write_float_24(LittleEndianBuffer& buffer, float _value)
|
||||||
|
{
|
||||||
|
// 1 bit sign
|
||||||
|
// 6 bit exponent
|
||||||
|
// 17 bit mantissa
|
||||||
|
// TODO: fixme for non-IEEE 754 architectures
|
||||||
|
uint32 value = (uint32&)_value;
|
||||||
|
|
||||||
|
int sign = (value & 0x80000000) >> 31;
|
||||||
|
int exponent = ((value & 0x7f800000) >> 23) - 127;
|
||||||
|
int mantissa = value & 0x007fffff;
|
||||||
|
|
||||||
|
if (exponent >= 32 || exponent < -32) {
|
||||||
|
uint8 zero = 0;
|
||||||
|
return buffer.Write(zero) && buffer.Write(zero)
|
||||||
|
&& buffer.Write(zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
int shortValue = (sign << 23)
|
||||||
|
| ((exponent + 32) << 17)
|
||||||
|
| (mantissa >> 6);
|
||||||
|
|
||||||
|
return buffer.Write((uint8)(shortValue >> 16))
|
||||||
|
&& buffer.Write((uint8)((shortValue >> 8) & 0xff))
|
||||||
|
&& buffer.Write((uint8)(shortValue & 0xff));
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FLAT_ICON_FORMAT_H
|
||||||
|
#define FLAT_ICON_FORMAT_H
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
extern const uint32 FLAT_ICON_MAGIC;
|
||||||
|
extern const char* kVectorAttrNodeName;
|
||||||
|
extern const char* kVectorAttrMimeName;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TAG_STYLE_SOLID_COLOR = 1,
|
||||||
|
TAG_STYLE_GRADIENT = 2,
|
||||||
|
TAG_STYLE_SOLID_COLOR_NO_ALPHA = 3,
|
||||||
|
|
||||||
|
TAG_SHAPE_PATH_SOURCE = 10,
|
||||||
|
|
||||||
|
TAG_TRANSFORMER_AFFINE = 20,
|
||||||
|
TAG_TRANSFORMER_CONTOUR = 21,
|
||||||
|
TAG_TRANSFORMER_PERSPECTIVE = 22,
|
||||||
|
TAG_TRANSFORMER_STROKE = 23,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
GRADIENT_FLAG_TRANSFORM = 1 << 1,
|
||||||
|
GRADIENT_FLAG_NO_ALPHA = 1 << 2,
|
||||||
|
GRADIENT_FLAG_16_BIT_COLORS = 1 << 3, // not yet used
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PATH_FLAGS_CLOSED = 1 << 1,
|
||||||
|
PATH_FLAGS_USES_COMMANDS = 1 << 2,
|
||||||
|
PATH_FLAGS_NO_CURVES = 1 << 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PATH_COMMAND_H_LINE = 0,
|
||||||
|
PATH_COMMAND_V_LINE = 1,
|
||||||
|
PATH_COMMAND_LINE = 2,
|
||||||
|
PATH_COMMAND_CURVE = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SHAPE_FLAG_TRANSFORM = 1 << 1,
|
||||||
|
SHAPE_FLAG_HINTING = 1 << 2,
|
||||||
|
SHAPE_FLAG_LOD_SCALE = 1 << 3,
|
||||||
|
SHAPE_FLAG_HAS_TRANSFORMERS = 1 << 4,
|
||||||
|
SHAPE_FLAG_TRANSLATION = 1 << 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
// utility functions
|
||||||
|
|
||||||
|
class LittleEndianBuffer;
|
||||||
|
|
||||||
|
bool read_coord(LittleEndianBuffer& buffer, float& coord);
|
||||||
|
bool write_coord(LittleEndianBuffer& buffer, float coord);
|
||||||
|
|
||||||
|
bool read_float_24(LittleEndianBuffer& buffer, float& value);
|
||||||
|
bool write_float_24(LittleEndianBuffer& buffer, float value);
|
||||||
|
|
||||||
|
#endif // FLAT_ICON_FORMAT_H
|
||||||
@@ -0,0 +1,594 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "FlatIconImporter.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <Archivable.h>
|
||||||
|
#include <DataIO.h>
|
||||||
|
#include <Message.h>
|
||||||
|
|
||||||
|
#include "AffineTransformer.h"
|
||||||
|
#include "AutoDeleter.h"
|
||||||
|
#include "ContourTransformer.h"
|
||||||
|
#include "FlatIconFormat.h"
|
||||||
|
#include "Gradient.h"
|
||||||
|
#include "Icon.h"
|
||||||
|
#include "LittleEndianBuffer.h"
|
||||||
|
#include "PathCommandQueue.h"
|
||||||
|
#include "PathContainer.h"
|
||||||
|
#include "PerspectiveTransformer.h"
|
||||||
|
#include "Shape.h"
|
||||||
|
#include "StrokeTransformer.h"
|
||||||
|
#include "Style.h"
|
||||||
|
#include "StyleContainer.h"
|
||||||
|
#include "VectorPath.h"
|
||||||
|
|
||||||
|
using std::nothrow;
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
FlatIconImporter::FlatIconImporter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
FlatIconImporter::~FlatIconImporter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import
|
||||||
|
status_t
|
||||||
|
FlatIconImporter::Import(Icon* icon, BPositionIO* stream)
|
||||||
|
{
|
||||||
|
// seek around in the stream to figure out the size
|
||||||
|
off_t size = stream->Seek(0, SEEK_END);
|
||||||
|
if (stream->Seek(0, SEEK_SET) != 0)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
// we chicken out on anything larger than 256k
|
||||||
|
if (size <= 0 || size > 256 * 1024)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// read the entire stream into a buffer
|
||||||
|
LittleEndianBuffer buffer(size);
|
||||||
|
if (!buffer.Buffer())
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
if (stream->Read(buffer.Buffer(), size) != size)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
status_t ret = _ParseSections(buffer, icon);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import
|
||||||
|
status_t
|
||||||
|
FlatIconImporter::Import(Icon* icon, uint8* _buffer, size_t size)
|
||||||
|
{
|
||||||
|
if (!_buffer)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// attach LittleEndianBuffer to buffer
|
||||||
|
LittleEndianBuffer buffer(_buffer, size);
|
||||||
|
|
||||||
|
return _ParseSections(buffer, icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// _ParseSections
|
||||||
|
status_t
|
||||||
|
FlatIconImporter::_ParseSections(LittleEndianBuffer& buffer, Icon* icon)
|
||||||
|
{
|
||||||
|
// test if this is an icon at all
|
||||||
|
uint32 magic;
|
||||||
|
if (!buffer.Read(magic) || magic != FLAT_ICON_MAGIC)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
// styles
|
||||||
|
StyleContainer* styles = icon->Styles();
|
||||||
|
status_t ret = _ParseStyles(buffer, styles);
|
||||||
|
if (ret < B_OK) {
|
||||||
|
printf("FlatIconImporter::_ParseSections() - "
|
||||||
|
"error parsing styles: %s\n", strerror(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// paths
|
||||||
|
PathContainer* paths = icon->Paths();
|
||||||
|
ret = _ParsePaths(buffer, paths);
|
||||||
|
if (ret < B_OK) {
|
||||||
|
printf("FlatIconImporter::_ParseSections() - "
|
||||||
|
"error parsing paths: %s\n", strerror(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// shapes
|
||||||
|
ret = _ParseShapes(buffer, styles, paths, icon->Shapes());
|
||||||
|
if (ret < B_OK) {
|
||||||
|
printf("FlatIconImporter::_ParseSections() - "
|
||||||
|
"error parsing shapes: %s\n", strerror(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _ReadTransformable
|
||||||
|
static bool
|
||||||
|
_ReadTransformable(LittleEndianBuffer& buffer, Transformable* transformable)
|
||||||
|
{
|
||||||
|
int32 matrixSize = Transformable::matrix_size;
|
||||||
|
double matrix[matrixSize];
|
||||||
|
for (int32 i = 0; i < matrixSize; i++) {
|
||||||
|
float value;
|
||||||
|
if (!read_float_24(buffer, value))
|
||||||
|
return false;
|
||||||
|
matrix[i] = value;
|
||||||
|
}
|
||||||
|
transformable->LoadFrom(matrix);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _ReadTranslation
|
||||||
|
static bool
|
||||||
|
_ReadTranslation(LittleEndianBuffer& buffer, Transformable* transformable)
|
||||||
|
{
|
||||||
|
BPoint t;
|
||||||
|
if (read_coord(buffer, t.x) && read_coord(buffer, t.y)) {
|
||||||
|
transformable->TranslateBy(t);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _ReadColorStyle
|
||||||
|
static Style*
|
||||||
|
_ReadColorStyle(LittleEndianBuffer& buffer, bool alpha)
|
||||||
|
{
|
||||||
|
rgb_color color;
|
||||||
|
if (alpha) {
|
||||||
|
if (!buffer.Read((uint32&)color))
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
color.alpha = 255;
|
||||||
|
if (!buffer.Read(color.red)
|
||||||
|
|| !buffer.Read(color.green)
|
||||||
|
|| !buffer.Read(color.blue))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return new (nothrow) Style(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// _ReadGradientStyle
|
||||||
|
static Style*
|
||||||
|
_ReadGradientStyle(LittleEndianBuffer& buffer)
|
||||||
|
{
|
||||||
|
Style* style = new (nothrow) Style();
|
||||||
|
if (!style)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ObjectDeleter<Style> styleDeleter(style);
|
||||||
|
|
||||||
|
uint8 gradientType;
|
||||||
|
uint8 gradientFlags;
|
||||||
|
uint8 gradientStopCount;
|
||||||
|
if (!buffer.Read(gradientType)
|
||||||
|
|| !buffer.Read(gradientFlags)
|
||||||
|
|| !buffer.Read(gradientStopCount)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Gradient gradient(true);
|
||||||
|
// empty gradient
|
||||||
|
|
||||||
|
gradient.SetType((gradient_type)gradientType);
|
||||||
|
// TODO: support more stuff with flags
|
||||||
|
// ("inherits transformation" and so on)
|
||||||
|
if (gradientFlags & GRADIENT_FLAG_TRANSFORM) {
|
||||||
|
if (!_ReadTransformable(buffer, &gradient))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool alpha = !(gradientFlags & GRADIENT_FLAG_NO_ALPHA);
|
||||||
|
|
||||||
|
for (int32 i = 0; i < gradientStopCount; i++) {
|
||||||
|
uint8 stopOffset;
|
||||||
|
rgb_color color;
|
||||||
|
|
||||||
|
if (!buffer.Read(stopOffset))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (alpha) {
|
||||||
|
if (!buffer.Read((uint32&)color))
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
color.alpha = 255;
|
||||||
|
if (!buffer.Read(color.red)
|
||||||
|
|| !buffer.Read(color.green)
|
||||||
|
|| !buffer.Read(color.blue)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gradient.AddColor(color, stopOffset / 255.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
style->SetGradient(&gradient);
|
||||||
|
|
||||||
|
styleDeleter.Detach();
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _ParseStyles
|
||||||
|
status_t
|
||||||
|
FlatIconImporter::_ParseStyles(LittleEndianBuffer& buffer,
|
||||||
|
StyleContainer* styles)
|
||||||
|
{
|
||||||
|
uint8 styleCount;
|
||||||
|
if (!buffer.Read(styleCount))
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
for (int32 i = 0; i < styleCount; i++) {
|
||||||
|
uint8 styleType;
|
||||||
|
if (!buffer.Read(styleType))
|
||||||
|
return B_ERROR;
|
||||||
|
Style* style = NULL;
|
||||||
|
if (styleType == TAG_STYLE_SOLID_COLOR) {
|
||||||
|
// solid color
|
||||||
|
style = _ReadColorStyle(buffer, true);
|
||||||
|
if (!style)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
} else if (styleType == TAG_STYLE_SOLID_COLOR_NO_ALPHA) {
|
||||||
|
// solid color without alpha
|
||||||
|
style = _ReadColorStyle(buffer, false);
|
||||||
|
if (!style)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
} else if (styleType == TAG_STYLE_GRADIENT) {
|
||||||
|
// gradient
|
||||||
|
style = _ReadGradientStyle(buffer);
|
||||||
|
if (!style)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
} else {
|
||||||
|
// unkown style type, skip tag
|
||||||
|
uint16 tagLength;
|
||||||
|
if (!buffer.Read(tagLength))
|
||||||
|
return B_ERROR;
|
||||||
|
buffer.Skip(tagLength);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// add style if we were able to read one
|
||||||
|
if (style && !styles->AddStyle(style)) {
|
||||||
|
delete style;
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read_path_no_curves
|
||||||
|
static bool
|
||||||
|
read_path_no_curves(LittleEndianBuffer& buffer, VectorPath* path,
|
||||||
|
uint8 pointCount)
|
||||||
|
{
|
||||||
|
for (uint32 p = 0; p < pointCount; p++) {
|
||||||
|
BPoint point;
|
||||||
|
if (!read_coord(buffer, point.x)
|
||||||
|
|| !read_coord(buffer, point.y))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!path->AddPoint(point))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read_path_curves
|
||||||
|
static bool
|
||||||
|
read_path_curves(LittleEndianBuffer& buffer, VectorPath* path,
|
||||||
|
uint8 pointCount)
|
||||||
|
{
|
||||||
|
for (uint32 p = 0; p < pointCount; p++) {
|
||||||
|
BPoint point;
|
||||||
|
if (!read_coord(buffer, point.x)
|
||||||
|
|| !read_coord(buffer, point.y))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
BPoint pointIn;
|
||||||
|
if (!read_coord(buffer, pointIn.x)
|
||||||
|
|| !read_coord(buffer, pointIn.y))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
BPoint pointOut;
|
||||||
|
if (!read_coord(buffer, pointOut.x)
|
||||||
|
|| !read_coord(buffer, pointOut.y))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!path->AddPoint(point, pointIn, pointOut, false))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read_path_with_commands
|
||||||
|
static bool
|
||||||
|
read_path_with_commands(LittleEndianBuffer& buffer, VectorPath* path,
|
||||||
|
uint8 pointCount)
|
||||||
|
{
|
||||||
|
PathCommandQueue queue;
|
||||||
|
return queue.Read(buffer, path, pointCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// _ParsePaths
|
||||||
|
status_t
|
||||||
|
FlatIconImporter::_ParsePaths(LittleEndianBuffer& buffer,
|
||||||
|
PathContainer* paths)
|
||||||
|
{
|
||||||
|
uint8 pathCount;
|
||||||
|
if (!buffer.Read(pathCount))
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
for (int32 i = 0; i < pathCount; i++) {
|
||||||
|
uint8 pathFlags;
|
||||||
|
uint8 pointCount;
|
||||||
|
if (!buffer.Read(pathFlags) || !buffer.Read(pointCount))
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
VectorPath* path = new (nothrow) VectorPath();
|
||||||
|
if (!path)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
// chose path reading strategy depending on path flags
|
||||||
|
bool error = false;
|
||||||
|
if (pathFlags & PATH_FLAGS_NO_CURVES) {
|
||||||
|
if (!read_path_no_curves(buffer, path, pointCount))
|
||||||
|
error = true;
|
||||||
|
} else if (pathFlags & PATH_FLAGS_USES_COMMANDS) {
|
||||||
|
if (!read_path_with_commands(buffer, path, pointCount))
|
||||||
|
error = true;
|
||||||
|
} else {
|
||||||
|
if (!read_path_curves(buffer, path, pointCount))
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
delete path;
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
// post process path to clean it up
|
||||||
|
path->CleanUp();
|
||||||
|
if (pathFlags & PATH_FLAGS_CLOSED)
|
||||||
|
path->SetClosed(true);
|
||||||
|
// add path to container
|
||||||
|
if (!paths->AddPath(path)) {
|
||||||
|
delete path;
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _ReadTransformer
|
||||||
|
static Transformer*
|
||||||
|
_ReadTransformer(LittleEndianBuffer& buffer, VertexSource& source)
|
||||||
|
{
|
||||||
|
uint8 transformerType;
|
||||||
|
if (!buffer.Read(transformerType))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
switch (transformerType) {
|
||||||
|
case TAG_TRANSFORMER_AFFINE: {
|
||||||
|
AffineTransformer* affine
|
||||||
|
= new (nothrow) AffineTransformer(source);
|
||||||
|
if (!affine)
|
||||||
|
return NULL;
|
||||||
|
double matrix[6];
|
||||||
|
for (int32 i = 0; i < 6; i++) {
|
||||||
|
float value;
|
||||||
|
if (!buffer.Read(value)) {
|
||||||
|
delete affine;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
matrix[i] = value;
|
||||||
|
}
|
||||||
|
affine->load_from(matrix);
|
||||||
|
return affine;
|
||||||
|
}
|
||||||
|
case TAG_TRANSFORMER_CONTOUR: {
|
||||||
|
ContourTransformer* contour
|
||||||
|
= new (nothrow) ContourTransformer(source);
|
||||||
|
uint8 width;
|
||||||
|
uint8 lineJoin;
|
||||||
|
uint8 miterLimit;
|
||||||
|
if (!contour
|
||||||
|
|| !buffer.Read(width)
|
||||||
|
|| !buffer.Read(lineJoin)
|
||||||
|
|| !buffer.Read(miterLimit)) {
|
||||||
|
delete contour;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
contour->width(width - 128.0);
|
||||||
|
contour->line_join((agg::line_join_e)lineJoin);
|
||||||
|
contour->miter_limit(miterLimit);
|
||||||
|
return contour;
|
||||||
|
}
|
||||||
|
case TAG_TRANSFORMER_PERSPECTIVE: {
|
||||||
|
PerspectiveTransformer* perspective
|
||||||
|
= new (nothrow) PerspectiveTransformer(source);
|
||||||
|
// TODO: upgrade AGG to be able to support storage of
|
||||||
|
// trans_perspective
|
||||||
|
return perspective;
|
||||||
|
}
|
||||||
|
case TAG_TRANSFORMER_STROKE: {
|
||||||
|
StrokeTransformer* stroke
|
||||||
|
= new (nothrow) StrokeTransformer(source);
|
||||||
|
uint8 width;
|
||||||
|
uint8 lineJoin;
|
||||||
|
uint8 lineCap;
|
||||||
|
uint8 miterLimit;
|
||||||
|
// uint8 shorten;
|
||||||
|
if (!stroke
|
||||||
|
|| !buffer.Read(width)
|
||||||
|
|| !buffer.Read(lineJoin)
|
||||||
|
|| !buffer.Read(lineCap)
|
||||||
|
|| !buffer.Read(miterLimit)) {
|
||||||
|
delete stroke;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
stroke->width(width - 128.0);
|
||||||
|
stroke->line_join((agg::line_join_e)lineJoin);
|
||||||
|
stroke->line_cap((agg::line_cap_e)lineCap);
|
||||||
|
stroke->miter_limit(miterLimit);
|
||||||
|
return stroke;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// unkown transformer, skip tag
|
||||||
|
uint16 tagLength;
|
||||||
|
if (!buffer.Read(tagLength))
|
||||||
|
return NULL;
|
||||||
|
buffer.Skip(tagLength);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// _ReadPathSourceShape
|
||||||
|
static Shape*
|
||||||
|
_ReadPathSourceShape(LittleEndianBuffer& buffer,
|
||||||
|
StyleContainer* styles, PathContainer* paths)
|
||||||
|
{
|
||||||
|
// find out which style this shape uses
|
||||||
|
uint8 styleIndex;
|
||||||
|
uint8 pathCount;
|
||||||
|
if (!buffer.Read(styleIndex) || !buffer.Read(pathCount))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
Style* style = styles->StyleAt(styleIndex);
|
||||||
|
if (!style) {
|
||||||
|
printf("_ReadPathSourceShape() - "
|
||||||
|
"shape references non-existing style %d\n", styleIndex);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the shape
|
||||||
|
Shape* shape = new (nothrow) Shape(style);
|
||||||
|
ObjectDeleter<Shape> shapeDeleter(shape);
|
||||||
|
|
||||||
|
if (!shape || shape->InitCheck() < B_OK)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// find out which paths this shape uses
|
||||||
|
for (uint32 i = 0; i < pathCount; i++) {
|
||||||
|
uint8 pathIndex;
|
||||||
|
if (!buffer.Read(pathIndex))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
VectorPath* path = paths->PathAt(pathIndex);
|
||||||
|
if (!path) {
|
||||||
|
printf("_ReadPathSourceShape() - "
|
||||||
|
"shape references non-existing path %d\n", pathIndex);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
shape->Paths()->AddPath(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// shape flags
|
||||||
|
uint8 shapeFlags;
|
||||||
|
if (!buffer.Read(shapeFlags))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
shape->SetHinting(shapeFlags & SHAPE_FLAG_HINTING);
|
||||||
|
|
||||||
|
if (shapeFlags & SHAPE_FLAG_TRANSFORM) {
|
||||||
|
// transformation
|
||||||
|
if (!_ReadTransformable(buffer, shape))
|
||||||
|
return NULL;
|
||||||
|
} else if (shapeFlags & SHAPE_FLAG_TRANSLATION) {
|
||||||
|
// translation
|
||||||
|
if (!_ReadTranslation(buffer, shape))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shapeFlags & SHAPE_FLAG_LOD_SCALE) {
|
||||||
|
// min max visibility scale
|
||||||
|
uint8 minScale;
|
||||||
|
uint8 maxScale;
|
||||||
|
if (!buffer.Read(minScale) || !buffer.Read(maxScale))
|
||||||
|
return NULL;
|
||||||
|
shape->SetMinVisibilityScale((float)minScale);
|
||||||
|
shape->SetMaxVisibilityScale((float)maxScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
// transformers
|
||||||
|
if (shapeFlags & SHAPE_FLAG_HAS_TRANSFORMERS) {
|
||||||
|
uint8 transformerCount;
|
||||||
|
if (!buffer.Read(transformerCount))
|
||||||
|
return NULL;
|
||||||
|
for (uint32 i = 0; i < transformerCount; i++) {
|
||||||
|
Transformer* transformer
|
||||||
|
= _ReadTransformer(buffer, shape->VertexSource());
|
||||||
|
if (transformer && !shape->AddTransformer(transformer)) {
|
||||||
|
delete transformer;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shapeDeleter.Detach();
|
||||||
|
return shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _ParseShapes
|
||||||
|
status_t
|
||||||
|
FlatIconImporter::_ParseShapes(LittleEndianBuffer& buffer,
|
||||||
|
StyleContainer* styles,
|
||||||
|
PathContainer* paths,
|
||||||
|
ShapeContainer* shapes)
|
||||||
|
{
|
||||||
|
uint8 shapeCount;
|
||||||
|
if (!buffer.Read(shapeCount))
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < shapeCount; i++) {
|
||||||
|
uint8 shapeType;
|
||||||
|
if (!buffer.Read(shapeType))
|
||||||
|
return B_ERROR;
|
||||||
|
Shape* shape = NULL;
|
||||||
|
if (shapeType == TAG_SHAPE_PATH_SOURCE) {
|
||||||
|
// path source shape
|
||||||
|
shape = _ReadPathSourceShape(buffer, styles, paths);
|
||||||
|
if (!shape)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
} else {
|
||||||
|
// unkown shape type, skip tag
|
||||||
|
uint16 tagLength;
|
||||||
|
if (!buffer.Read(tagLength))
|
||||||
|
return B_ERROR;
|
||||||
|
buffer.Skip(tagLength);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// add shape if we were able to read one
|
||||||
|
if (shape && !shapes->AddShape(shape)) {
|
||||||
|
delete shape;
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FLAT_ICON_IMPORTER_H
|
||||||
|
#define FLAT_ICON_IMPORTER_H
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
class BMessage;
|
||||||
|
class BPositionIO;
|
||||||
|
class Icon;
|
||||||
|
class LittleEndianBuffer;
|
||||||
|
class PathContainer;
|
||||||
|
class ShapeContainer;
|
||||||
|
class StyleContainer;
|
||||||
|
|
||||||
|
class FlatIconImporter {
|
||||||
|
public:
|
||||||
|
FlatIconImporter();
|
||||||
|
virtual ~FlatIconImporter();
|
||||||
|
|
||||||
|
// Importer interface (Importer base not yet written)
|
||||||
|
virtual status_t Import(Icon* icon,
|
||||||
|
BPositionIO* stream);
|
||||||
|
|
||||||
|
// FlatIconImporter
|
||||||
|
status_t Import(Icon* icon,
|
||||||
|
uint8* buffer, size_t size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t _ParseSections(LittleEndianBuffer& buffer,
|
||||||
|
Icon* icon);
|
||||||
|
|
||||||
|
status_t _ParseStyles(LittleEndianBuffer& buffer,
|
||||||
|
StyleContainer* styles);
|
||||||
|
status_t _ParsePaths(LittleEndianBuffer& buffer,
|
||||||
|
PathContainer* paths);
|
||||||
|
status_t _ParseShapes(LittleEndianBuffer& buffer,
|
||||||
|
StyleContainer* styles,
|
||||||
|
PathContainer* paths,
|
||||||
|
ShapeContainer* shapes);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FLAT_ICON_IMPORTER_H
|
||||||
@@ -0,0 +1,289 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "LittleEndianBuffer.h"
|
||||||
|
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <ByteOrder.h>
|
||||||
|
|
||||||
|
#define CHUNK_SIZE 256
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
LittleEndianBuffer::LittleEndianBuffer()
|
||||||
|
: fBuffer((uint8*)malloc(CHUNK_SIZE)),
|
||||||
|
fHandle(fBuffer),
|
||||||
|
fBufferEnd(fBuffer + CHUNK_SIZE),
|
||||||
|
fSize(CHUNK_SIZE),
|
||||||
|
fOwnsBuffer(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
LittleEndianBuffer::LittleEndianBuffer(size_t size)
|
||||||
|
: fBuffer((uint8*)malloc(size)),
|
||||||
|
fHandle(fBuffer),
|
||||||
|
fBufferEnd(fBuffer + size),
|
||||||
|
fSize(size),
|
||||||
|
fOwnsBuffer(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
LittleEndianBuffer::LittleEndianBuffer(uint8* buffer, size_t size)
|
||||||
|
: fBuffer(buffer),
|
||||||
|
fHandle(fBuffer),
|
||||||
|
fBufferEnd(fBuffer + size),
|
||||||
|
fSize(size),
|
||||||
|
fOwnsBuffer(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
LittleEndianBuffer::~LittleEndianBuffer()
|
||||||
|
{
|
||||||
|
if (fOwnsBuffer)
|
||||||
|
free(fBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write 8
|
||||||
|
bool
|
||||||
|
LittleEndianBuffer::Write(uint8 value)
|
||||||
|
{
|
||||||
|
if (fHandle == fBufferEnd)
|
||||||
|
_SetSize(fSize + CHUNK_SIZE);
|
||||||
|
|
||||||
|
if (!fBuffer)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*fHandle = value;
|
||||||
|
fHandle++;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write 16
|
||||||
|
bool
|
||||||
|
LittleEndianBuffer::Write(uint16 value)
|
||||||
|
{
|
||||||
|
if ((fHandle + 1) >= fBufferEnd)
|
||||||
|
_SetSize(fSize + CHUNK_SIZE);
|
||||||
|
|
||||||
|
if (!fBuffer)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*(uint16*)fHandle = B_HOST_TO_LENDIAN_INT16(value);
|
||||||
|
fHandle += 2;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write 32
|
||||||
|
bool
|
||||||
|
LittleEndianBuffer::Write(uint32 value)
|
||||||
|
{
|
||||||
|
if ((fHandle + 3) >= fBufferEnd)
|
||||||
|
_SetSize(fSize + CHUNK_SIZE);
|
||||||
|
|
||||||
|
if (!fBuffer)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*(uint32*)fHandle = B_HOST_TO_LENDIAN_INT32(value);
|
||||||
|
fHandle += 4;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write double
|
||||||
|
bool
|
||||||
|
LittleEndianBuffer::Write(float value)
|
||||||
|
{
|
||||||
|
if ((fHandle + sizeof(float) - 1) >= fBufferEnd)
|
||||||
|
_SetSize(fSize + CHUNK_SIZE);
|
||||||
|
|
||||||
|
if (!fBuffer)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*(float*)fHandle = B_HOST_TO_LENDIAN_FLOAT(value);
|
||||||
|
fHandle += sizeof(float);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write double
|
||||||
|
bool
|
||||||
|
LittleEndianBuffer::Write(double value)
|
||||||
|
{
|
||||||
|
if ((fHandle + sizeof(double) - 1) >= fBufferEnd)
|
||||||
|
_SetSize(fSize + CHUNK_SIZE);
|
||||||
|
|
||||||
|
if (!fBuffer)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*(double*)fHandle = B_HOST_TO_LENDIAN_DOUBLE(value);
|
||||||
|
fHandle += sizeof(double);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write LittleEndianBuffer
|
||||||
|
bool
|
||||||
|
LittleEndianBuffer::Write(const LittleEndianBuffer& other)
|
||||||
|
{
|
||||||
|
return Write(other.Buffer(), other.SizeUsed());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write buffer
|
||||||
|
bool
|
||||||
|
LittleEndianBuffer::Write(const uint8* buffer, size_t bytes)
|
||||||
|
{
|
||||||
|
if (bytes == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// figure out needed size and suitable new size
|
||||||
|
size_t neededSize = SizeUsed() + bytes;
|
||||||
|
size_t newSize = fSize;
|
||||||
|
while (newSize < neededSize)
|
||||||
|
newSize += CHUNK_SIZE;
|
||||||
|
|
||||||
|
// resize if necessary
|
||||||
|
if (newSize > fSize)
|
||||||
|
_SetSize(newSize);
|
||||||
|
|
||||||
|
if (!fBuffer)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// paste buffer
|
||||||
|
memcpy(fHandle, buffer, bytes);
|
||||||
|
fHandle += bytes;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// Read 8
|
||||||
|
bool
|
||||||
|
LittleEndianBuffer::Read(uint8& value)
|
||||||
|
{
|
||||||
|
if (fHandle >= fBufferEnd)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
value = *fHandle++;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read 16
|
||||||
|
bool
|
||||||
|
LittleEndianBuffer::Read(uint16& value)
|
||||||
|
{
|
||||||
|
if ((fHandle + 1) >= fBufferEnd)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
value = B_LENDIAN_TO_HOST_INT16(*(uint16*)fHandle);
|
||||||
|
fHandle += 2;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read 32
|
||||||
|
bool
|
||||||
|
LittleEndianBuffer::Read(uint32& value)
|
||||||
|
{
|
||||||
|
if ((fHandle + 3) >= fBufferEnd)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
value = B_LENDIAN_TO_HOST_INT32(*(uint32*)fHandle);
|
||||||
|
fHandle += 4;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read float
|
||||||
|
bool
|
||||||
|
LittleEndianBuffer::Read(float& value)
|
||||||
|
{
|
||||||
|
if ((fHandle + sizeof(float) - 1) >= fBufferEnd)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
value = B_LENDIAN_TO_HOST_FLOAT(*(float*)fHandle);
|
||||||
|
fHandle += sizeof(float);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read double
|
||||||
|
bool
|
||||||
|
LittleEndianBuffer::Read(double& value)
|
||||||
|
{
|
||||||
|
if ((fHandle + sizeof(double) - 1) >= fBufferEnd)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
value = B_LENDIAN_TO_HOST_DOUBLE(*(double*)fHandle);
|
||||||
|
fHandle += sizeof(double);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read LittleEndianBuffer
|
||||||
|
bool
|
||||||
|
LittleEndianBuffer::Read(LittleEndianBuffer& other, size_t bytes)
|
||||||
|
{
|
||||||
|
if ((fHandle + bytes - 1) >= fBufferEnd)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (other.Write(fHandle, bytes)) {
|
||||||
|
// reset other handle to beginning of pasted data
|
||||||
|
other.fHandle -= bytes;
|
||||||
|
fHandle += bytes;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// Skip
|
||||||
|
void
|
||||||
|
LittleEndianBuffer::Skip(size_t bytes)
|
||||||
|
{
|
||||||
|
// NOTE: is ment to be used while reading!!
|
||||||
|
// when used while writing, the growing will not work reliably
|
||||||
|
fHandle += bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset
|
||||||
|
void
|
||||||
|
LittleEndianBuffer::Reset()
|
||||||
|
{
|
||||||
|
fHandle = fBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// _SetSize
|
||||||
|
void
|
||||||
|
LittleEndianBuffer::_SetSize(size_t size)
|
||||||
|
{
|
||||||
|
if (!fOwnsBuffer) {
|
||||||
|
// prevent user error
|
||||||
|
// (we are in read mode)
|
||||||
|
fBuffer = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 pos = fHandle - fBuffer;
|
||||||
|
fBuffer = (uint8*)realloc((void*)fBuffer, size);
|
||||||
|
fHandle = fBuffer + pos;
|
||||||
|
fBufferEnd = fBuffer + size;
|
||||||
|
fSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LITTLE_ENDIAN_BUFFER_H
|
||||||
|
#define LITTLE_ENDIAN_BUFFER_H
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
class LittleEndianBuffer {
|
||||||
|
public:
|
||||||
|
LittleEndianBuffer();
|
||||||
|
LittleEndianBuffer(size_t size);
|
||||||
|
LittleEndianBuffer(uint8* buffer,
|
||||||
|
size_t size);
|
||||||
|
~LittleEndianBuffer();
|
||||||
|
|
||||||
|
bool Write(uint8 value);
|
||||||
|
bool Write(uint16 value);
|
||||||
|
bool Write(uint32 value);
|
||||||
|
bool Write(float value);
|
||||||
|
bool Write(double value);
|
||||||
|
|
||||||
|
bool Write(const LittleEndianBuffer& other);
|
||||||
|
bool Write(const uint8* buffer, size_t bytes);
|
||||||
|
|
||||||
|
bool Read(uint8& value);
|
||||||
|
bool Read(uint16& value);
|
||||||
|
bool Read(uint32& value);
|
||||||
|
bool Read(float& value);
|
||||||
|
bool Read(double& value);
|
||||||
|
bool Read(LittleEndianBuffer& other, size_t bytes);
|
||||||
|
|
||||||
|
void Skip(size_t bytes);
|
||||||
|
|
||||||
|
uint8* Buffer() const
|
||||||
|
{ return fBuffer; }
|
||||||
|
size_t SizeUsed() const
|
||||||
|
{ return fHandle - fBuffer; }
|
||||||
|
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _SetSize(size_t size);
|
||||||
|
|
||||||
|
uint8* fBuffer;
|
||||||
|
uint8* fHandle;
|
||||||
|
uint8* fBufferEnd;
|
||||||
|
size_t fSize;
|
||||||
|
bool fOwnsBuffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LITTLE_ENDIAN_BUFFER_H
|
||||||
@@ -0,0 +1,264 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PathCommandQueue.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <Point.h>
|
||||||
|
|
||||||
|
#include "FlatIconFormat.h"
|
||||||
|
#include "VectorPath.h"
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
PathCommandQueue::PathCommandQueue()
|
||||||
|
: fCommandBuffer(),
|
||||||
|
fPointBuffer(),
|
||||||
|
|
||||||
|
fCommandByte(0),
|
||||||
|
fCommandPos(0),
|
||||||
|
|
||||||
|
fCommandCount(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
PathCommandQueue::~PathCommandQueue()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write
|
||||||
|
bool
|
||||||
|
PathCommandQueue::Write(LittleEndianBuffer& buffer,
|
||||||
|
const VectorPath* path, uint8 pointCount)
|
||||||
|
{
|
||||||
|
// reset
|
||||||
|
fCommandCount = 0;
|
||||||
|
fCommandByte = 0;
|
||||||
|
fCommandPos = 0;
|
||||||
|
fCommandBuffer.Reset();
|
||||||
|
fPointBuffer.Reset();
|
||||||
|
|
||||||
|
BPoint last(B_ORIGIN);
|
||||||
|
|
||||||
|
for (uint32 p = 0; p < pointCount; p++) {
|
||||||
|
BPoint point;
|
||||||
|
BPoint pointIn;
|
||||||
|
BPoint pointOut;
|
||||||
|
if (!path->GetPointsAt(p, point, pointIn, pointOut))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (point == pointIn && point == pointOut) {
|
||||||
|
// single point is sufficient
|
||||||
|
if (point.x == last.x) {
|
||||||
|
// vertical line
|
||||||
|
if (!_AppendVLine(point.y))
|
||||||
|
return false;
|
||||||
|
} else if (point.y == last.y) {
|
||||||
|
// horizontal line
|
||||||
|
if (!_AppendHLine(point.x))
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
// line
|
||||||
|
if (!_AppendLine(point))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// needing to write all three points
|
||||||
|
if (!_AppendCurve(point, pointIn, pointOut))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
last = point;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fCommandPos > 0) {
|
||||||
|
// the last couple commands have not been written
|
||||||
|
if (!fCommandBuffer.Write(fCommandByte))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer.Write(fCommandBuffer) && buffer.Write(fPointBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read
|
||||||
|
bool
|
||||||
|
PathCommandQueue::Read(LittleEndianBuffer& buffer,
|
||||||
|
VectorPath* path, uint8 pointCount)
|
||||||
|
{
|
||||||
|
// reset
|
||||||
|
fCommandCount = 0;
|
||||||
|
fCommandByte = 0;
|
||||||
|
fCommandPos = 0;
|
||||||
|
|
||||||
|
fCommandBuffer.Reset();
|
||||||
|
|
||||||
|
// NOTE: fPointBuffer is not used for reading
|
||||||
|
// we read the command buffer and then use the
|
||||||
|
// buffer directly for the coords
|
||||||
|
|
||||||
|
// read command buffer
|
||||||
|
uint8 commandBufferSize = (pointCount + 3) / 4;
|
||||||
|
if (!buffer.Read(fCommandBuffer, commandBufferSize))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
BPoint last(B_ORIGIN);
|
||||||
|
for (uint32 p = 0; p < pointCount; p++) {
|
||||||
|
|
||||||
|
uint8 command;
|
||||||
|
if (!_ReadCommand(command))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
BPoint point;
|
||||||
|
BPoint pointIn;
|
||||||
|
BPoint pointOut;
|
||||||
|
|
||||||
|
switch (command) {
|
||||||
|
case PATH_COMMAND_H_LINE:
|
||||||
|
if (!read_coord(buffer, point.x))
|
||||||
|
return false;
|
||||||
|
point.y = last.y;
|
||||||
|
pointIn = point;
|
||||||
|
pointOut = point;
|
||||||
|
break;
|
||||||
|
case PATH_COMMAND_V_LINE:
|
||||||
|
if (!read_coord(buffer, point.y))
|
||||||
|
return false;
|
||||||
|
point.x = last.x;
|
||||||
|
pointIn = point;
|
||||||
|
pointOut = point;
|
||||||
|
break;
|
||||||
|
case PATH_COMMAND_LINE:
|
||||||
|
if (!read_coord(buffer, point.x)
|
||||||
|
|| !read_coord(buffer, point.y))
|
||||||
|
return false;
|
||||||
|
pointIn = point;
|
||||||
|
pointOut = point;
|
||||||
|
break;
|
||||||
|
case PATH_COMMAND_CURVE:
|
||||||
|
if (!read_coord(buffer, point.x)
|
||||||
|
|| !read_coord(buffer, point.y)
|
||||||
|
|| !read_coord(buffer, pointIn.x)
|
||||||
|
|| !read_coord(buffer, pointIn.y)
|
||||||
|
|| !read_coord(buffer, pointOut.x)
|
||||||
|
|| !read_coord(buffer, pointOut.y))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!path->AddPoint(point, pointIn, pointOut, false))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
last = point;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// _AppendHLine
|
||||||
|
bool
|
||||||
|
PathCommandQueue::_AppendHLine(float x)
|
||||||
|
{
|
||||||
|
return _AppendCommand(PATH_COMMAND_H_LINE)
|
||||||
|
&& write_coord(fPointBuffer, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
// _AppendVLine
|
||||||
|
bool
|
||||||
|
PathCommandQueue::_AppendVLine(float y)
|
||||||
|
{
|
||||||
|
return _AppendCommand(PATH_COMMAND_V_LINE)
|
||||||
|
&& write_coord(fPointBuffer, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// _AppendLine
|
||||||
|
bool
|
||||||
|
PathCommandQueue::_AppendLine(const BPoint& point)
|
||||||
|
{
|
||||||
|
return _AppendCommand(PATH_COMMAND_LINE)
|
||||||
|
&& write_coord(fPointBuffer, point.x)
|
||||||
|
&& write_coord(fPointBuffer, point.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// _AppendCurve
|
||||||
|
bool
|
||||||
|
PathCommandQueue::_AppendCurve(const BPoint& point,
|
||||||
|
const BPoint& pointIn,
|
||||||
|
const BPoint& pointOut)
|
||||||
|
{
|
||||||
|
return _AppendCommand(PATH_COMMAND_CURVE)
|
||||||
|
&& write_coord(fPointBuffer, point.x)
|
||||||
|
&& write_coord(fPointBuffer, point.y)
|
||||||
|
&& write_coord(fPointBuffer, pointIn.x)
|
||||||
|
&& write_coord(fPointBuffer, pointIn.y)
|
||||||
|
&& write_coord(fPointBuffer, pointOut.x)
|
||||||
|
&& write_coord(fPointBuffer, pointOut.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// _AppendCommand
|
||||||
|
bool
|
||||||
|
PathCommandQueue::_AppendCommand(uint8 command)
|
||||||
|
{
|
||||||
|
// NOTE: a path command uses 2 bits, so 4 of
|
||||||
|
// them fit into a single byte
|
||||||
|
// after we have appended the fourth command,
|
||||||
|
// the byte is written to fCommandBuffer and
|
||||||
|
// the cycle repeats
|
||||||
|
|
||||||
|
if (fCommandCount == 255) {
|
||||||
|
printf("PathCommandQueue::_AppendCommand() - "
|
||||||
|
"maximum path section count reached\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fCommandByte |= command << fCommandPos;
|
||||||
|
fCommandPos += 2;
|
||||||
|
fCommandCount++;
|
||||||
|
|
||||||
|
if (fCommandPos == 8) {
|
||||||
|
uint8 commandByte = fCommandByte;
|
||||||
|
fCommandByte = 0;
|
||||||
|
fCommandPos = 0;
|
||||||
|
return fCommandBuffer.Write(commandByte);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// _ReadCommand
|
||||||
|
bool
|
||||||
|
PathCommandQueue::_ReadCommand(uint8& command)
|
||||||
|
{
|
||||||
|
if (fCommandCount == 255) {
|
||||||
|
printf("PathCommandQueue::_NextCommand() - "
|
||||||
|
"maximum path section count reached\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fCommandPos == 0) {
|
||||||
|
// fetch the next four commands from the buffer
|
||||||
|
if (!fCommandBuffer.Read(fCommandByte))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
command = (fCommandByte >> fCommandPos) & 0x03;
|
||||||
|
fCommandPos += 2;
|
||||||
|
fCommandCount++;
|
||||||
|
|
||||||
|
if (fCommandPos == 8)
|
||||||
|
fCommandPos = 0;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PATH_COMMAND_QUEUE_H
|
||||||
|
#define PATH_COMMAND_QUEUE_H
|
||||||
|
|
||||||
|
#include "LittleEndianBuffer.h"
|
||||||
|
|
||||||
|
class BPoint;
|
||||||
|
class VectorPath;
|
||||||
|
|
||||||
|
class PathCommandQueue {
|
||||||
|
public:
|
||||||
|
PathCommandQueue();
|
||||||
|
virtual ~PathCommandQueue();
|
||||||
|
|
||||||
|
bool Write(LittleEndianBuffer& buffer,
|
||||||
|
const VectorPath* path,
|
||||||
|
uint8 pointCount);
|
||||||
|
|
||||||
|
bool Read(LittleEndianBuffer& buffer,
|
||||||
|
VectorPath* path,
|
||||||
|
uint8 pointCount);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// writing
|
||||||
|
bool _AppendHLine(float x);
|
||||||
|
bool _AppendVLine(float y);
|
||||||
|
bool _AppendLine(const BPoint& point);
|
||||||
|
bool _AppendCurve(const BPoint& point,
|
||||||
|
const BPoint& pointIn,
|
||||||
|
const BPoint& pointOut);
|
||||||
|
|
||||||
|
bool _AppendCommand(uint8 command);
|
||||||
|
|
||||||
|
// reading
|
||||||
|
bool _ReadCommand(uint8& command);
|
||||||
|
|
||||||
|
LittleEndianBuffer fCommandBuffer;
|
||||||
|
LittleEndianBuffer fPointBuffer;
|
||||||
|
|
||||||
|
uint8 fCommandByte;
|
||||||
|
uint8 fCommandPos;
|
||||||
|
|
||||||
|
uint8 fCommandCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PATH_COMMAND_QUEUE_H
|
||||||
@@ -0,0 +1,213 @@
|
|||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
PathContainerListener::PathContainerListener() {}
|
||||||
|
PathContainerListener::~PathContainerListener() {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
PathContainer::PathContainer(bool ownsPaths)
|
||||||
|
: fPaths(16),
|
||||||
|
fOwnsPaths(ownsPaths),
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
fListeners(2)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
PathContainer::~PathContainer()
|
||||||
|
{
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
int32 count = fListeners.CountItems();
|
||||||
|
if (count > 0) {
|
||||||
|
debugger("~PathContainer() - there are still"
|
||||||
|
"listeners attached\n");
|
||||||
|
}
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
_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)) {
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
_NotifyPathAdded(path);
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "PathContainer::AddPath() - out of memory!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemovePath
|
||||||
|
bool
|
||||||
|
PathContainer::RemovePath(VectorPath* path)
|
||||||
|
{
|
||||||
|
if (fPaths.RemoveItem((void*)path)) {
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
_NotifyPathRemoved(path);
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemovePath
|
||||||
|
VectorPath*
|
||||||
|
PathContainer::RemovePath(int32 index)
|
||||||
|
{
|
||||||
|
VectorPath* path = (VectorPath*)fPaths.RemoveItem(index);
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
if (path) {
|
||||||
|
_NotifyPathRemoved(path);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// IndexOf
|
||||||
|
int32
|
||||||
|
PathContainer::IndexOf(VectorPath* path) const
|
||||||
|
{
|
||||||
|
return fPaths.IndexOf((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 -
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// _MakeEmpty
|
||||||
|
void
|
||||||
|
PathContainer::_MakeEmpty()
|
||||||
|
{
|
||||||
|
int32 count = CountPaths();
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
VectorPath* path = PathAtFast(i);
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
_NotifyPathRemoved(path);
|
||||||
|
if (fOwnsPaths)
|
||||||
|
path->Release();
|
||||||
|
#else
|
||||||
|
if (fOwnsPaths)
|
||||||
|
delete path;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
fPaths.MakeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// _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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
class PathContainerListener {
|
||||||
|
public:
|
||||||
|
PathContainerListener();
|
||||||
|
virtual ~PathContainerListener();
|
||||||
|
|
||||||
|
virtual void PathAdded(VectorPath* path) = 0;
|
||||||
|
virtual void PathRemoved(VectorPath* path) = 0;
|
||||||
|
};
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
class PathContainer {
|
||||||
|
public:
|
||||||
|
PathContainer(bool ownsPaths);
|
||||||
|
virtual ~PathContainer();
|
||||||
|
|
||||||
|
bool AddPath(VectorPath* path);
|
||||||
|
bool RemovePath(VectorPath* path);
|
||||||
|
VectorPath* RemovePath(int32 index);
|
||||||
|
|
||||||
|
void MakeEmpty();
|
||||||
|
|
||||||
|
int32 CountPaths() const;
|
||||||
|
bool HasPath(VectorPath* path) const;
|
||||||
|
int32 IndexOf(VectorPath* path) const;
|
||||||
|
|
||||||
|
VectorPath* PathAt(int32 index) const;
|
||||||
|
VectorPath* PathAtFast(int32 index) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _MakeEmpty();
|
||||||
|
|
||||||
|
BList fPaths;
|
||||||
|
bool fOwnsPaths;
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
public:
|
||||||
|
bool AddListener(PathContainerListener* listener);
|
||||||
|
bool RemoveListener(PathContainerListener* listener);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _NotifyPathAdded(VectorPath* path) const;
|
||||||
|
void _NotifyPathRemoved(VectorPath* path) const;
|
||||||
|
|
||||||
|
BList fListeners;
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PATH_CONTAINER_H
|
||||||
@@ -0,0 +1,676 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Shape.h"
|
||||||
|
|
||||||
|
#include <Message.h>
|
||||||
|
#include <TypeConstants.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "agg_bounding_rect.h"
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
# include "CommonPropertyIDs.h"
|
||||||
|
# include "Property.h"
|
||||||
|
# include "PropertyObject.h"
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
#include "Style.h"
|
||||||
|
#include "TransformerFactory.h"
|
||||||
|
|
||||||
|
using std::nothrow;
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// constructor
|
||||||
|
ShapeListener::ShapeListener()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
ShapeListener::~ShapeListener()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
Shape::Shape(::Style* style)
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
: IconObject("<shape>"),
|
||||||
|
Transformable(),
|
||||||
|
Observer(),
|
||||||
|
PathContainerListener(),
|
||||||
|
#else
|
||||||
|
: Transformable(),
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fPaths(new (nothrow) PathContainer(false)),
|
||||||
|
fStyle(NULL),
|
||||||
|
|
||||||
|
fPathSource(fPaths),
|
||||||
|
fTransformers(4),
|
||||||
|
fNeedsUpdate(true),
|
||||||
|
|
||||||
|
fLastBounds(0, 0, -1, -1),
|
||||||
|
|
||||||
|
fHinting(false),
|
||||||
|
fMinVisibilityScale(0.0),
|
||||||
|
fMaxVisibilityScale(255.0)
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
, fListeners(8)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
SetStyle(style);
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
if (fPaths)
|
||||||
|
fPaths->AddListener(this);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
Shape::Shape(const Shape& other)
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
: IconObject(other),
|
||||||
|
Transformable(other),
|
||||||
|
Observer(),
|
||||||
|
PathContainerListener(),
|
||||||
|
#else
|
||||||
|
: Transformable(other),
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fPaths(new (nothrow) PathContainer(false)),
|
||||||
|
fStyle(NULL),
|
||||||
|
|
||||||
|
fPathSource(fPaths),
|
||||||
|
fTransformers(4),
|
||||||
|
fNeedsUpdate(true),
|
||||||
|
|
||||||
|
fLastBounds(0, 0, -1, -1),
|
||||||
|
|
||||||
|
fHinting(other.fHinting),
|
||||||
|
fMinVisibilityScale(other.fMinVisibilityScale),
|
||||||
|
fMaxVisibilityScale(other.fMaxVisibilityScale)
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
, fListeners(8)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
SetStyle(other.fStyle);
|
||||||
|
|
||||||
|
if (fPaths) {
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
fPaths->AddListener(this);
|
||||||
|
#endif
|
||||||
|
// copy the path references from
|
||||||
|
// the other shape
|
||||||
|
if (other.fPaths) {
|
||||||
|
int32 count = other.fPaths->CountPaths();
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
if (!fPaths->AddPath(other.fPaths->PathAtFast(i)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// clone vertex transformers
|
||||||
|
int32 count = other.CountTransformers();
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
Transformer* original = other.TransformerAtFast(i);
|
||||||
|
Transformer* cloned = original->Clone(fPathSource);
|
||||||
|
if (!AddTransformer(cloned)) {
|
||||||
|
delete cloned;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
Shape::~Shape()
|
||||||
|
{
|
||||||
|
int32 count = fTransformers.CountItems();
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
Transformer* t = (Transformer*)fTransformers.ItemAtFast(i);
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
t->RemoveObserver(this);
|
||||||
|
_NotifyTransformerRemoved(t);
|
||||||
|
#endif
|
||||||
|
delete t;
|
||||||
|
}
|
||||||
|
|
||||||
|
fPaths->MakeEmpty();
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
fPaths->RemoveListener(this);
|
||||||
|
#endif
|
||||||
|
delete fPaths;
|
||||||
|
|
||||||
|
SetStyle(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
|
||||||
|
// Unarchive
|
||||||
|
status_t
|
||||||
|
Shape::Unarchive(const BMessage* archive)
|
||||||
|
{
|
||||||
|
// IconObject properties
|
||||||
|
status_t ret = IconObject::Unarchive(archive);
|
||||||
|
if (ret < B_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
// recreate transformers
|
||||||
|
BMessage transformerArchive;
|
||||||
|
for (int32 i = 0;
|
||||||
|
archive->FindMessage("transformer", i,
|
||||||
|
&transformerArchive) == B_OK;
|
||||||
|
i++) {
|
||||||
|
Transformer* transformer
|
||||||
|
= TransformerFactory::TransformerFor(
|
||||||
|
&transformerArchive, VertexSource());
|
||||||
|
if (!transformer || !AddTransformer(transformer)) {
|
||||||
|
delete transformer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// read transformation
|
||||||
|
int32 size = Transformable::matrix_size;
|
||||||
|
const void* matrix;
|
||||||
|
ssize_t dataSize = size * sizeof(double);
|
||||||
|
ret = archive->FindData("transformation", B_DOUBLE_TYPE,
|
||||||
|
&matrix, &dataSize);
|
||||||
|
if (ret == B_OK && dataSize == (ssize_t)(size * sizeof(double)))
|
||||||
|
LoadFrom((const double*)matrix);
|
||||||
|
|
||||||
|
// hinting
|
||||||
|
if (archive->FindBool("hinting", &fHinting) < B_OK)
|
||||||
|
fHinting = false;
|
||||||
|
|
||||||
|
// min visibility scale
|
||||||
|
if (archive->FindFloat("min visibility scale",
|
||||||
|
&fMinVisibilityScale) < B_OK)
|
||||||
|
fMinVisibilityScale = 0.0;
|
||||||
|
|
||||||
|
// max visibility scale
|
||||||
|
if (archive->FindFloat("max visibility scale",
|
||||||
|
&fMaxVisibilityScale) < B_OK)
|
||||||
|
fMaxVisibilityScale = 255.0;
|
||||||
|
|
||||||
|
if (fMinVisibilityScale < 0.0)
|
||||||
|
fMinVisibilityScale = 0.0;
|
||||||
|
if (fMinVisibilityScale > 255.0)
|
||||||
|
fMinVisibilityScale = 255.0;
|
||||||
|
if (fMaxVisibilityScale < 0.0)
|
||||||
|
fMaxVisibilityScale = 0.0;
|
||||||
|
if (fMaxVisibilityScale > 255.0)
|
||||||
|
fMaxVisibilityScale = 255.0;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Archive
|
||||||
|
status_t
|
||||||
|
Shape::Archive(BMessage* into, bool deep) const
|
||||||
|
{
|
||||||
|
status_t ret = IconObject::Archive(into, deep);
|
||||||
|
|
||||||
|
// transformers
|
||||||
|
if (ret == B_OK) {
|
||||||
|
int32 count = CountTransformers();
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
Transformer* transformer = TransformerAtFast(i);
|
||||||
|
BMessage transformerArchive;
|
||||||
|
ret = transformer->Archive(&transformerArchive);
|
||||||
|
if (ret == B_OK)
|
||||||
|
ret = into->AddMessage("transformer", &transformerArchive);
|
||||||
|
if (ret < B_OK)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// transformation
|
||||||
|
if (ret == B_OK) {
|
||||||
|
int32 size = Transformable::matrix_size;
|
||||||
|
double matrix[size];
|
||||||
|
StoreTo(matrix);
|
||||||
|
ret = into->AddData("transformation", B_DOUBLE_TYPE,
|
||||||
|
matrix, size * sizeof(double));
|
||||||
|
}
|
||||||
|
|
||||||
|
// hinting
|
||||||
|
if (ret ==B_OK)
|
||||||
|
ret = into->AddBool("hinting", fHinting);
|
||||||
|
|
||||||
|
// min visibility scale
|
||||||
|
if (ret ==B_OK)
|
||||||
|
ret = into->AddFloat("min visibility scale",
|
||||||
|
fMinVisibilityScale);
|
||||||
|
|
||||||
|
// max visibility scale
|
||||||
|
if (ret ==B_OK)
|
||||||
|
ret = into->AddFloat("max visibility scale",
|
||||||
|
fMaxVisibilityScale);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakePropertyObject
|
||||||
|
PropertyObject*
|
||||||
|
Shape::MakePropertyObject() const
|
||||||
|
{
|
||||||
|
PropertyObject* object = IconObject::MakePropertyObject();
|
||||||
|
if (!object)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
object->AddProperty(new BoolProperty(PROPERTY_HINTING, fHinting));
|
||||||
|
|
||||||
|
object->AddProperty(new FloatProperty(PROPERTY_MIN_VISIBILITY_SCALE,
|
||||||
|
fMinVisibilityScale, 0, 255));
|
||||||
|
|
||||||
|
object->AddProperty(new FloatProperty(PROPERTY_MAX_VISIBILITY_SCALE,
|
||||||
|
fMaxVisibilityScale, 0, 255));
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetToPropertyObject
|
||||||
|
bool
|
||||||
|
Shape::SetToPropertyObject(const PropertyObject* object)
|
||||||
|
{
|
||||||
|
AutoNotificationSuspender _(this);
|
||||||
|
IconObject::SetToPropertyObject(object);
|
||||||
|
|
||||||
|
// hinting
|
||||||
|
SetHinting(object->Value(PROPERTY_HINTING, fHinting));
|
||||||
|
|
||||||
|
// min visibility scale
|
||||||
|
SetMinVisibilityScale(object->Value(PROPERTY_MIN_VISIBILITY_SCALE,
|
||||||
|
fMinVisibilityScale));
|
||||||
|
|
||||||
|
// max visibility scale
|
||||||
|
SetMaxVisibilityScale(object->Value(PROPERTY_MAX_VISIBILITY_SCALE,
|
||||||
|
fMaxVisibilityScale));
|
||||||
|
|
||||||
|
return HasPendingNotifications();
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// TransformationChanged
|
||||||
|
void
|
||||||
|
Shape::TransformationChanged()
|
||||||
|
{
|
||||||
|
// TODO: notify appearance change
|
||||||
|
_NotifyRerender();
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// ObjectChanged
|
||||||
|
void
|
||||||
|
Shape::ObjectChanged(const Observable* object)
|
||||||
|
{
|
||||||
|
// simply pass on the event for now
|
||||||
|
// (a path, transformer or the style changed,
|
||||||
|
// the shape needs to be re-rendered)
|
||||||
|
_NotifyRerender();
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// PathAdded
|
||||||
|
void
|
||||||
|
Shape::PathAdded(VectorPath* path)
|
||||||
|
{
|
||||||
|
path->Acquire();
|
||||||
|
path->AddListener(this);
|
||||||
|
_NotifyRerender();
|
||||||
|
}
|
||||||
|
|
||||||
|
// PathRemoved
|
||||||
|
void
|
||||||
|
Shape::PathRemoved(VectorPath* path)
|
||||||
|
{
|
||||||
|
path->RemoveListener(this);
|
||||||
|
_NotifyRerender();
|
||||||
|
path->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// PointAdded
|
||||||
|
void
|
||||||
|
Shape::PointAdded(int32 index)
|
||||||
|
{
|
||||||
|
_NotifyRerender();
|
||||||
|
}
|
||||||
|
|
||||||
|
// PointRemoved
|
||||||
|
void
|
||||||
|
Shape::PointRemoved(int32 index)
|
||||||
|
{
|
||||||
|
_NotifyRerender();
|
||||||
|
}
|
||||||
|
|
||||||
|
// PointChanged
|
||||||
|
void
|
||||||
|
Shape::PointChanged(int32 index)
|
||||||
|
{
|
||||||
|
_NotifyRerender();
|
||||||
|
}
|
||||||
|
|
||||||
|
// PathChanged
|
||||||
|
void
|
||||||
|
Shape::PathChanged()
|
||||||
|
{
|
||||||
|
_NotifyRerender();
|
||||||
|
}
|
||||||
|
|
||||||
|
// PathClosedChanged
|
||||||
|
void
|
||||||
|
Shape::PathClosedChanged()
|
||||||
|
{
|
||||||
|
_NotifyRerender();
|
||||||
|
}
|
||||||
|
|
||||||
|
// PathReversed
|
||||||
|
void
|
||||||
|
Shape::PathReversed()
|
||||||
|
{
|
||||||
|
_NotifyRerender();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// InitCheck
|
||||||
|
status_t
|
||||||
|
Shape::InitCheck() const
|
||||||
|
{
|
||||||
|
return fPaths ? B_OK : B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// SetStyle
|
||||||
|
void
|
||||||
|
Shape::SetStyle(::Style* style)
|
||||||
|
{
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
if (fStyle == style)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (fStyle) {
|
||||||
|
fStyle->RemoveObserver(this);
|
||||||
|
fStyle->Release();
|
||||||
|
}
|
||||||
|
::Style* oldStyle = fStyle;
|
||||||
|
#else
|
||||||
|
delete fStyle;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fStyle = style;
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
if (fStyle) {
|
||||||
|
fStyle->Acquire();
|
||||||
|
fStyle->AddObserver(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
_NotifyStyleChanged(oldStyle, fStyle);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// Bounds
|
||||||
|
BRect
|
||||||
|
Shape::Bounds(bool updateLast) const
|
||||||
|
{
|
||||||
|
// TODO: what about sub-paths?!?
|
||||||
|
// the problem is that the path ids are
|
||||||
|
// nowhere stored while converting VectorPath
|
||||||
|
// to agg::path_storage, but it is also unclear
|
||||||
|
// if those would mean anything later on in
|
||||||
|
// the Transformer pipeline
|
||||||
|
uint32 pathID[1];
|
||||||
|
pathID[0] = 0;
|
||||||
|
double left, top, right, bottom;
|
||||||
|
|
||||||
|
::VertexSource& source = const_cast<Shape*>(this)->VertexSource();
|
||||||
|
agg::conv_transform< ::VertexSource, Transformable>
|
||||||
|
transformedSource(source, *this);
|
||||||
|
agg::bounding_rect(transformedSource, pathID, 0, 1,
|
||||||
|
&left, &top, &right, &bottom);
|
||||||
|
|
||||||
|
BRect bounds(left, top, right, bottom);
|
||||||
|
|
||||||
|
if (updateLast)
|
||||||
|
fLastBounds = bounds;
|
||||||
|
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
// VertexSource
|
||||||
|
::VertexSource&
|
||||||
|
Shape::VertexSource()
|
||||||
|
{
|
||||||
|
::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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fNeedsUpdate) {
|
||||||
|
fPathSource.Update(source->WantsOpenPaths(),
|
||||||
|
source->ApproximationScale());
|
||||||
|
fNeedsUpdate = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *source;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTransformer
|
||||||
|
bool
|
||||||
|
Shape::AddTransformer(Transformer* transformer)
|
||||||
|
{
|
||||||
|
return AddTransformer(transformer, CountTransformers());
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTransformer
|
||||||
|
bool
|
||||||
|
Shape::AddTransformer(Transformer* transformer, int32 index)
|
||||||
|
{
|
||||||
|
if (!transformer)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!fTransformers.AddItem((void*)transformer, index))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
transformer->AddObserver(this);
|
||||||
|
|
||||||
|
_NotifyTransformerAdded(transformer, index);
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveTransformer
|
||||||
|
bool
|
||||||
|
Shape::RemoveTransformer(Transformer* transformer)
|
||||||
|
{
|
||||||
|
if (fTransformers.RemoveItem((void*)transformer)) {
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
transformer->RemoveObserver(this);
|
||||||
|
|
||||||
|
_NotifyTransformerRemoved(transformer);
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// CountShapes
|
||||||
|
int32
|
||||||
|
Shape::CountTransformers() const
|
||||||
|
{
|
||||||
|
return fTransformers.CountItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasTransformer
|
||||||
|
bool
|
||||||
|
Shape::HasTransformer(Transformer* transformer) const
|
||||||
|
{
|
||||||
|
return fTransformers.HasItem((void*)transformer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// IndexOf
|
||||||
|
int32
|
||||||
|
Shape::IndexOf(Transformer* transformer) const
|
||||||
|
{
|
||||||
|
return fTransformers.IndexOf((void*)transformer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TransformerAt
|
||||||
|
Transformer*
|
||||||
|
Shape::TransformerAt(int32 index) const
|
||||||
|
{
|
||||||
|
return (Transformer*)fTransformers.ItemAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TransformerAtFast
|
||||||
|
Transformer*
|
||||||
|
Shape::TransformerAtFast(int32 index) const
|
||||||
|
{
|
||||||
|
return (Transformer*)fTransformers.ItemAtFast(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// SetHinting
|
||||||
|
void
|
||||||
|
Shape::SetHinting(bool hinting)
|
||||||
|
{
|
||||||
|
if (fHinting == hinting)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fHinting = hinting;
|
||||||
|
Notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMinVisibilityScale
|
||||||
|
void
|
||||||
|
Shape::SetMinVisibilityScale(float scale)
|
||||||
|
{
|
||||||
|
if (fMinVisibilityScale == scale)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fMinVisibilityScale = scale;
|
||||||
|
Notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMaxVisibilityScale
|
||||||
|
void
|
||||||
|
Shape::SetMaxVisibilityScale(float scale)
|
||||||
|
{
|
||||||
|
if (fMaxVisibilityScale == scale)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fMaxVisibilityScale = scale;
|
||||||
|
Notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
|
||||||
|
// AddListener
|
||||||
|
bool
|
||||||
|
Shape::AddListener(ShapeListener* listener)
|
||||||
|
{
|
||||||
|
if (listener && !fListeners.HasItem((void*)listener))
|
||||||
|
return fListeners.AddItem((void*)listener);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveListener
|
||||||
|
bool
|
||||||
|
Shape::RemoveListener(ShapeListener* listener)
|
||||||
|
{
|
||||||
|
return fListeners.RemoveItem((void*)listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// _NotifyTransformerAdded
|
||||||
|
void
|
||||||
|
Shape::_NotifyTransformerAdded(Transformer* transformer, int32 index) const
|
||||||
|
{
|
||||||
|
BList listeners(fListeners);
|
||||||
|
int32 count = listeners.CountItems();
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
ShapeListener* listener
|
||||||
|
= (ShapeListener*)listeners.ItemAtFast(i);
|
||||||
|
listener->TransformerAdded(transformer, index);
|
||||||
|
}
|
||||||
|
// TODO: merge Observable and ShapeListener interface
|
||||||
|
_NotifyRerender();
|
||||||
|
}
|
||||||
|
|
||||||
|
// _NotifyTransformerRemoved
|
||||||
|
void
|
||||||
|
Shape::_NotifyTransformerRemoved(Transformer* transformer) const
|
||||||
|
{
|
||||||
|
BList listeners(fListeners);
|
||||||
|
int32 count = listeners.CountItems();
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
ShapeListener* listener
|
||||||
|
= (ShapeListener*)listeners.ItemAtFast(i);
|
||||||
|
listener->TransformerRemoved(transformer);
|
||||||
|
}
|
||||||
|
// TODO: merge Observable and ShapeListener interface
|
||||||
|
_NotifyRerender();
|
||||||
|
}
|
||||||
|
|
||||||
|
// _NotifyStyleChanged
|
||||||
|
void
|
||||||
|
Shape::_NotifyStyleChanged(::Style* oldStyle, ::Style* newStyle) const
|
||||||
|
{
|
||||||
|
BList listeners(fListeners);
|
||||||
|
int32 count = listeners.CountItems();
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
ShapeListener* listener
|
||||||
|
= (ShapeListener*)listeners.ItemAtFast(i);
|
||||||
|
listener->StyleChanged(oldStyle, newStyle);
|
||||||
|
}
|
||||||
|
// TODO: merge Observable and ShapeListener interface
|
||||||
|
_NotifyRerender();
|
||||||
|
}
|
||||||
|
|
||||||
|
// _NotifyRerender
|
||||||
|
void
|
||||||
|
Shape::_NotifyRerender() const
|
||||||
|
{
|
||||||
|
fNeedsUpdate = true;
|
||||||
|
Notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SHAPE_H
|
||||||
|
#define SHAPE_H
|
||||||
|
|
||||||
|
#include <List.h>
|
||||||
|
#include <Rect.h>
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
# include "IconObject.h"
|
||||||
|
# include "Observer.h"
|
||||||
|
#endif
|
||||||
|
#include "PathContainer.h"
|
||||||
|
#include "PathSource.h"
|
||||||
|
#include "Transformable.h"
|
||||||
|
#include "VectorPath.h"
|
||||||
|
|
||||||
|
class Style;
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// TODO: merge Observer and ShapeListener interface
|
||||||
|
// ie add "AppearanceChanged(Shape* shape)"
|
||||||
|
class ShapeListener {
|
||||||
|
public:
|
||||||
|
ShapeListener();
|
||||||
|
virtual ~ShapeListener();
|
||||||
|
|
||||||
|
virtual void TransformerAdded(Transformer* t,
|
||||||
|
int32 index) = 0;
|
||||||
|
virtual void TransformerRemoved(Transformer* t) = 0;
|
||||||
|
|
||||||
|
virtual void StyleChanged(::Style* oldStyle,
|
||||||
|
::Style* newStyle) = 0;
|
||||||
|
};
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
class Shape : public IconObject,
|
||||||
|
public Transformable,
|
||||||
|
public Observer, // observing all the paths and the style
|
||||||
|
public PathContainerListener,
|
||||||
|
public PathListener {
|
||||||
|
#else
|
||||||
|
class Shape : public Transformable {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
|
Shape(::Style* style);
|
||||||
|
Shape(const Shape& other);
|
||||||
|
virtual ~Shape();
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// IconObject interface
|
||||||
|
virtual status_t Unarchive(const BMessage* archive);
|
||||||
|
virtual status_t Archive(BMessage* into,
|
||||||
|
bool deep = true) const;
|
||||||
|
|
||||||
|
virtual PropertyObject* MakePropertyObject() const;
|
||||||
|
virtual bool SetToPropertyObject(
|
||||||
|
const PropertyObject* object);
|
||||||
|
|
||||||
|
// Transformable interface
|
||||||
|
virtual void TransformationChanged();
|
||||||
|
|
||||||
|
// Observer interface
|
||||||
|
virtual void ObjectChanged(const Observable* object);
|
||||||
|
|
||||||
|
// PathContainerListener interface
|
||||||
|
virtual void PathAdded(VectorPath* path);
|
||||||
|
virtual void PathRemoved(VectorPath* path);
|
||||||
|
|
||||||
|
// PathListener interface
|
||||||
|
virtual void PointAdded(int32 index);
|
||||||
|
virtual void PointRemoved(int32 index);
|
||||||
|
virtual void PointChanged(int32 index);
|
||||||
|
virtual void PathChanged();
|
||||||
|
virtual void PathClosedChanged();
|
||||||
|
virtual void PathReversed();
|
||||||
|
#else
|
||||||
|
inline void Notify() {}
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
// Shape
|
||||||
|
status_t InitCheck() const;
|
||||||
|
|
||||||
|
inline PathContainer* Paths() const
|
||||||
|
{ return fPaths; }
|
||||||
|
|
||||||
|
void SetStyle(::Style* style);
|
||||||
|
inline ::Style* Style() const
|
||||||
|
{ return fStyle; }
|
||||||
|
|
||||||
|
inline BRect LastBounds() const
|
||||||
|
{ return fLastBounds; }
|
||||||
|
BRect Bounds(bool updateLast = false) const;
|
||||||
|
|
||||||
|
::VertexSource& VertexSource();
|
||||||
|
|
||||||
|
bool AddTransformer(Transformer* transformer);
|
||||||
|
bool AddTransformer(Transformer* transformer,
|
||||||
|
int32 index);
|
||||||
|
bool RemoveTransformer(Transformer* transformer);
|
||||||
|
|
||||||
|
int32 CountTransformers() const;
|
||||||
|
|
||||||
|
bool HasTransformer(Transformer* transformer) const;
|
||||||
|
int32 IndexOf(Transformer* transformer) const;
|
||||||
|
|
||||||
|
Transformer* TransformerAt(int32 index) const;
|
||||||
|
Transformer* TransformerAtFast(int32 index) const;
|
||||||
|
|
||||||
|
void SetHinting(bool hinting);
|
||||||
|
bool Hinting() const
|
||||||
|
{ return fHinting; }
|
||||||
|
void SetMinVisibilityScale(float scale);
|
||||||
|
float MinVisibilityScale() const
|
||||||
|
{ return fMinVisibilityScale; }
|
||||||
|
void SetMaxVisibilityScale(float scale);
|
||||||
|
float MaxVisibilityScale() const
|
||||||
|
{ return fMaxVisibilityScale; }
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
bool AddListener(ShapeListener* listener);
|
||||||
|
bool RemoveListener(ShapeListener* listener);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _NotifyTransformerAdded(Transformer* t,
|
||||||
|
int32 index) const;
|
||||||
|
void _NotifyTransformerRemoved(Transformer* t) const;
|
||||||
|
|
||||||
|
void _NotifyStyleChanged(::Style* oldStyle,
|
||||||
|
::Style* newStyle) const;
|
||||||
|
|
||||||
|
void _NotifyRerender() const;
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
private:
|
||||||
|
PathContainer* fPaths;
|
||||||
|
::Style* fStyle;
|
||||||
|
|
||||||
|
PathSource fPathSource;
|
||||||
|
BList fTransformers;
|
||||||
|
mutable bool fNeedsUpdate;
|
||||||
|
|
||||||
|
mutable BRect fLastBounds;
|
||||||
|
|
||||||
|
bool fHinting;
|
||||||
|
float fMinVisibilityScale;
|
||||||
|
float fMaxVisibilityScale;
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
BList fListeners;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SHAPE_H
|
||||||
@@ -0,0 +1,228 @@
|
|||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// constructor
|
||||||
|
ShapeContainerListener::ShapeContainerListener()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
ShapeContainerListener::~ShapeContainerListener()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
ShapeContainer::ShapeContainer()
|
||||||
|
: fShapes(16)
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
, fListeners(2)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
ShapeContainer::~ShapeContainer()
|
||||||
|
{
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
int32 count = fListeners.CountItems();
|
||||||
|
if (count > 0) {
|
||||||
|
debugger("~ShapeContainer() - there are still"
|
||||||
|
"listeners attached\n");
|
||||||
|
}
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
_MakeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// AddShape
|
||||||
|
bool
|
||||||
|
ShapeContainer::AddShape(Shape* shape)
|
||||||
|
{
|
||||||
|
return AddShape(shape, CountShapes());
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddShape
|
||||||
|
bool
|
||||||
|
ShapeContainer::AddShape(Shape* shape, int32 index)
|
||||||
|
{
|
||||||
|
if (!shape)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// prevent adding the same shape twice
|
||||||
|
if (HasShape(shape))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (fShapes.AddItem((void*)shape, index)) {
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
_NotifyShapeAdded(shape, index);
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "ShapeContainer::AddShape() - out of memory!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveShape
|
||||||
|
bool
|
||||||
|
ShapeContainer::RemoveShape(Shape* shape)
|
||||||
|
{
|
||||||
|
if (fShapes.RemoveItem((void*)shape)) {
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
_NotifyShapeRemoved(shape);
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveShape
|
||||||
|
Shape*
|
||||||
|
ShapeContainer::RemoveShape(int32 index)
|
||||||
|
{
|
||||||
|
Shape* shape = (Shape*)fShapes.RemoveItem(index);
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
if (shape) {
|
||||||
|
_NotifyShapeRemoved(shape);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// IndexOf
|
||||||
|
int32
|
||||||
|
ShapeContainer::IndexOf(Shape* shape) const
|
||||||
|
{
|
||||||
|
return fShapes.IndexOf((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 -
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
|
||||||
|
// AddListener
|
||||||
|
bool
|
||||||
|
ShapeContainer::AddListener(ShapeContainerListener* listener)
|
||||||
|
{
|
||||||
|
if (listener && !fListeners.HasItem((void*)listener))
|
||||||
|
return fListeners.AddItem((void*)listener);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveListener
|
||||||
|
bool
|
||||||
|
ShapeContainer::RemoveListener(ShapeContainerListener* listener)
|
||||||
|
{
|
||||||
|
return fListeners.RemoveItem((void*)listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// _MakeEmpty
|
||||||
|
void
|
||||||
|
ShapeContainer::_MakeEmpty()
|
||||||
|
{
|
||||||
|
int32 count = CountShapes();
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
Shape* shape = ShapeAtFast(i);
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
_NotifyShapeRemoved(shape);
|
||||||
|
shape->Release();
|
||||||
|
#else
|
||||||
|
delete shape;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
fShapes.MakeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
|
||||||
|
// _NotifyShapeAdded
|
||||||
|
void
|
||||||
|
ShapeContainer::_NotifyShapeAdded(Shape* shape, int32 index) const
|
||||||
|
{
|
||||||
|
BList listeners(fListeners);
|
||||||
|
int32 count = listeners.CountItems();
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
ShapeContainerListener* listener
|
||||||
|
= (ShapeContainerListener*)listeners.ItemAtFast(i);
|
||||||
|
listener->ShapeAdded(shape, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// _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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
class ShapeContainerListener {
|
||||||
|
public:
|
||||||
|
ShapeContainerListener();
|
||||||
|
virtual ~ShapeContainerListener();
|
||||||
|
|
||||||
|
virtual void ShapeAdded(Shape* shape, int32 index) = 0;
|
||||||
|
virtual void ShapeRemoved(Shape* shape) = 0;
|
||||||
|
};
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
class ShapeContainer {
|
||||||
|
public:
|
||||||
|
ShapeContainer();
|
||||||
|
virtual ~ShapeContainer();
|
||||||
|
|
||||||
|
bool AddShape(Shape* shape);
|
||||||
|
bool AddShape(Shape* shape, int32 index);
|
||||||
|
bool RemoveShape(Shape* shape);
|
||||||
|
Shape* RemoveShape(int32 index);
|
||||||
|
|
||||||
|
void MakeEmpty();
|
||||||
|
|
||||||
|
int32 CountShapes() const;
|
||||||
|
bool HasShape(Shape* shape) const;
|
||||||
|
int32 IndexOf(Shape* shape) const;
|
||||||
|
|
||||||
|
Shape* ShapeAt(int32 index) const;
|
||||||
|
Shape* ShapeAtFast(int32 index) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _MakeEmpty();
|
||||||
|
|
||||||
|
BList fShapes;
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
public:
|
||||||
|
bool AddListener(ShapeContainerListener* listener);
|
||||||
|
bool RemoveListener(
|
||||||
|
ShapeContainerListener* listener);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _NotifyShapeAdded(Shape* shape,
|
||||||
|
int32 index) const;
|
||||||
|
void _NotifyShapeRemoved(Shape* shape) const;
|
||||||
|
|
||||||
|
BList fListeners;
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SHAPE_CONTAINER_H
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VECTOR_PATH_H
|
||||||
|
#define VECTOR_PATH_H
|
||||||
|
|
||||||
|
#include <Rect.h>
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
#include <agg_path_storage.h>
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
# include <Archivable.h>
|
||||||
|
# include <List.h>
|
||||||
|
|
||||||
|
# include "IconObject.h"
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
class BBitmap;
|
||||||
|
class BMessage;
|
||||||
|
class BView;
|
||||||
|
|
||||||
|
struct control_point {
|
||||||
|
BPoint point; // actual point on path
|
||||||
|
BPoint point_in; // control point for incomming curve
|
||||||
|
BPoint point_out; // control point for outgoing curve
|
||||||
|
bool connected; // if all 3 points should be on one line
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
class PathListener {
|
||||||
|
public:
|
||||||
|
PathListener();
|
||||||
|
virtual ~PathListener();
|
||||||
|
|
||||||
|
virtual void PointAdded(int32 index) = 0;
|
||||||
|
virtual void PointRemoved(int32 index) = 0;
|
||||||
|
virtual void PointChanged(int32 index) = 0;
|
||||||
|
virtual void PathChanged() = 0;
|
||||||
|
virtual void PathClosedChanged() = 0;
|
||||||
|
virtual void PathReversed() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class VectorPath : public BArchivable,
|
||||||
|
public IconObject {
|
||||||
|
#else
|
||||||
|
class VectorPath {
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
public:
|
||||||
|
|
||||||
|
class Iterator {
|
||||||
|
public:
|
||||||
|
Iterator() {}
|
||||||
|
virtual ~Iterator() {}
|
||||||
|
|
||||||
|
virtual void MoveTo(BPoint point) = 0;
|
||||||
|
virtual void LineTo(BPoint point) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
VectorPath();
|
||||||
|
VectorPath(const VectorPath& from);
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
VectorPath(BMessage* archive);
|
||||||
|
#endif
|
||||||
|
virtual ~VectorPath();
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// IconObject
|
||||||
|
virtual status_t Archive(BMessage* into,
|
||||||
|
bool deep = true) const;
|
||||||
|
|
||||||
|
virtual PropertyObject* MakePropertyObject() const;
|
||||||
|
virtual bool SetToPropertyObject(
|
||||||
|
const PropertyObject* object);
|
||||||
|
#else
|
||||||
|
inline void Notify() {}
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
// VectorPath
|
||||||
|
VectorPath& operator=(const VectorPath& from);
|
||||||
|
// bool operator==(const VectorPath& frrom) const;
|
||||||
|
|
||||||
|
void MakeEmpty();
|
||||||
|
|
||||||
|
bool AddPoint(BPoint point);
|
||||||
|
bool AddPoint(const BPoint& point,
|
||||||
|
const BPoint& pointIn,
|
||||||
|
const BPoint& pointOut,
|
||||||
|
bool connected);
|
||||||
|
bool AddPoint(BPoint point, int32 index);
|
||||||
|
|
||||||
|
bool RemovePoint(int32 index);
|
||||||
|
|
||||||
|
// modify existing points position
|
||||||
|
bool SetPoint(int32 index, BPoint point);
|
||||||
|
bool SetPoint(int32 index, BPoint point,
|
||||||
|
BPoint pointIn,
|
||||||
|
BPoint pointOut,
|
||||||
|
bool connected);
|
||||||
|
bool SetPointIn(int32 index, BPoint point);
|
||||||
|
bool SetPointOut(int32 index, BPoint point,
|
||||||
|
bool mirrorDist = false);
|
||||||
|
|
||||||
|
bool SetInOutConnected(int32 index, bool connected);
|
||||||
|
|
||||||
|
// query existing points position
|
||||||
|
bool GetPointAt(int32 index, BPoint& point) const;
|
||||||
|
bool GetPointInAt(int32 index, BPoint& point) const;
|
||||||
|
bool GetPointOutAt(int32 index, BPoint& point) const;
|
||||||
|
bool GetPointsAt(int32 index,
|
||||||
|
BPoint& point,
|
||||||
|
BPoint& pointIn,
|
||||||
|
BPoint& pointOut,
|
||||||
|
bool* connected = NULL) const;
|
||||||
|
|
||||||
|
int32 CountPoints() const;
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// iterates over curve segments and returns
|
||||||
|
// the distance and index of the point that
|
||||||
|
// started the segment that is closest
|
||||||
|
bool GetDistance(BPoint point,
|
||||||
|
float* distance, int32* index) const;
|
||||||
|
|
||||||
|
// at curve segment indicated by "index", this
|
||||||
|
// function looks for the closest point
|
||||||
|
// directly on the curve and returns a "scale"
|
||||||
|
// that indicates the distance on the curve
|
||||||
|
// between [0..1]
|
||||||
|
bool FindBezierScale(int32 index, BPoint point,
|
||||||
|
double* scale) const;
|
||||||
|
// this function can be used to get a point
|
||||||
|
// directly on the segment indicated by "index"
|
||||||
|
// "scale" is on [0..1] indicating the distance
|
||||||
|
// from the start of the segment to the end
|
||||||
|
bool GetPoint(int32 index, double scale,
|
||||||
|
BPoint& point) const;
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
void SetClosed(bool closed);
|
||||||
|
bool IsClosed() const
|
||||||
|
{ return fClosed; }
|
||||||
|
|
||||||
|
BRect Bounds() const;
|
||||||
|
BRect ControlPointBounds() const;
|
||||||
|
|
||||||
|
void Iterate(Iterator* iterator,
|
||||||
|
float smoothScale = 1.0) const;
|
||||||
|
|
||||||
|
void CleanUp();
|
||||||
|
void Reverse();
|
||||||
|
|
||||||
|
void PrintToStream() const;
|
||||||
|
|
||||||
|
bool GetAGGPathStorage(agg::path_storage& path) const;
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
bool AddListener(PathListener* listener);
|
||||||
|
bool RemoveListener(PathListener* listener);
|
||||||
|
int32 CountListeners() const;
|
||||||
|
PathListener* ListenerAtFast(int32 index) const;
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
BRect _Bounds() const;
|
||||||
|
void _SetPoint(int32 index, BPoint point);
|
||||||
|
void _SetPoint(int32 index,
|
||||||
|
const BPoint& point,
|
||||||
|
const BPoint& pointIn,
|
||||||
|
const BPoint& pointOut,
|
||||||
|
bool connected);
|
||||||
|
bool _SetPointCount(int32 count);
|
||||||
|
|
||||||
|
#ifndef ICON_O_MATIC
|
||||||
|
inline void _NotifyPointAdded(int32 index) const {}
|
||||||
|
inline void _NotifyPointChanged(int32 index) const {}
|
||||||
|
inline void _NotifyPointRemoved(int32 index) const {}
|
||||||
|
inline void _NotifyPathChanged() const {}
|
||||||
|
inline void _NotifyClosedChanged() const {}
|
||||||
|
inline void _NotifyPathReversed() const {}
|
||||||
|
#else
|
||||||
|
void _NotifyPointAdded(int32 index) const;
|
||||||
|
void _NotifyPointChanged(int32 index) const;
|
||||||
|
void _NotifyPointRemoved(int32 index) const;
|
||||||
|
void _NotifyPathChanged() const;
|
||||||
|
void _NotifyClosedChanged() const;
|
||||||
|
void _NotifyPathReversed() const;
|
||||||
|
|
||||||
|
BList fListeners;
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
control_point* fPath;
|
||||||
|
bool fClosed;
|
||||||
|
|
||||||
|
int32 fPointCount;
|
||||||
|
int32 fAllocCount;
|
||||||
|
|
||||||
|
mutable BRect fCachedBounds;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VECTOR_PATH_H
|
||||||
|
|
||||||
@@ -0,0 +1,638 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Gradient.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <Message.h>
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
# include "support.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
color_step::color_step(const rgb_color c, float o)
|
||||||
|
{
|
||||||
|
color.red = c.red;
|
||||||
|
color.green = c.green;
|
||||||
|
color.blue = c.blue;
|
||||||
|
color.alpha = c.alpha;
|
||||||
|
offset = o;
|
||||||
|
}
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
color_step::color_step(uint8 r, uint8 g, uint8 b, uint8 a, float o)
|
||||||
|
{
|
||||||
|
color.red = r;
|
||||||
|
color.green = g;
|
||||||
|
color.blue = b;
|
||||||
|
color.alpha = a;
|
||||||
|
offset = o;
|
||||||
|
}
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
color_step::color_step(const color_step& other)
|
||||||
|
{
|
||||||
|
color.red = other.color.red;
|
||||||
|
color.green = other.color.green;
|
||||||
|
color.blue = other.color.blue;
|
||||||
|
color.alpha = other.color.alpha;
|
||||||
|
offset = other.offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
color_step::color_step()
|
||||||
|
{
|
||||||
|
color.red = 0;
|
||||||
|
color.green = 0;
|
||||||
|
color.blue = 0;
|
||||||
|
color.alpha = 255;
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// operator!=
|
||||||
|
bool
|
||||||
|
color_step::operator!=(const color_step& other) const
|
||||||
|
{
|
||||||
|
return color.red != other.color.red ||
|
||||||
|
color.green != other.color.green ||
|
||||||
|
color.blue != other.color.blue ||
|
||||||
|
color.alpha != other.color.alpha ||
|
||||||
|
offset != other.offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
Gradient::Gradient(bool empty)
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
: BArchivable(),
|
||||||
|
Observable(),
|
||||||
|
Transformable(),
|
||||||
|
#else
|
||||||
|
: Transformable(),
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fColors(4),
|
||||||
|
fType(GRADIENT_LINEAR),
|
||||||
|
fInterpolation(INTERPOLATION_SMOOTH),
|
||||||
|
fInheritTransformation(true)
|
||||||
|
{
|
||||||
|
if (!empty) {
|
||||||
|
AddColor(color_step(0, 0, 0, 255, 0.0), 0);
|
||||||
|
AddColor(color_step(255, 255, 255, 255, 1.0), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// constructor
|
||||||
|
Gradient::Gradient(BMessage* archive)
|
||||||
|
: BArchivable(archive),
|
||||||
|
Observable(),
|
||||||
|
Transformable(),
|
||||||
|
|
||||||
|
fColors(4),
|
||||||
|
fType(GRADIENT_LINEAR),
|
||||||
|
fInterpolation(INTERPOLATION_SMOOTH),
|
||||||
|
fInheritTransformation(true)
|
||||||
|
{
|
||||||
|
if (!archive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// read transformation
|
||||||
|
int32 size = Transformable::matrix_size;
|
||||||
|
const void* matrix;
|
||||||
|
ssize_t dataSize = size * sizeof(double);
|
||||||
|
if (archive->FindData("transformation", B_DOUBLE_TYPE,
|
||||||
|
&matrix, &dataSize) == B_OK
|
||||||
|
&& dataSize == (ssize_t)(size * sizeof(double)))
|
||||||
|
LoadFrom((const double*)matrix);
|
||||||
|
|
||||||
|
// color steps
|
||||||
|
color_step step;
|
||||||
|
for (int32 i = 0; archive->FindFloat("offset", i, &step.offset) >= B_OK; i++) {
|
||||||
|
if (archive->FindInt32("color", i, (int32*)&step.color) >= B_OK)
|
||||||
|
AddColor(step, i);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (archive->FindInt32("type", (int32*)&fType) < B_OK)
|
||||||
|
fType = GRADIENT_LINEAR;
|
||||||
|
|
||||||
|
if (archive->FindInt32("interpolation", (int32*)&fInterpolation) < B_OK)
|
||||||
|
fInterpolation = INTERPOLATION_SMOOTH;
|
||||||
|
|
||||||
|
if (archive->FindBool("inherit transformation",
|
||||||
|
&fInheritTransformation) < B_OK)
|
||||||
|
fInheritTransformation = true;
|
||||||
|
}
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
Gradient::Gradient(const Gradient& other)
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
: BArchivable(other),
|
||||||
|
Observable(),
|
||||||
|
Transformable(other),
|
||||||
|
#else
|
||||||
|
: Transformable(other),
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fColors(4),
|
||||||
|
fType(other.fType),
|
||||||
|
fInterpolation(other.fInterpolation),
|
||||||
|
fInheritTransformation(other.fInheritTransformation)
|
||||||
|
{
|
||||||
|
for (int32 i = 0; color_step* step = other.ColorAt(i); i++) {
|
||||||
|
AddColor(*step, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
Gradient::~Gradient()
|
||||||
|
{
|
||||||
|
_MakeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// Archive
|
||||||
|
status_t
|
||||||
|
Gradient::Archive(BMessage* into, bool deep) const
|
||||||
|
{
|
||||||
|
status_t ret = BArchivable::Archive(into, deep);
|
||||||
|
|
||||||
|
// transformation
|
||||||
|
if (ret == B_OK) {
|
||||||
|
int32 size = Transformable::matrix_size;
|
||||||
|
double matrix[size];
|
||||||
|
StoreTo(matrix);
|
||||||
|
ret = into->AddData("transformation", B_DOUBLE_TYPE,
|
||||||
|
matrix, size * sizeof(double));
|
||||||
|
}
|
||||||
|
|
||||||
|
// color steps
|
||||||
|
if (ret >= B_OK) {
|
||||||
|
for (int32 i = 0; color_step* step = ColorAt(i); i++) {
|
||||||
|
ret = into->AddInt32("color", (const uint32&)step->color);
|
||||||
|
if (ret < B_OK)
|
||||||
|
break;
|
||||||
|
ret = into->AddFloat("offset", step->offset);
|
||||||
|
if (ret < B_OK)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// gradient and interpolation type
|
||||||
|
if (ret >= B_OK)
|
||||||
|
ret = into->AddInt32("type", (int32)fType);
|
||||||
|
if (ret >= B_OK)
|
||||||
|
ret = into->AddInt32("interpolation", (int32)fInterpolation);
|
||||||
|
if (ret >= B_OK)
|
||||||
|
ret = into->AddBool("inherit transformation", fInheritTransformation);
|
||||||
|
|
||||||
|
// finish off
|
||||||
|
if (ret >= B_OK)
|
||||||
|
ret = into->AddString("class", "Gradient");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// operator=
|
||||||
|
Gradient&
|
||||||
|
Gradient::operator=(const Gradient& other)
|
||||||
|
{
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
AutoNotificationSuspender _(this);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SetTransform(other);
|
||||||
|
SetColors(other);
|
||||||
|
SetType(other.fType);
|
||||||
|
SetInterpolation(other.fInterpolation);
|
||||||
|
SetInheritTransformation(other.fInheritTransformation);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// operator==
|
||||||
|
bool
|
||||||
|
Gradient::operator==(const Gradient& other) const
|
||||||
|
{
|
||||||
|
if (Transformable::operator==(other)) {
|
||||||
|
int32 count = CountColors();
|
||||||
|
if (count == other.CountColors() &&
|
||||||
|
fType == other.fType &&
|
||||||
|
fInterpolation == other.fInterpolation &&
|
||||||
|
fInheritTransformation == other.fInheritTransformation) {
|
||||||
|
|
||||||
|
bool equal = true;
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
color_step* ourStep = ColorAtFast(i);
|
||||||
|
color_step* otherStep = other.ColorAtFast(i);
|
||||||
|
if (*ourStep != *otherStep) {
|
||||||
|
equal = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return equal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// operator!=
|
||||||
|
bool
|
||||||
|
Gradient::operator!=(const Gradient& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetColors
|
||||||
|
void
|
||||||
|
Gradient::SetColors(const Gradient& other)
|
||||||
|
{
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
AutoNotificationSuspender _(this);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_MakeEmpty();
|
||||||
|
for (int32 i = 0; color_step* step = other.ColorAt(i); i++)
|
||||||
|
AddColor(*step, i);
|
||||||
|
|
||||||
|
Notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// AddColor
|
||||||
|
int32
|
||||||
|
Gradient::AddColor(const rgb_color& color, float offset)
|
||||||
|
{
|
||||||
|
// find the correct index (sorted by offset)
|
||||||
|
color_step* step = new color_step(color, offset);
|
||||||
|
int32 index = 0;
|
||||||
|
int32 count = CountColors();
|
||||||
|
for (; index < count; index++) {
|
||||||
|
color_step* s = ColorAtFast(index);
|
||||||
|
if (s->offset > step->offset)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!fColors.AddItem((void*)step, index)) {
|
||||||
|
delete step;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
Notify();
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddColor
|
||||||
|
bool
|
||||||
|
Gradient::AddColor(const color_step& color, int32 index)
|
||||||
|
{
|
||||||
|
color_step* step = new color_step(color);
|
||||||
|
if (!fColors.AddItem((void*)step, index)) {
|
||||||
|
delete step;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Notify();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveColor
|
||||||
|
bool
|
||||||
|
Gradient::RemoveColor(int32 index)
|
||||||
|
{
|
||||||
|
color_step* step = (color_step*)fColors.RemoveItem(index);
|
||||||
|
if (!step) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
delete step;
|
||||||
|
Notify();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// SetColor
|
||||||
|
bool
|
||||||
|
Gradient::SetColor(int32 index, const color_step& color)
|
||||||
|
{
|
||||||
|
if (color_step* step = ColorAt(index)) {
|
||||||
|
if (*step != color) {
|
||||||
|
step->color = color.color;
|
||||||
|
step->offset = color.offset;
|
||||||
|
Notify();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetColor
|
||||||
|
bool
|
||||||
|
Gradient::SetColor(int32 index, const rgb_color& color)
|
||||||
|
{
|
||||||
|
if (color_step* step = ColorAt(index)) {
|
||||||
|
if ((uint32&)step->color != (uint32&)color) {
|
||||||
|
step->color = color;
|
||||||
|
Notify();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOffset
|
||||||
|
bool
|
||||||
|
Gradient::SetOffset(int32 index, float offset)
|
||||||
|
{
|
||||||
|
color_step* step = ColorAt(index);
|
||||||
|
if (step && step->offset != offset) {
|
||||||
|
step->offset = offset;
|
||||||
|
Notify();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// CountColors
|
||||||
|
int32
|
||||||
|
Gradient::CountColors() const
|
||||||
|
{
|
||||||
|
return fColors.CountItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ColorAt
|
||||||
|
color_step*
|
||||||
|
Gradient::ColorAt(int32 index) const
|
||||||
|
{
|
||||||
|
return (color_step*)fColors.ItemAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ColorAtFast
|
||||||
|
color_step*
|
||||||
|
Gradient::ColorAtFast(int32 index) const
|
||||||
|
{
|
||||||
|
return (color_step*)fColors.ItemAtFast(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// SetType
|
||||||
|
void
|
||||||
|
Gradient::SetType(gradient_type type)
|
||||||
|
{
|
||||||
|
if (fType != type) {
|
||||||
|
fType = type;
|
||||||
|
Notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetInterpolation
|
||||||
|
void
|
||||||
|
Gradient::SetInterpolation(interpolation_type type)
|
||||||
|
{
|
||||||
|
if (fInterpolation != type) {
|
||||||
|
fInterpolation = type;
|
||||||
|
Notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetInheritTransformation
|
||||||
|
void
|
||||||
|
Gradient::SetInheritTransformation(bool inherit)
|
||||||
|
{
|
||||||
|
if (fInheritTransformation != inherit) {
|
||||||
|
fInheritTransformation = inherit;
|
||||||
|
Notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// gauss
|
||||||
|
inline double
|
||||||
|
gauss(double f)
|
||||||
|
{
|
||||||
|
// this aint' a real gauss function
|
||||||
|
if (f > 0.0) {
|
||||||
|
if (f < 0.5)
|
||||||
|
return (1.0 - 2.0 * f*f);
|
||||||
|
|
||||||
|
f = 1.0 - f;
|
||||||
|
return (2.0 * f*f);
|
||||||
|
}
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeGradient
|
||||||
|
void
|
||||||
|
Gradient::MakeGradient(uint32* colors, int32 count) const
|
||||||
|
{
|
||||||
|
color_step* from = ColorAt(0);
|
||||||
|
|
||||||
|
if (!from)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// find the step with the lowest offset
|
||||||
|
for (int32 i = 0; color_step* step = ColorAt(i); i++) {
|
||||||
|
if (step->offset < from->offset)
|
||||||
|
from = step;
|
||||||
|
}
|
||||||
|
|
||||||
|
// current index into "colors" array
|
||||||
|
int32 index = (int32)floorf(count * from->offset + 0.5);
|
||||||
|
if (index < 0)
|
||||||
|
index = 0;
|
||||||
|
if (index > count)
|
||||||
|
index = count;
|
||||||
|
// make sure we fill the entire array
|
||||||
|
if (index > 0) {
|
||||||
|
uint8* c = (uint8*)&colors[0];
|
||||||
|
for (int32 i = 0; i < index; i++) {
|
||||||
|
c[0] = from->color.red;
|
||||||
|
c[1] = from->color.green;
|
||||||
|
c[2] = from->color.blue;
|
||||||
|
c[3] = from->color.alpha;
|
||||||
|
c += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// put all steps that we need to interpolate to into a list
|
||||||
|
BList nextSteps(fColors.CountItems() - 1);
|
||||||
|
for (int32 i = 0; color_step* step = ColorAt(i); i++) {
|
||||||
|
if (step != from)
|
||||||
|
nextSteps.AddItem((void*)step);
|
||||||
|
}
|
||||||
|
|
||||||
|
// interpolate "from" to "to"
|
||||||
|
while (!nextSteps.IsEmpty()) {
|
||||||
|
|
||||||
|
// find the step with the next offset
|
||||||
|
color_step* to = NULL;
|
||||||
|
float nextOffsetDist = 2.0;
|
||||||
|
for (int32 i = 0; color_step* step = (color_step*)nextSteps.ItemAt(i); i++) {
|
||||||
|
float d = step->offset - from->offset;
|
||||||
|
if (d < nextOffsetDist && d >= 0) {
|
||||||
|
to = step;
|
||||||
|
nextOffsetDist = d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!to)
|
||||||
|
break;
|
||||||
|
|
||||||
|
nextSteps.RemoveItem((void*)to);
|
||||||
|
|
||||||
|
// interpolate
|
||||||
|
int32 offset = (int32)floorf((count - 1) * to->offset + 0.5);
|
||||||
|
if (offset >= count)
|
||||||
|
offset = count - 1;
|
||||||
|
int32 dist = offset - index;
|
||||||
|
if (dist >= 0) {
|
||||||
|
uint8* c = (uint8*)&colors[index];
|
||||||
|
#if GAMMA_BLEND
|
||||||
|
uint16 fromRed = kGammaTable[from->color.red];
|
||||||
|
uint16 fromGreen = kGammaTable[from->color.green];
|
||||||
|
uint16 fromBlue = kGammaTable[from->color.blue];
|
||||||
|
uint16 toRed = kGammaTable[to->color.red];
|
||||||
|
uint16 toGreen = kGammaTable[to->color.green];
|
||||||
|
uint16 toBlue = kGammaTable[to->color.blue];
|
||||||
|
|
||||||
|
for (int32 i = index; i <= offset; i++) {
|
||||||
|
float f = (float)(offset - i) / (float)(dist + 1);
|
||||||
|
if (fInterpolation == INTERPOLATION_SMOOTH)
|
||||||
|
f = gauss(1.0 - f);
|
||||||
|
float t = 1.0 - f;
|
||||||
|
c[0] = kInverseGammaTable[(uint16)floor(fromBlue * f + toBlue * t + 0.5)];
|
||||||
|
c[1] = kInverseGammaTable[(uint16)floor(fromGreen * f + toGreen * t + 0.5)];
|
||||||
|
c[2] = kInverseGammaTable[(uint16)floor(fromRed * f + toRed * t + 0.5)];
|
||||||
|
c[3] = (uint8)floor(from->color.alpha * f + to->color.alpha * t + 0.5);
|
||||||
|
c += 4;
|
||||||
|
}
|
||||||
|
#else // GAMMA_BLEND
|
||||||
|
for (int32 i = index; i <= offset; i++) {
|
||||||
|
float f = (float)(offset - i) / (float)(dist + 1);
|
||||||
|
if (fInterpolation == INTERPOLATION_SMOOTH)
|
||||||
|
f = gauss(1.0 - f);
|
||||||
|
float t = 1.0 - f;
|
||||||
|
c[0] = (uint8)floor(from->color.red * f + to->color.red * t + 0.5);
|
||||||
|
c[1] = (uint8)floor(from->color.green * f + to->color.green * t + 0.5);
|
||||||
|
c[2] = (uint8)floor(from->color.blue * f + to->color.blue * t + 0.5);
|
||||||
|
c[3] = (uint8)floor(from->color.alpha * f + to->color.alpha * t + 0.5);
|
||||||
|
c += 4;
|
||||||
|
}
|
||||||
|
#endif // GAMMA_BLEND
|
||||||
|
}
|
||||||
|
index = offset + 1;
|
||||||
|
// the current "to" will be the "from" in the next interpolation
|
||||||
|
from = to;
|
||||||
|
}
|
||||||
|
// make sure we fill the entire array
|
||||||
|
if (index < count) {
|
||||||
|
uint8* c = (uint8*)&colors[index];
|
||||||
|
for (int32 i = index; i < count; i++) {
|
||||||
|
c[0] = from->color.red;
|
||||||
|
c[1] = from->color.green;
|
||||||
|
c[2] = from->color.blue;
|
||||||
|
c[3] = from->color.alpha;
|
||||||
|
c += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// string_for_type
|
||||||
|
static const char*
|
||||||
|
string_for_type(gradient_type type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case GRADIENT_LINEAR:
|
||||||
|
return "GRADIENT_LINEAR";
|
||||||
|
case GRADIENT_CIRCULAR:
|
||||||
|
return "GRADIENT_CIRCULAR";
|
||||||
|
case GRADIENT_DIAMONT:
|
||||||
|
return "GRADIENT_DIAMONT";
|
||||||
|
case GRADIENT_CONIC:
|
||||||
|
return "GRADIENT_CONIC";
|
||||||
|
case GRADIENT_XY:
|
||||||
|
return "GRADIENT_XY";
|
||||||
|
case GRADIENT_SQRT_XY:
|
||||||
|
return "GRADIENT_SQRT_XY";
|
||||||
|
}
|
||||||
|
return "<unkown>";
|
||||||
|
}
|
||||||
|
|
||||||
|
//string_for_interpolation
|
||||||
|
static const char*
|
||||||
|
string_for_interpolation(interpolation_type type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case INTERPOLATION_LINEAR:
|
||||||
|
return "INTERPOLATION_LINEAR";
|
||||||
|
case INTERPOLATION_SMOOTH:
|
||||||
|
return "INTERPOLATION_SMOOTH";
|
||||||
|
}
|
||||||
|
return "<unkown>";
|
||||||
|
}
|
||||||
|
|
||||||
|
// GradientArea
|
||||||
|
BRect
|
||||||
|
Gradient::GradientArea() const
|
||||||
|
{
|
||||||
|
BRect area(0, 0, 63, 63);
|
||||||
|
switch (fType) {
|
||||||
|
case GRADIENT_LINEAR:
|
||||||
|
case GRADIENT_CIRCULAR:
|
||||||
|
case GRADIENT_DIAMONT:
|
||||||
|
case GRADIENT_CONIC:
|
||||||
|
case GRADIENT_XY:
|
||||||
|
case GRADIENT_SQRT_XY:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return area;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TransformationChanged()
|
||||||
|
void
|
||||||
|
Gradient::TransformationChanged()
|
||||||
|
{
|
||||||
|
Notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrintToStream
|
||||||
|
void
|
||||||
|
Gradient::PrintToStream() const
|
||||||
|
{
|
||||||
|
printf("Gradient: type: %s, interpolation: %s, inherits transform: %d\n",
|
||||||
|
string_for_type(fType),
|
||||||
|
string_for_interpolation(fInterpolation),
|
||||||
|
fInheritTransformation);
|
||||||
|
for (int32 i = 0; color_step* step = ColorAt(i); i++) {
|
||||||
|
printf(" %ld: offset: %.1f -> color(%d, %d, %d, %d)\n",
|
||||||
|
i, step->offset,
|
||||||
|
step->color.red,
|
||||||
|
step->color.green,
|
||||||
|
step->color.blue,
|
||||||
|
step->color.alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// _MakeEmpty
|
||||||
|
void
|
||||||
|
Gradient::_MakeEmpty()
|
||||||
|
{
|
||||||
|
int32 count = CountColors();
|
||||||
|
for (int32 i = 0; i < count; i++)
|
||||||
|
delete ColorAtFast(i);
|
||||||
|
fColors.MakeEmpty();
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GRADIENT_H
|
||||||
|
#define GRADIENT_H
|
||||||
|
|
||||||
|
#include <GraphicsDefs.h>
|
||||||
|
#include <List.h>
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
# include <Archivable.h>
|
||||||
|
|
||||||
|
# include "Observable.h"
|
||||||
|
#endif ICON_O_MATIC
|
||||||
|
|
||||||
|
#include "Transformable.h"
|
||||||
|
|
||||||
|
class BMessage;
|
||||||
|
|
||||||
|
enum gradient_type {
|
||||||
|
GRADIENT_LINEAR = 0,
|
||||||
|
GRADIENT_CIRCULAR,
|
||||||
|
GRADIENT_DIAMONT,
|
||||||
|
GRADIENT_CONIC,
|
||||||
|
GRADIENT_XY,
|
||||||
|
GRADIENT_SQRT_XY,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum interpolation_type {
|
||||||
|
INTERPOLATION_LINEAR = 0,
|
||||||
|
INTERPOLATION_SMOOTH,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct color_step {
|
||||||
|
color_step(const rgb_color c, float o);
|
||||||
|
color_step(uint8 r, uint8 g, uint8 b, uint8 a, float o);
|
||||||
|
color_step(const color_step& other);
|
||||||
|
color_step();
|
||||||
|
|
||||||
|
bool operator!=(const color_step& other) const;
|
||||||
|
|
||||||
|
rgb_color color;
|
||||||
|
float offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
class Gradient : public BArchivable,
|
||||||
|
public Observable,
|
||||||
|
public Transformable {
|
||||||
|
#else
|
||||||
|
class Gradient : public Transformable {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
|
Gradient(bool empty = false);
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
Gradient(BMessage* archive);
|
||||||
|
#endif
|
||||||
|
Gradient(const Gradient& other);
|
||||||
|
virtual ~Gradient();
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
status_t Archive(BMessage* into, bool deep = true) const;
|
||||||
|
#else
|
||||||
|
inline void Notify() {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Gradient& operator=(const Gradient& other);
|
||||||
|
|
||||||
|
bool operator==(const Gradient& other) const;
|
||||||
|
bool operator!=(const Gradient& other) const;
|
||||||
|
|
||||||
|
void SetColors(const Gradient& other);
|
||||||
|
|
||||||
|
|
||||||
|
int32 AddColor(const rgb_color& color, float offset);
|
||||||
|
bool AddColor(const color_step& color, int32 index);
|
||||||
|
|
||||||
|
bool RemoveColor(int32 index);
|
||||||
|
|
||||||
|
bool SetColor(int32 index, const color_step& step);
|
||||||
|
bool SetColor(int32 index, const rgb_color& color);
|
||||||
|
bool SetOffset(int32 index, float offset);
|
||||||
|
|
||||||
|
int32 CountColors() const;
|
||||||
|
color_step* ColorAt(int32 index) const;
|
||||||
|
color_step* ColorAtFast(int32 index) const;
|
||||||
|
|
||||||
|
void SetType(gradient_type type);
|
||||||
|
gradient_type Type() const
|
||||||
|
{ return fType; }
|
||||||
|
|
||||||
|
void SetInterpolation(interpolation_type type);
|
||||||
|
interpolation_type Interpolation() const
|
||||||
|
{ return fInterpolation; }
|
||||||
|
|
||||||
|
void SetInheritTransformation(bool inherit);
|
||||||
|
bool InheritTransformation() const
|
||||||
|
{ return fInheritTransformation; }
|
||||||
|
|
||||||
|
void MakeGradient(uint32* colors,
|
||||||
|
int32 count) const;
|
||||||
|
|
||||||
|
BRect GradientArea() const;
|
||||||
|
virtual void TransformationChanged();
|
||||||
|
|
||||||
|
void PrintToStream() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _MakeEmpty();
|
||||||
|
|
||||||
|
BList fColors;
|
||||||
|
gradient_type fType;
|
||||||
|
interpolation_type fInterpolation;
|
||||||
|
bool fInheritTransformation;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // GRADIENT_H
|
||||||
@@ -0,0 +1,220 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Style.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
# include <Message.h>
|
||||||
|
|
||||||
|
# include "ui_defines.h"
|
||||||
|
#else
|
||||||
|
# define kWhite (rgb_color){ 255, 255, 255, 255 }
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
#include "Gradient.h"
|
||||||
|
|
||||||
|
using std::nothrow;
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
Style::Style()
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
: IconObject("<style>"),
|
||||||
|
Observer(),
|
||||||
|
#else
|
||||||
|
:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fColor(kWhite),
|
||||||
|
fGradient(NULL),
|
||||||
|
fColors(NULL),
|
||||||
|
|
||||||
|
fGammaCorrectedColors(NULL),
|
||||||
|
fGammaCorrectedColorsValid(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
Style::Style(const rgb_color& color)
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
: IconObject("<style>"),
|
||||||
|
Observer(),
|
||||||
|
#else
|
||||||
|
:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fColor(color),
|
||||||
|
fGradient(NULL),
|
||||||
|
fColors(NULL),
|
||||||
|
|
||||||
|
fGammaCorrectedColors(NULL),
|
||||||
|
fGammaCorrectedColorsValid(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
Style::Style(const Style& other)
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
: IconObject(other),
|
||||||
|
Observer(),
|
||||||
|
#else
|
||||||
|
:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fColor(other.fColor),
|
||||||
|
fGradient(NULL),
|
||||||
|
fColors(NULL),
|
||||||
|
|
||||||
|
fGammaCorrectedColors(NULL),
|
||||||
|
fGammaCorrectedColorsValid(false)
|
||||||
|
{
|
||||||
|
SetGradient(other.fGradient);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// constructor
|
||||||
|
Style::Style(BMessage* archive)
|
||||||
|
: IconObject(archive),
|
||||||
|
Observer(),
|
||||||
|
|
||||||
|
fColor(kWhite),
|
||||||
|
fGradient(NULL),
|
||||||
|
fColors(NULL),
|
||||||
|
|
||||||
|
fGammaCorrectedColors(NULL),
|
||||||
|
fGammaCorrectedColorsValid(false)
|
||||||
|
{
|
||||||
|
if (!archive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (archive->FindInt32("color", (int32*)&fColor) < B_OK)
|
||||||
|
fColor = kWhite;
|
||||||
|
|
||||||
|
BMessage gradientArchive;
|
||||||
|
if (archive->FindMessage("gradient", &gradientArchive) == B_OK) {
|
||||||
|
::Gradient gradient(&gradientArchive);
|
||||||
|
SetGradient(&gradient);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
Style::~Style()
|
||||||
|
{
|
||||||
|
SetGradient(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// ObjectChanged
|
||||||
|
void
|
||||||
|
Style::ObjectChanged(const Observable* object)
|
||||||
|
{
|
||||||
|
if (object == fGradient && fColors) {
|
||||||
|
fGradient->MakeGradient((uint32*)fColors, 256);
|
||||||
|
fGammaCorrectedColorsValid = false;
|
||||||
|
Notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// Archive
|
||||||
|
status_t
|
||||||
|
Style::Archive(BMessage* into, bool deep) const
|
||||||
|
{
|
||||||
|
status_t ret = IconObject::Archive(into, deep);
|
||||||
|
|
||||||
|
if (ret == B_OK)
|
||||||
|
ret = into->AddInt32("color", (uint32&)fColor);
|
||||||
|
|
||||||
|
if (ret == B_OK && fGradient) {
|
||||||
|
BMessage gradientArchive;
|
||||||
|
ret = fGradient->Archive(&gradientArchive, deep);
|
||||||
|
if (ret == B_OK)
|
||||||
|
ret = into->AddMessage("gradient", &gradientArchive);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
// SetColor
|
||||||
|
void
|
||||||
|
Style::SetColor(const rgb_color& color)
|
||||||
|
{
|
||||||
|
if ((uint32&)fColor == (uint32&)color)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fColor = color;
|
||||||
|
Notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetGradient
|
||||||
|
void
|
||||||
|
Style::SetGradient(const ::Gradient* gradient)
|
||||||
|
{
|
||||||
|
if (!fGradient && !gradient)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (gradient) {
|
||||||
|
if (!fGradient) {
|
||||||
|
fGradient = new (nothrow) ::Gradient(*gradient);
|
||||||
|
if (fGradient) {
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
fGradient->AddObserver(this);
|
||||||
|
#endif
|
||||||
|
// generate gradient
|
||||||
|
fColors = new agg::rgba8[256];
|
||||||
|
fGradient->MakeGradient((uint32*)fColors, 256);
|
||||||
|
fGammaCorrectedColorsValid = false;
|
||||||
|
|
||||||
|
Notify();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (*fGradient != *gradient) {
|
||||||
|
*fGradient = *gradient;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
fGradient->RemoveObserver(this);
|
||||||
|
#endif
|
||||||
|
delete[] fColors;
|
||||||
|
delete[] fGammaCorrectedColors;
|
||||||
|
fColors = NULL;
|
||||||
|
fGammaCorrectedColors = NULL;
|
||||||
|
fGradient = NULL;
|
||||||
|
Notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GammaCorrectedColors
|
||||||
|
const agg::rgba8*
|
||||||
|
Style::GammaCorrectedColors(const GammaTable& table) const
|
||||||
|
{
|
||||||
|
if (!fColors)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!fGammaCorrectedColors)
|
||||||
|
fGammaCorrectedColors = new agg::rgba8[256];
|
||||||
|
|
||||||
|
if (!fGammaCorrectedColorsValid) {
|
||||||
|
for (int32 i = 0; i < 256; i++) {
|
||||||
|
fGammaCorrectedColors[i].r = table.dir(fColors[i].r);
|
||||||
|
fGammaCorrectedColors[i].g = table.dir(fColors[i].g);
|
||||||
|
fGammaCorrectedColors[i].b = table.dir(fColors[i].b);
|
||||||
|
fGammaCorrectedColors[i].a = fColors[i].a;
|
||||||
|
fGammaCorrectedColors[i].premultiply();
|
||||||
|
}
|
||||||
|
fGammaCorrectedColorsValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fGammaCorrectedColors;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef STYLE_H
|
||||||
|
#define STYLE_H
|
||||||
|
|
||||||
|
#include <GraphicsDefs.h>
|
||||||
|
|
||||||
|
#include <agg_color_rgba.h>
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
# include "IconObject.h"
|
||||||
|
# include "Observer.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "IconRenderer.h"
|
||||||
|
// TODO: put GammaTable into its own file
|
||||||
|
|
||||||
|
class Gradient;
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
class Style : public IconObject,
|
||||||
|
public Observer {
|
||||||
|
#else
|
||||||
|
class Style {
|
||||||
|
#endif
|
||||||
|
public:
|
||||||
|
Style();
|
||||||
|
Style(const Style& other);
|
||||||
|
Style(const rgb_color& color);
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
Style(BMessage* archive);
|
||||||
|
#endif
|
||||||
|
virtual ~Style();
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// Observer interface
|
||||||
|
virtual void ObjectChanged(const Observable* object);
|
||||||
|
|
||||||
|
// Style
|
||||||
|
status_t Archive(BMessage* into,
|
||||||
|
bool deep = true) const;
|
||||||
|
#else
|
||||||
|
inline void Notify() {}
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
void SetColor(const rgb_color& color);
|
||||||
|
inline rgb_color Color() const
|
||||||
|
{ return fColor; }
|
||||||
|
|
||||||
|
void SetGradient(const ::Gradient* gradient);
|
||||||
|
::Gradient* Gradient() const
|
||||||
|
{ return fGradient; }
|
||||||
|
|
||||||
|
const agg::rgba8* Colors() const
|
||||||
|
{ return fColors; }
|
||||||
|
|
||||||
|
const agg::rgba8* GammaCorrectedColors(
|
||||||
|
const GammaTable& table) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
rgb_color fColor;
|
||||||
|
::Gradient* fGradient;
|
||||||
|
|
||||||
|
// hold gradient color array
|
||||||
|
agg::rgba8* fColors;
|
||||||
|
|
||||||
|
// for caching gamma corrected gradient color array
|
||||||
|
mutable agg::rgba8* fGammaCorrectedColors;
|
||||||
|
mutable bool fGammaCorrectedColorsValid;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // STYLE_H
|
||||||
@@ -0,0 +1,215 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "StyleContainer.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
|
||||||
|
#include "Style.h"
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
StyleContainerListener::StyleContainerListener() {}
|
||||||
|
StyleContainerListener::~StyleContainerListener() {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
StyleContainer::StyleContainer()
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
: fStyles(32),
|
||||||
|
fListeners(2)
|
||||||
|
#else
|
||||||
|
: fStyles(32)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
StyleContainer::~StyleContainer()
|
||||||
|
{
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
int32 count = fListeners.CountItems();
|
||||||
|
if (count > 0) {
|
||||||
|
debugger("~StyleContainer() - there are still"
|
||||||
|
"listeners attached\n");
|
||||||
|
}
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
_MakeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// AddStyle
|
||||||
|
bool
|
||||||
|
StyleContainer::AddStyle(Style* style)
|
||||||
|
{
|
||||||
|
if (!style)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// prevent adding the same style twice
|
||||||
|
if (HasStyle(style))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (fStyles.AddItem((void*)style)) {
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
_NotifyStyleAdded(style);
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "StyleContainer::AddStyle() - out of memory!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveStyle
|
||||||
|
bool
|
||||||
|
StyleContainer::RemoveStyle(Style* style)
|
||||||
|
{
|
||||||
|
if (fStyles.RemoveItem((void*)style)) {
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
_NotifyStyleRemoved(style);
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveStyle
|
||||||
|
Style*
|
||||||
|
StyleContainer::RemoveStyle(int32 index)
|
||||||
|
{
|
||||||
|
Style* style = (Style*)fStyles.RemoveItem(index);
|
||||||
|
if (style) {
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
_NotifyStyleRemoved(style);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeEmpty
|
||||||
|
void
|
||||||
|
StyleContainer::MakeEmpty()
|
||||||
|
{
|
||||||
|
_MakeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// CountStyles
|
||||||
|
int32
|
||||||
|
StyleContainer::CountStyles() const
|
||||||
|
{
|
||||||
|
return fStyles.CountItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasStyle
|
||||||
|
bool
|
||||||
|
StyleContainer::HasStyle(Style* style) const
|
||||||
|
{
|
||||||
|
return fStyles.HasItem((void*)style);
|
||||||
|
}
|
||||||
|
|
||||||
|
// IndexOf
|
||||||
|
int32
|
||||||
|
StyleContainer::IndexOf(Style* style) const
|
||||||
|
{
|
||||||
|
return fStyles.IndexOf((void*)style);
|
||||||
|
}
|
||||||
|
|
||||||
|
// StyleAt
|
||||||
|
Style*
|
||||||
|
StyleContainer::StyleAt(int32 index) const
|
||||||
|
{
|
||||||
|
return (Style*)fStyles.ItemAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// StyleAtFast
|
||||||
|
Style*
|
||||||
|
StyleContainer::StyleAtFast(int32 index) const
|
||||||
|
{
|
||||||
|
return (Style*)fStyles.ItemAtFast(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
|
||||||
|
// AddListener
|
||||||
|
bool
|
||||||
|
StyleContainer::AddListener(StyleContainerListener* listener)
|
||||||
|
{
|
||||||
|
if (listener && !fListeners.HasItem((void*)listener))
|
||||||
|
return fListeners.AddItem(listener);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveListener
|
||||||
|
bool
|
||||||
|
StyleContainer::RemoveListener(StyleContainerListener* listener)
|
||||||
|
{
|
||||||
|
return fListeners.RemoveItem(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// _MakeEmpty
|
||||||
|
void
|
||||||
|
StyleContainer::_MakeEmpty()
|
||||||
|
{
|
||||||
|
int32 count = CountStyles();
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
Style* style = StyleAtFast(i);
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
_NotifyStyleRemoved(style);
|
||||||
|
style->Release();
|
||||||
|
#else
|
||||||
|
delete style;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
fStyles.MakeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
|
||||||
|
// _NotifyStyleAdded
|
||||||
|
void
|
||||||
|
StyleContainer::_NotifyStyleAdded(Style* style) const
|
||||||
|
{
|
||||||
|
BList listeners(fListeners);
|
||||||
|
int32 count = listeners.CountItems();
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
StyleContainerListener* listener
|
||||||
|
= (StyleContainerListener*)listeners.ItemAtFast(i);
|
||||||
|
listener->StyleAdded(style);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// _NotifyStyleRemoved
|
||||||
|
void
|
||||||
|
StyleContainer::_NotifyStyleRemoved(Style* style) const
|
||||||
|
{
|
||||||
|
BList listeners(fListeners);
|
||||||
|
int32 count = listeners.CountItems();
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
StyleContainerListener* listener
|
||||||
|
= (StyleContainerListener*)listeners.ItemAtFast(i);
|
||||||
|
listener->StyleRemoved(style);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef STYLE_MANAGER_H
|
||||||
|
#define STYLE_MANAGER_H
|
||||||
|
|
||||||
|
#include <List.h>
|
||||||
|
|
||||||
|
class Style;
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
class StyleContainerListener {
|
||||||
|
public:
|
||||||
|
StyleContainerListener();
|
||||||
|
virtual ~StyleContainerListener();
|
||||||
|
|
||||||
|
virtual void StyleAdded(Style* style) = 0;
|
||||||
|
virtual void StyleRemoved(Style* style) = 0;
|
||||||
|
};
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
class StyleContainer {
|
||||||
|
public:
|
||||||
|
StyleContainer();
|
||||||
|
virtual ~StyleContainer();
|
||||||
|
|
||||||
|
bool AddStyle(Style* style);
|
||||||
|
bool RemoveStyle(Style* style);
|
||||||
|
Style* RemoveStyle(int32 index);
|
||||||
|
|
||||||
|
void MakeEmpty();
|
||||||
|
|
||||||
|
int32 CountStyles() const;
|
||||||
|
bool HasStyle(Style* style) const;
|
||||||
|
int32 IndexOf(Style* style) const;
|
||||||
|
|
||||||
|
Style* StyleAt(int32 index) const;
|
||||||
|
Style* StyleAtFast(int32 index) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
BList fStyles;
|
||||||
|
|
||||||
|
void _MakeEmpty();
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
public:
|
||||||
|
bool AddListener(StyleContainerListener* listener);
|
||||||
|
bool RemoveListener(StyleContainerListener* listener);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _NotifyStyleAdded(Style* style) const;
|
||||||
|
void _NotifyStyleRemoved(Style* style) const;
|
||||||
|
|
||||||
|
BList fListeners;
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // STYLE_MANAGER_H
|
||||||
@@ -0,0 +1,315 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Transformable.h"
|
||||||
|
|
||||||
|
#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
|
||||||
|
void
|
||||||
|
Transformable::StoreTo(double matrix[matrix_size]) const
|
||||||
|
{
|
||||||
|
store_to(matrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadFrom
|
||||||
|
void
|
||||||
|
Transformable::LoadFrom(const double matrix[matrix_size])
|
||||||
|
{
|
||||||
|
// before calling the potentially heavy TransformationChanged()
|
||||||
|
// hook function, make sure that the transformation
|
||||||
|
// really changed
|
||||||
|
Transformable t;
|
||||||
|
t.load_from(matrix);
|
||||||
|
if (*this != t) {
|
||||||
|
load_from(matrix);
|
||||||
|
TransformationChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTransform
|
||||||
|
void
|
||||||
|
Transformable::SetTransform(const Transformable& other)
|
||||||
|
{
|
||||||
|
if (*this != other) {
|
||||||
|
*this = other;
|
||||||
|
TransformationChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// operator=
|
||||||
|
Transformable&
|
||||||
|
Transformable::operator=(const Transformable& other)
|
||||||
|
{
|
||||||
|
if (other != *this) {
|
||||||
|
reset();
|
||||||
|
multiply(other);
|
||||||
|
TransformationChanged();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiply
|
||||||
|
Transformable&
|
||||||
|
Transformable::Multiply(const Transformable& other)
|
||||||
|
{
|
||||||
|
if (!other.IsIdentity()) {
|
||||||
|
multiply(other);
|
||||||
|
TransformationChanged();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset
|
||||||
|
void
|
||||||
|
Transformable::Reset()
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invert
|
||||||
|
void
|
||||||
|
Transformable::Invert()
|
||||||
|
{
|
||||||
|
invert();
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsIdentity
|
||||||
|
bool
|
||||||
|
Transformable::IsIdentity() const
|
||||||
|
{
|
||||||
|
double m[matrix_size];
|
||||||
|
store_to(m);
|
||||||
|
if (m[0] == 1.0 &&
|
||||||
|
m[1] == 0.0 &&
|
||||||
|
m[2] == 0.0 &&
|
||||||
|
m[3] == 1.0 &&
|
||||||
|
m[4] == 0.0 &&
|
||||||
|
m[5] == 0.0)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsTranslationOnly
|
||||||
|
bool
|
||||||
|
Transformable::IsTranslationOnly() const
|
||||||
|
{
|
||||||
|
double m[matrix_size];
|
||||||
|
store_to(m);
|
||||||
|
if (m[0] == 1.0 &&
|
||||||
|
m[1] == 0.0 &&
|
||||||
|
m[2] == 0.0 &&
|
||||||
|
m[3] == 1.0)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNotDistorted
|
||||||
|
bool
|
||||||
|
Transformable::IsNotDistorted() const
|
||||||
|
{
|
||||||
|
double m[matrix_size];
|
||||||
|
store_to(m);
|
||||||
|
return (m[0] == m[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsValid
|
||||||
|
bool
|
||||||
|
Transformable::IsValid() const
|
||||||
|
{
|
||||||
|
double m[matrix_size];
|
||||||
|
store_to(m);
|
||||||
|
return ((m[0] * m[3] - m[1] * m[2]) != 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// operator==
|
||||||
|
bool
|
||||||
|
Transformable::operator==(const Transformable& other) const
|
||||||
|
{
|
||||||
|
double m1[matrix_size];
|
||||||
|
other.store_to(m1);
|
||||||
|
double m2[matrix_size];
|
||||||
|
store_to(m2);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
if (bounds.IsValid()) {
|
||||||
|
BPoint lt(bounds.left, bounds.top);
|
||||||
|
BPoint rt(bounds.right, bounds.top);
|
||||||
|
BPoint lb(bounds.left, bounds.bottom);
|
||||||
|
BPoint rb(bounds.right, bounds.bottom);
|
||||||
|
|
||||||
|
Transform(<);
|
||||||
|
Transform(&rt);
|
||||||
|
Transform(&lb);
|
||||||
|
Transform(&rb);
|
||||||
|
|
||||||
|
return BRect(floorf(min4(lt.x, rt.x, lb.x, rb.x)),
|
||||||
|
floorf(min4(lt.y, rt.y, lb.y, rb.y)),
|
||||||
|
ceilf(max4(lt.x, rt.x, lb.x, rb.x)),
|
||||||
|
ceilf(max4(lt.y, rt.y, lb.y, rb.y)));
|
||||||
|
}
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TranslateBy
|
||||||
|
void
|
||||||
|
Transformable::TranslateBy(BPoint offset)
|
||||||
|
{
|
||||||
|
if (offset.x != 0.0 || offset.y != 0.0) {
|
||||||
|
multiply(agg::trans_affine_translation(offset.x, offset.y));
|
||||||
|
TransformationChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RotateBy
|
||||||
|
void
|
||||||
|
Transformable::RotateBy(BPoint origin, double degrees)
|
||||||
|
{
|
||||||
|
if (degrees != 0.0) {
|
||||||
|
multiply(agg::trans_affine_translation(-origin.x, -origin.y));
|
||||||
|
multiply(agg::trans_affine_rotation(degrees * (PI / 180.0)));
|
||||||
|
multiply(agg::trans_affine_translation(origin.x, origin.y));
|
||||||
|
TransformationChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScaleBy
|
||||||
|
void
|
||||||
|
Transformable::ScaleBy(BPoint origin, double xScale, double yScale)
|
||||||
|
{
|
||||||
|
if (xScale != 1.0 || yScale != 1.0) {
|
||||||
|
multiply(agg::trans_affine_translation(-origin.x, -origin.y));
|
||||||
|
multiply(agg::trans_affine_scaling(xScale, yScale));
|
||||||
|
multiply(agg::trans_affine_translation(origin.x, origin.y));
|
||||||
|
TransformationChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShearBy
|
||||||
|
void
|
||||||
|
Transformable::ShearBy(BPoint origin, double xShear, double yShear)
|
||||||
|
{
|
||||||
|
if (xShear != 0.0 || yShear != 0.0) {
|
||||||
|
multiply(agg::trans_affine_translation(-origin.x, -origin.y));
|
||||||
|
multiply(agg::trans_affine_skewing(xShear, yShear));
|
||||||
|
multiply(agg::trans_affine_translation(origin.x, origin.y));
|
||||||
|
TransformationChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TransformationChanged
|
||||||
|
void
|
||||||
|
Transformable::TransformationChanged()
|
||||||
|
{
|
||||||
|
// default implementation doesn't care
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TRANSFORMABLE_H
|
||||||
|
#define TRANSFORMABLE_H
|
||||||
|
|
||||||
|
#include <Rect.h>
|
||||||
|
|
||||||
|
#include <agg_trans_affine.h>
|
||||||
|
|
||||||
|
class Transformable : public agg::trans_affine {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
matrix_size = 6,
|
||||||
|
};
|
||||||
|
|
||||||
|
Transformable();
|
||||||
|
Transformable(const Transformable& other);
|
||||||
|
virtual ~Transformable();
|
||||||
|
|
||||||
|
void StoreTo(double matrix[matrix_size]) const;
|
||||||
|
void LoadFrom(const double matrix[matrix_size]);
|
||||||
|
|
||||||
|
// set to or combine with other matrix
|
||||||
|
void SetTransform(const Transformable& other);
|
||||||
|
Transformable& operator=(const Transformable& other);
|
||||||
|
Transformable& Multiply(const Transformable& other);
|
||||||
|
virtual void Reset();
|
||||||
|
|
||||||
|
void Invert();
|
||||||
|
|
||||||
|
bool IsIdentity() const;
|
||||||
|
bool IsTranslationOnly() const;
|
||||||
|
bool IsNotDistorted() const;
|
||||||
|
bool IsValid() const;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
// some convenience functions
|
||||||
|
virtual void TranslateBy(BPoint offset);
|
||||||
|
virtual void RotateBy(BPoint origin, double degrees);
|
||||||
|
virtual void ScaleBy(BPoint origin, double xScale, double yScale);
|
||||||
|
virtual void ShearBy(BPoint origin, double xShear, double yShear);
|
||||||
|
|
||||||
|
virtual void TransformationChanged();
|
||||||
|
// hook function that is called when the transformation
|
||||||
|
// is changed for some reason
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TRANSFORMABLE_H
|
||||||
|
|
||||||
@@ -0,0 +1,194 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "AffineTransformer.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
# include <Message.h>
|
||||||
|
|
||||||
|
# include "CommonPropertyIDs.h"
|
||||||
|
# include "Property.h"
|
||||||
|
# include "PropertyObject.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
using std::nothrow;
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
AffineTransformer::AffineTransformer(VertexSource& source)
|
||||||
|
: Transformer(source, "Transformation"),
|
||||||
|
Affine(source, *this)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// constructor
|
||||||
|
AffineTransformer::AffineTransformer(VertexSource& source,
|
||||||
|
BMessage* archive)
|
||||||
|
: Transformer(source, archive),
|
||||||
|
Affine(source, *this)
|
||||||
|
{
|
||||||
|
if (!archive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int32 size = 6;
|
||||||
|
const void* matrix;
|
||||||
|
ssize_t dataSize = size * sizeof(double);
|
||||||
|
if (archive->FindData("matrix", B_DOUBLE_TYPE,
|
||||||
|
&matrix, &dataSize) == B_OK) {
|
||||||
|
if (dataSize == (ssize_t)(size * sizeof(double)))
|
||||||
|
load_from((const double*)matrix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
AffineTransformer::~AffineTransformer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone
|
||||||
|
Transformer*
|
||||||
|
AffineTransformer::Clone(VertexSource& source) const
|
||||||
|
{
|
||||||
|
AffineTransformer* clone = new (nothrow) AffineTransformer(source);
|
||||||
|
if (clone)
|
||||||
|
clone->multiply(*this);
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rewind
|
||||||
|
void
|
||||||
|
AffineTransformer::rewind(unsigned path_id)
|
||||||
|
{
|
||||||
|
Affine::rewind(path_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// vertex
|
||||||
|
unsigned
|
||||||
|
AffineTransformer::vertex(double* x, double* y)
|
||||||
|
{
|
||||||
|
return Affine::vertex(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSource
|
||||||
|
void
|
||||||
|
AffineTransformer::SetSource(VertexSource& source)
|
||||||
|
{
|
||||||
|
Transformer::SetSource(source);
|
||||||
|
Affine::attach(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApproximationScale
|
||||||
|
double
|
||||||
|
AffineTransformer::ApproximationScale() const
|
||||||
|
{
|
||||||
|
return fSource.ApproximationScale() * scale();
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
|
||||||
|
// Archive
|
||||||
|
status_t
|
||||||
|
AffineTransformer::Archive(BMessage* into, bool deep) const
|
||||||
|
{
|
||||||
|
status_t ret = Transformer::Archive(into, deep);
|
||||||
|
|
||||||
|
if (ret == B_OK)
|
||||||
|
into->what = archive_code;
|
||||||
|
|
||||||
|
if (ret == B_OK) {
|
||||||
|
double matrix[6];
|
||||||
|
store_to(matrix);
|
||||||
|
ret = into->AddData("matrix", B_DOUBLE_TYPE,
|
||||||
|
matrix, 6 * sizeof(double));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakePropertyObject
|
||||||
|
PropertyObject*
|
||||||
|
AffineTransformer::MakePropertyObject() const
|
||||||
|
{
|
||||||
|
PropertyObject* object = Transformer::MakePropertyObject();
|
||||||
|
if (!object)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// translation
|
||||||
|
double tx;
|
||||||
|
double ty;
|
||||||
|
translation(&tx, &ty);
|
||||||
|
object->AddProperty(new FloatProperty(PROPERTY_TRANSLATION_X, tx));
|
||||||
|
object->AddProperty(new FloatProperty(PROPERTY_TRANSLATION_Y, ty));
|
||||||
|
|
||||||
|
// rotation
|
||||||
|
object->AddProperty(new FloatProperty(PROPERTY_ROTATION,
|
||||||
|
agg::rad2deg(rotation())));
|
||||||
|
|
||||||
|
// scale
|
||||||
|
double scaleX;
|
||||||
|
double scaleY;
|
||||||
|
scaling(&scaleX, &scaleY);
|
||||||
|
object->AddProperty(new FloatProperty(PROPERTY_SCALE_X, scaleX));
|
||||||
|
object->AddProperty(new FloatProperty(PROPERTY_SCALE_Y, scaleY));
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetToPropertyObject
|
||||||
|
bool
|
||||||
|
AffineTransformer::SetToPropertyObject(const PropertyObject* object)
|
||||||
|
{
|
||||||
|
AutoNotificationSuspender _(this);
|
||||||
|
Transformer::SetToPropertyObject(object);
|
||||||
|
|
||||||
|
// current affine parameters
|
||||||
|
double tx;
|
||||||
|
double ty;
|
||||||
|
translation(&tx, &ty);
|
||||||
|
double r = rotation();
|
||||||
|
double scaleX;
|
||||||
|
double scaleY;
|
||||||
|
scaling(&scaleX, &scaleY);
|
||||||
|
|
||||||
|
// properties
|
||||||
|
double newTX = object->Value(PROPERTY_TRANSLATION_X, (float)tx);
|
||||||
|
double newTY = object->Value(PROPERTY_TRANSLATION_Y, (float)ty);
|
||||||
|
|
||||||
|
double newR = object->Value(PROPERTY_ROTATION,
|
||||||
|
(float)agg::rad2deg(r));
|
||||||
|
newR = agg::deg2rad(newR);
|
||||||
|
|
||||||
|
double newScaleX = object->Value(PROPERTY_SCALE_X, (float)scaleX);
|
||||||
|
double newScaleY = object->Value(PROPERTY_SCALE_Y, (float)scaleY);
|
||||||
|
|
||||||
|
if (newTX != tx || newTY != ty
|
||||||
|
|| newR != r
|
||||||
|
|| newScaleX != scaleX
|
||||||
|
|| newScaleY != scaleY) {
|
||||||
|
|
||||||
|
reset();
|
||||||
|
|
||||||
|
multiply(agg::trans_affine_scaling(newScaleX, newScaleY));
|
||||||
|
multiply(agg::trans_affine_rotation(newR));
|
||||||
|
multiply(agg::trans_affine_translation(newTX, newTY));
|
||||||
|
|
||||||
|
Notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
return HasPendingNotifications();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AFFINE_TRANSFORMER_H
|
||||||
|
#define AFFINE_TRANSFORMER_H
|
||||||
|
|
||||||
|
#include <agg_conv_transform.h>
|
||||||
|
#include <agg_trans_affine.h>
|
||||||
|
|
||||||
|
#include "Transformer.h"
|
||||||
|
|
||||||
|
typedef agg::conv_transform<VertexSource,
|
||||||
|
agg::trans_affine> Affine;
|
||||||
|
|
||||||
|
class AffineTransformer : public Transformer,
|
||||||
|
public Affine,
|
||||||
|
public agg::trans_affine {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
archive_code = 'affn',
|
||||||
|
};
|
||||||
|
|
||||||
|
AffineTransformer(
|
||||||
|
VertexSource& source);
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
AffineTransformer(
|
||||||
|
VertexSource& source,
|
||||||
|
BMessage* archive);
|
||||||
|
#endif
|
||||||
|
virtual ~AffineTransformer();
|
||||||
|
|
||||||
|
virtual Transformer* Clone(VertexSource& source) const;
|
||||||
|
|
||||||
|
virtual void rewind(unsigned path_id);
|
||||||
|
virtual unsigned vertex(double* x, double* y);
|
||||||
|
|
||||||
|
virtual void SetSource(VertexSource& source);
|
||||||
|
|
||||||
|
virtual double ApproximationScale() const;
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// IconObject interface
|
||||||
|
virtual status_t Archive(BMessage* into,
|
||||||
|
bool deep = true) const;
|
||||||
|
|
||||||
|
virtual PropertyObject* MakePropertyObject() const;
|
||||||
|
virtual bool SetToPropertyObject(
|
||||||
|
const PropertyObject* object);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // AFFINE_TRANSFORMER_H
|
||||||
@@ -0,0 +1,218 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ContourTransformer.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
# include <Message.h>
|
||||||
|
|
||||||
|
# include "CommonPropertyIDs.h"
|
||||||
|
# include "OptionProperty.h"
|
||||||
|
# include "Property.h"
|
||||||
|
# include "PropertyObject.h"
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
using std::nothrow;
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
ContourTransformer::ContourTransformer(VertexSource& source)
|
||||||
|
: Transformer(source, "Contour"),
|
||||||
|
Contour(source)
|
||||||
|
{
|
||||||
|
auto_detect_orientation(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// constructor
|
||||||
|
ContourTransformer::ContourTransformer(VertexSource& source,
|
||||||
|
BMessage* archive)
|
||||||
|
: Transformer(source, archive),
|
||||||
|
Contour(source)
|
||||||
|
{
|
||||||
|
auto_detect_orientation(true);
|
||||||
|
|
||||||
|
if (!archive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int32 mode;
|
||||||
|
if (archive->FindInt32("line join", &mode) == B_OK)
|
||||||
|
line_join((agg::line_join_e)mode);
|
||||||
|
|
||||||
|
if (archive->FindInt32("inner join", &mode) == B_OK)
|
||||||
|
inner_join((agg::inner_join_e)mode);
|
||||||
|
|
||||||
|
double value;
|
||||||
|
if (archive->FindDouble("width", &value) == B_OK)
|
||||||
|
width(value);
|
||||||
|
|
||||||
|
if (archive->FindDouble("miter limit", &value) == B_OK)
|
||||||
|
miter_limit(value);
|
||||||
|
|
||||||
|
if (archive->FindDouble("inner miter limit", &value) == B_OK)
|
||||||
|
inner_miter_limit(value);
|
||||||
|
}
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
ContourTransformer::~ContourTransformer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone
|
||||||
|
Transformer*
|
||||||
|
ContourTransformer::Clone(VertexSource& source) const
|
||||||
|
{
|
||||||
|
ContourTransformer* clone = new (nothrow) ContourTransformer(source);
|
||||||
|
if (clone) {
|
||||||
|
clone->line_join(line_join());
|
||||||
|
clone->inner_join(inner_join());
|
||||||
|
clone->width(width());
|
||||||
|
clone->miter_limit(miter_limit());
|
||||||
|
clone->inner_miter_limit(inner_miter_limit());
|
||||||
|
clone->auto_detect_orientation(auto_detect_orientation());
|
||||||
|
}
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rewind
|
||||||
|
void
|
||||||
|
ContourTransformer::rewind(unsigned path_id)
|
||||||
|
{
|
||||||
|
Contour::rewind(path_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// vertex
|
||||||
|
unsigned
|
||||||
|
ContourTransformer::vertex(double* x, double* y)
|
||||||
|
{
|
||||||
|
return Contour::vertex(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSource
|
||||||
|
void
|
||||||
|
ContourTransformer::SetSource(VertexSource& source)
|
||||||
|
{
|
||||||
|
Transformer::SetSource(source);
|
||||||
|
Contour::attach(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApproximationScale
|
||||||
|
double
|
||||||
|
ContourTransformer::ApproximationScale() const
|
||||||
|
{
|
||||||
|
return fSource.ApproximationScale() * width();
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
|
||||||
|
// Archive
|
||||||
|
status_t
|
||||||
|
ContourTransformer::Archive(BMessage* into, bool deep) const
|
||||||
|
{
|
||||||
|
status_t ret = Transformer::Archive(into, deep);
|
||||||
|
|
||||||
|
if (ret == B_OK)
|
||||||
|
into->what = archive_code;
|
||||||
|
|
||||||
|
if (ret == B_OK)
|
||||||
|
ret = into->AddInt32("line join", line_join());
|
||||||
|
|
||||||
|
if (ret == B_OK)
|
||||||
|
ret = into->AddInt32("inner join", inner_join());
|
||||||
|
|
||||||
|
if (ret == B_OK)
|
||||||
|
ret = into->AddDouble("width", width());
|
||||||
|
|
||||||
|
if (ret == B_OK)
|
||||||
|
ret = into->AddDouble("miter limit", miter_limit());
|
||||||
|
|
||||||
|
if (ret == B_OK)
|
||||||
|
ret = into->AddDouble("inner miter limit", inner_miter_limit());
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakePropertyObject
|
||||||
|
PropertyObject*
|
||||||
|
ContourTransformer::MakePropertyObject() const
|
||||||
|
{
|
||||||
|
PropertyObject* object = Transformer::MakePropertyObject();
|
||||||
|
if (!object)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// width
|
||||||
|
object->AddProperty(new FloatProperty(PROPERTY_WIDTH, width()));
|
||||||
|
|
||||||
|
// auto detect orientation
|
||||||
|
object->AddProperty(new BoolProperty(PROPERTY_DETECT_ORIENTATION,
|
||||||
|
auto_detect_orientation()));
|
||||||
|
|
||||||
|
// join mode
|
||||||
|
OptionProperty* property = new OptionProperty(PROPERTY_JOIN_MODE);
|
||||||
|
property->AddOption(agg::miter_join, "Miter");
|
||||||
|
property->AddOption(agg::round_join, "Round");
|
||||||
|
property->AddOption(agg::bevel_join, "Bevel");
|
||||||
|
property->SetCurrentOptionID(line_join());
|
||||||
|
|
||||||
|
object->AddProperty(property);
|
||||||
|
|
||||||
|
// miter limit
|
||||||
|
object->AddProperty(new FloatProperty(PROPERTY_MITER_LIMIT,
|
||||||
|
miter_limit()));
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetToPropertyObject
|
||||||
|
bool
|
||||||
|
ContourTransformer::SetToPropertyObject(const PropertyObject* object)
|
||||||
|
{
|
||||||
|
AutoNotificationSuspender _(this);
|
||||||
|
Transformer::SetToPropertyObject(object);
|
||||||
|
|
||||||
|
// width
|
||||||
|
float w = object->Value(PROPERTY_WIDTH, (float)width());
|
||||||
|
if (w != width()) {
|
||||||
|
width(w);
|
||||||
|
Notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
// auto detect orientation
|
||||||
|
bool ado = object->Value(PROPERTY_DETECT_ORIENTATION,
|
||||||
|
auto_detect_orientation());
|
||||||
|
if (ado != auto_detect_orientation()) {
|
||||||
|
auto_detect_orientation(ado);
|
||||||
|
Notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
// join mode
|
||||||
|
OptionProperty* property = dynamic_cast<OptionProperty*>(
|
||||||
|
object->FindProperty(PROPERTY_JOIN_MODE));
|
||||||
|
if (property && line_join() != property->CurrentOptionID()) {
|
||||||
|
line_join((agg::line_join_e)property->CurrentOptionID());
|
||||||
|
Notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
// miter limit
|
||||||
|
float l = object->Value(PROPERTY_MITER_LIMIT, (float)miter_limit());
|
||||||
|
if (l != miter_limit()) {
|
||||||
|
miter_limit(l);
|
||||||
|
Notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
return HasPendingNotifications();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CONTOUR_TRANSFORMER_H
|
||||||
|
#define CONTOUR_TRANSFORMER_H
|
||||||
|
|
||||||
|
#include <agg_conv_contour.h>
|
||||||
|
|
||||||
|
#include "Transformer.h"
|
||||||
|
|
||||||
|
typedef agg::conv_contour<VertexSource> Contour;
|
||||||
|
|
||||||
|
class ContourTransformer : public Transformer,
|
||||||
|
public Contour {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
archive_code = 'cntr',
|
||||||
|
};
|
||||||
|
|
||||||
|
ContourTransformer(
|
||||||
|
VertexSource& source);
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
ContourTransformer(
|
||||||
|
VertexSource& source,
|
||||||
|
BMessage* archive);
|
||||||
|
#endif
|
||||||
|
virtual ~ContourTransformer();
|
||||||
|
|
||||||
|
virtual Transformer* Clone(VertexSource& source) const;
|
||||||
|
|
||||||
|
virtual void rewind(unsigned path_id);
|
||||||
|
virtual unsigned vertex(double* x, double* y);
|
||||||
|
|
||||||
|
virtual void SetSource(VertexSource& source);
|
||||||
|
|
||||||
|
virtual double ApproximationScale() const;
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// IconObject interface
|
||||||
|
virtual status_t Archive(BMessage* into,
|
||||||
|
bool deep = true) const;
|
||||||
|
|
||||||
|
virtual PropertyObject* MakePropertyObject() const;
|
||||||
|
virtual bool SetToPropertyObject(
|
||||||
|
const PropertyObject* object);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CONTOUR_TRANSFORMER_H
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// WantsOpenPaths
|
||||||
|
bool
|
||||||
|
PathSource::WantsOpenPaths() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApproximationScale
|
||||||
|
double
|
||||||
|
PathSource::ApproximationScale() const
|
||||||
|
{
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// Update
|
||||||
|
void
|
||||||
|
PathSource::Update(bool leavePathsOpen, double approximationScale)
|
||||||
|
{
|
||||||
|
fAGGPath.remove_all();
|
||||||
|
|
||||||
|
int32 count = fPaths->CountPaths();
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
fPaths->PathAtFast(i)->GetAGGPathStorage(fAGGPath);
|
||||||
|
if (!leavePathsOpen)
|
||||||
|
fAGGPath.close_polygon();
|
||||||
|
}
|
||||||
|
|
||||||
|
fAGGCurvedPath.approximation_scale(approximationScale);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
virtual bool WantsOpenPaths() const;
|
||||||
|
virtual double ApproximationScale() const;
|
||||||
|
|
||||||
|
// PathSource
|
||||||
|
void Update(bool leavePathsOpen,
|
||||||
|
double approximationScale);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PathContainer* fPaths;
|
||||||
|
AGGPath fAGGPath;
|
||||||
|
AGGCurvedPath fAGGCurvedPath;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PATH_SOURCE_H
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PerspectiveTransformer.h"
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
# include <Message.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
using std::nothrow;
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
PerspectiveTransformer::PerspectiveTransformer(VertexSource& source)
|
||||||
|
: Transformer(source, "Perspective"),
|
||||||
|
Perspective(source, *this)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// constructor
|
||||||
|
PerspectiveTransformer::PerspectiveTransformer(VertexSource& source,
|
||||||
|
BMessage* archive)
|
||||||
|
: Transformer(source, archive),
|
||||||
|
Perspective(source, *this)
|
||||||
|
{
|
||||||
|
// TODO: upgrade AGG to be able to use load_from() etc
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
PerspectiveTransformer::~PerspectiveTransformer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone
|
||||||
|
Transformer*
|
||||||
|
PerspectiveTransformer::Clone(VertexSource& source) const
|
||||||
|
{
|
||||||
|
PerspectiveTransformer* clone
|
||||||
|
= new (nothrow) PerspectiveTransformer(source);
|
||||||
|
if (clone) {
|
||||||
|
// TODO: upgrade AGG
|
||||||
|
// clone->multiply(*this);
|
||||||
|
}
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rewind
|
||||||
|
void
|
||||||
|
PerspectiveTransformer::rewind(unsigned path_id)
|
||||||
|
{
|
||||||
|
Perspective::rewind(path_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// vertex
|
||||||
|
unsigned
|
||||||
|
PerspectiveTransformer::vertex(double* x, double* y)
|
||||||
|
{
|
||||||
|
return Perspective::vertex(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSource
|
||||||
|
void
|
||||||
|
PerspectiveTransformer::SetSource(VertexSource& source)
|
||||||
|
{
|
||||||
|
Transformer::SetSource(source);
|
||||||
|
Perspective::attach(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApproximationScale
|
||||||
|
double
|
||||||
|
PerspectiveTransformer::ApproximationScale() const
|
||||||
|
{
|
||||||
|
// TODO: upgrade AGG
|
||||||
|
return fSource.ApproximationScale();// * scale();
|
||||||
|
}
|
||||||
|
|
||||||
|
// #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;
|
||||||
|
|
||||||
|
// TODO: upgrade AGG to be able to use store_to()
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PERSPECTIVE_TRANSFORMER_H
|
||||||
|
#define PERSPECTIVE_TRANSFORMER_H
|
||||||
|
|
||||||
|
#include <agg_conv_transform.h>
|
||||||
|
#include <agg_trans_perspective.h>
|
||||||
|
|
||||||
|
#include "Transformer.h"
|
||||||
|
|
||||||
|
typedef agg::conv_transform<VertexSource,
|
||||||
|
agg::trans_perspective> Perspective;
|
||||||
|
|
||||||
|
class PerspectiveTransformer : public Transformer,
|
||||||
|
public Perspective,
|
||||||
|
public agg::trans_perspective {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
archive_code = 'prsp',
|
||||||
|
};
|
||||||
|
|
||||||
|
PerspectiveTransformer(
|
||||||
|
VertexSource& source);
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
PerspectiveTransformer(
|
||||||
|
VertexSource& source,
|
||||||
|
BMessage* archive);
|
||||||
|
#endif
|
||||||
|
virtual ~PerspectiveTransformer();
|
||||||
|
|
||||||
|
// Transformer interface
|
||||||
|
virtual Transformer* Clone(VertexSource& source) const;
|
||||||
|
|
||||||
|
virtual void rewind(unsigned path_id);
|
||||||
|
virtual unsigned vertex(double* x, double* y);
|
||||||
|
|
||||||
|
virtual void SetSource(VertexSource& source);
|
||||||
|
|
||||||
|
virtual double ApproximationScale() const;
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// IconObject interface
|
||||||
|
virtual status_t Archive(BMessage* into,
|
||||||
|
bool deep = true) const;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PERSPECTIVE_TRANSFORMER_H
|
||||||
@@ -0,0 +1,251 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "StrokeTransformer.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
# include <Message.h>
|
||||||
|
|
||||||
|
# include "CommonPropertyIDs.h"
|
||||||
|
# include "OptionProperty.h"
|
||||||
|
# include "Property.h"
|
||||||
|
# include "PropertyObject.h"
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
using std::nothrow;
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
StrokeTransformer::StrokeTransformer(VertexSource& source)
|
||||||
|
: Transformer(source, "Stroke"),
|
||||||
|
Stroke(source)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// constructor
|
||||||
|
StrokeTransformer::StrokeTransformer(VertexSource& source,
|
||||||
|
BMessage* archive)
|
||||||
|
: Transformer(source, archive),
|
||||||
|
Stroke(source)
|
||||||
|
{
|
||||||
|
if (!archive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int32 mode;
|
||||||
|
if (archive->FindInt32("line cap", &mode) == B_OK)
|
||||||
|
line_cap((agg::line_cap_e)mode);
|
||||||
|
|
||||||
|
if (archive->FindInt32("line join", &mode) == B_OK)
|
||||||
|
line_join((agg::line_join_e)mode);
|
||||||
|
|
||||||
|
if (archive->FindInt32("inner join", &mode) == B_OK)
|
||||||
|
inner_join((agg::inner_join_e)mode);
|
||||||
|
|
||||||
|
double value;
|
||||||
|
if (archive->FindDouble("width", &value) == B_OK)
|
||||||
|
width(value);
|
||||||
|
|
||||||
|
if (archive->FindDouble("miter limit", &value) == B_OK)
|
||||||
|
miter_limit(value);
|
||||||
|
|
||||||
|
if (archive->FindDouble("inner miter limit", &value) == B_OK)
|
||||||
|
inner_miter_limit(value);
|
||||||
|
|
||||||
|
if (archive->FindDouble("shorten", &value) == B_OK)
|
||||||
|
shorten(value);
|
||||||
|
}
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
StrokeTransformer::~StrokeTransformer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone
|
||||||
|
Transformer*
|
||||||
|
StrokeTransformer::Clone(VertexSource& source) const
|
||||||
|
{
|
||||||
|
StrokeTransformer* clone = new (nothrow) StrokeTransformer(source);
|
||||||
|
if (clone) {
|
||||||
|
clone->line_cap(line_cap());
|
||||||
|
clone->line_join(line_join());
|
||||||
|
clone->inner_join(inner_join());
|
||||||
|
clone->width(width());
|
||||||
|
clone->miter_limit(miter_limit());
|
||||||
|
clone->inner_miter_limit(inner_miter_limit());
|
||||||
|
clone->shorten(shorten());
|
||||||
|
}
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// WantsOpenPaths
|
||||||
|
bool
|
||||||
|
StrokeTransformer::WantsOpenPaths() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApproximationScale
|
||||||
|
double
|
||||||
|
StrokeTransformer::ApproximationScale() const
|
||||||
|
{
|
||||||
|
return fSource.ApproximationScale() * width();
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
|
||||||
|
// Archive
|
||||||
|
status_t
|
||||||
|
StrokeTransformer::Archive(BMessage* into, bool deep) const
|
||||||
|
{
|
||||||
|
status_t ret = Transformer::Archive(into, deep);
|
||||||
|
|
||||||
|
if (ret == B_OK)
|
||||||
|
into->what = archive_code;
|
||||||
|
|
||||||
|
if (ret == B_OK)
|
||||||
|
ret = into->AddInt32("line cap", line_cap());
|
||||||
|
|
||||||
|
if (ret == B_OK)
|
||||||
|
ret = into->AddInt32("line join", line_join());
|
||||||
|
|
||||||
|
if (ret == B_OK)
|
||||||
|
ret = into->AddInt32("inner join", inner_join());
|
||||||
|
|
||||||
|
if (ret == B_OK)
|
||||||
|
ret = into->AddDouble("width", width());
|
||||||
|
|
||||||
|
if (ret == B_OK)
|
||||||
|
ret = into->AddDouble("miter limit", miter_limit());
|
||||||
|
|
||||||
|
if (ret == B_OK)
|
||||||
|
ret = into->AddDouble("inner miter limit", inner_miter_limit());
|
||||||
|
|
||||||
|
if (ret == B_OK)
|
||||||
|
ret = into->AddDouble("shorten",shorten());
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakePropertyObject
|
||||||
|
PropertyObject*
|
||||||
|
StrokeTransformer::MakePropertyObject() const
|
||||||
|
{
|
||||||
|
PropertyObject* object = Transformer::MakePropertyObject();
|
||||||
|
if (!object)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// width
|
||||||
|
object->AddProperty(new FloatProperty(PROPERTY_WIDTH, width()));
|
||||||
|
|
||||||
|
// cap mode
|
||||||
|
OptionProperty* property = new OptionProperty(PROPERTY_CAP_MODE);
|
||||||
|
property->AddOption(agg::butt_cap, "Butt");
|
||||||
|
property->AddOption(agg::square_cap, "Square");
|
||||||
|
property->AddOption(agg::round_cap, "Round");
|
||||||
|
property->SetCurrentOptionID(line_cap());
|
||||||
|
|
||||||
|
object->AddProperty(property);
|
||||||
|
|
||||||
|
// join mode
|
||||||
|
property = new OptionProperty(PROPERTY_JOIN_MODE);
|
||||||
|
property->AddOption(agg::miter_join, "Miter");
|
||||||
|
property->AddOption(agg::round_join, "Round");
|
||||||
|
property->AddOption(agg::bevel_join, "Bevel");
|
||||||
|
property->SetCurrentOptionID(line_join());
|
||||||
|
|
||||||
|
object->AddProperty(property);
|
||||||
|
|
||||||
|
// miter limit
|
||||||
|
if (line_join() == agg::miter_join) {
|
||||||
|
object->AddProperty(new FloatProperty(PROPERTY_MITER_LIMIT,
|
||||||
|
miter_limit()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// shorten
|
||||||
|
object->AddProperty(new FloatProperty(PROPERTY_STROKE_SHORTEN,
|
||||||
|
shorten()));
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetToPropertyObject
|
||||||
|
bool
|
||||||
|
StrokeTransformer::SetToPropertyObject(const PropertyObject* object)
|
||||||
|
{
|
||||||
|
AutoNotificationSuspender _(this);
|
||||||
|
Transformer::SetToPropertyObject(object);
|
||||||
|
|
||||||
|
// width
|
||||||
|
float w = object->Value(PROPERTY_WIDTH, (float)width());
|
||||||
|
if (w != width()) {
|
||||||
|
width(w);
|
||||||
|
Notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
// cap mode
|
||||||
|
OptionProperty* property = dynamic_cast<OptionProperty*>(
|
||||||
|
object->FindProperty(PROPERTY_CAP_MODE));
|
||||||
|
if (property && line_cap() != property->CurrentOptionID()) {
|
||||||
|
line_cap((agg::line_cap_e)property->CurrentOptionID());
|
||||||
|
Notify();
|
||||||
|
}
|
||||||
|
// join mode
|
||||||
|
property = dynamic_cast<OptionProperty*>(
|
||||||
|
object->FindProperty(PROPERTY_JOIN_MODE));
|
||||||
|
if (property && line_join() != property->CurrentOptionID()) {
|
||||||
|
line_join((agg::line_join_e)property->CurrentOptionID());
|
||||||
|
Notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
// miter limit
|
||||||
|
float l = object->Value(PROPERTY_MITER_LIMIT, (float)miter_limit());
|
||||||
|
if (l != miter_limit()) {
|
||||||
|
miter_limit(l);
|
||||||
|
Notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
// shorten
|
||||||
|
float s = object->Value(PROPERTY_STROKE_SHORTEN, (float)shorten());
|
||||||
|
if (s != shorten()) {
|
||||||
|
shorten(s);
|
||||||
|
Notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
return HasPendingNotifications();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* 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:
|
||||||
|
enum {
|
||||||
|
archive_code = 'strk',
|
||||||
|
};
|
||||||
|
|
||||||
|
StrokeTransformer(
|
||||||
|
VertexSource& source);
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
StrokeTransformer(
|
||||||
|
VertexSource& source,
|
||||||
|
BMessage* archive);
|
||||||
|
#endif
|
||||||
|
virtual ~StrokeTransformer();
|
||||||
|
|
||||||
|
// Transformer interface
|
||||||
|
virtual Transformer* Clone(VertexSource& source) const;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// IconObject interface
|
||||||
|
virtual status_t Archive(BMessage* into,
|
||||||
|
bool deep = true) const;
|
||||||
|
|
||||||
|
virtual PropertyObject* MakePropertyObject() const;
|
||||||
|
virtual bool SetToPropertyObject(
|
||||||
|
const PropertyObject* object);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // STROKE_TRANSFORMER_H
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* 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, const char* name)
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
: IconObject(name),
|
||||||
|
#else
|
||||||
|
:
|
||||||
|
#endif
|
||||||
|
fSource(source)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// constructor
|
||||||
|
Transformer::Transformer(VertexSource& source,
|
||||||
|
BMessage* archive)
|
||||||
|
: IconObject(archive),
|
||||||
|
fSource(source)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TRANSFORMER_H
|
||||||
|
#define TRANSFORMER_H
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
# include "IconObject.h"
|
||||||
|
#else
|
||||||
|
# include <SupportDefs.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class VertexSource {
|
||||||
|
public:
|
||||||
|
VertexSource();
|
||||||
|
virtual ~VertexSource();
|
||||||
|
|
||||||
|
virtual void rewind(unsigned path_id) = 0;
|
||||||
|
virtual unsigned vertex(double* x, double* y) = 0;
|
||||||
|
|
||||||
|
virtual bool WantsOpenPaths() const = 0;
|
||||||
|
virtual double ApproximationScale() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
class Transformer : public VertexSource,
|
||||||
|
public IconObject {
|
||||||
|
#else
|
||||||
|
class Transformer : public VertexSource {
|
||||||
|
#endif
|
||||||
|
public:
|
||||||
|
Transformer(VertexSource& source,
|
||||||
|
const char* name);
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
Transformer(VertexSource& source,
|
||||||
|
BMessage* archive);
|
||||||
|
#endif
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TRANSFORMER_H
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "TransformerFactory.h"
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
# include <Message.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "AffineTransformer.h"
|
||||||
|
#include "ContourTransformer.h"
|
||||||
|
#include "PerspectiveTransformer.h"
|
||||||
|
#include "StrokeTransformer.h"
|
||||||
|
|
||||||
|
// TransformerFor
|
||||||
|
Transformer*
|
||||||
|
TransformerFactory::TransformerFor(uint32 type, VertexSource& source)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case 0:
|
||||||
|
return new AffineTransformer(source);
|
||||||
|
case 1:
|
||||||
|
return new PerspectiveTransformer(source);
|
||||||
|
case 2:
|
||||||
|
return new ContourTransformer(source);
|
||||||
|
case 3:
|
||||||
|
return new StrokeTransformer(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
// TransformerFor
|
||||||
|
Transformer*
|
||||||
|
TransformerFactory::TransformerFor(BMessage* message,
|
||||||
|
VertexSource& source)
|
||||||
|
{
|
||||||
|
switch (message->what) {
|
||||||
|
case AffineTransformer::archive_code:
|
||||||
|
return new AffineTransformer(source, message);
|
||||||
|
case PerspectiveTransformer::archive_code:
|
||||||
|
return new PerspectiveTransformer(source, message);
|
||||||
|
case ContourTransformer::archive_code:
|
||||||
|
return new ContourTransformer(source, message);
|
||||||
|
case StrokeTransformer::archive_code:
|
||||||
|
return new StrokeTransformer(source, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextType
|
||||||
|
bool
|
||||||
|
TransformerFactory::NextType(int32* cookie, uint32* type, BString* name)
|
||||||
|
{
|
||||||
|
*type = *cookie;
|
||||||
|
*cookie = *cookie + 1;
|
||||||
|
|
||||||
|
switch (*type) {
|
||||||
|
case 0:
|
||||||
|
*name = "Transformation";
|
||||||
|
return true;
|
||||||
|
case 1:
|
||||||
|
*name = "Perspective";
|
||||||
|
return true;
|
||||||
|
case 2:
|
||||||
|
*name = "Contour";
|
||||||
|
return true;
|
||||||
|
case 3:
|
||||||
|
*name = "Stroke";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TRANSFORMER_FACTORY_H
|
||||||
|
#define TRANSFORMER_FACTORY_H
|
||||||
|
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
class BMessage;
|
||||||
|
class Transformer;
|
||||||
|
class VertexSource;
|
||||||
|
|
||||||
|
class TransformerFactory {
|
||||||
|
public:
|
||||||
|
|
||||||
|
static Transformer* TransformerFor(uint32 type,
|
||||||
|
VertexSource& source);
|
||||||
|
|
||||||
|
#ifdef ICON_O_MATIC
|
||||||
|
static Transformer* TransformerFor(BMessage* archive,
|
||||||
|
VertexSource& source);
|
||||||
|
|
||||||
|
static bool NextType(int32* cookie,
|
||||||
|
uint32* type,
|
||||||
|
BString* name);
|
||||||
|
|
||||||
|
#endif // ICON_O_MATIC
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TRANSFORMER_FACTORY_H
|
||||||
Reference in New Issue
Block a user