263 lines
7.5 KiB
C++
263 lines
7.5 KiB
C++
/**********************************************************************
|
|
|
|
Filename : GCompoundShape.h
|
|
Content :
|
|
Created : 2005-2006
|
|
Authors : Maxim Shemanarev
|
|
|
|
Copyright : (c) 2001-2006 Scaleform Corp. All Rights Reserved.
|
|
|
|
Notes : Compound Shape container
|
|
|
|
Licensees may use this file in accordance with the valid Scaleform
|
|
Commercial License Agreement provided with the software.
|
|
|
|
This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
|
|
THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR ANY PURPOSE.
|
|
|
|
**********************************************************************/
|
|
|
|
#ifndef INC_GCOMPOUNDSHAPE_H
|
|
#define INC_GCOMPOUNDSHAPE_H
|
|
|
|
#include "GArrayPaged.h"
|
|
#include "GMath2D.h"
|
|
|
|
|
|
// ***** Declared Classes
|
|
class GCompoundShape;
|
|
|
|
// See implementation in the tessellator code
|
|
enum GStatRenderGen
|
|
{
|
|
GStatRG_Default = GStatGroup_RenderGen,
|
|
|
|
GStatRG_Mem,
|
|
GStatRG_Vertices_Mem,
|
|
GStatRG_MeshFill_Mem,
|
|
GStatRG_MeshStroke_Mem,
|
|
GStatRG_Tessellator_Mem,
|
|
GStatRG_Rasterizer_Mem,
|
|
GStatRG_Stroker_Mem,
|
|
GStatRG_EdgeAA_Mem,
|
|
GStatRG_StrokerAA_Mem,
|
|
GStatRG_Other_Mem
|
|
};
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
const GCoordType G_CollinearCurveEpsilon = (GCoordType)1e-4;
|
|
|
|
//-----------------------------------------------------------------------
|
|
class GCompoundShape
|
|
{
|
|
public:
|
|
enum { SID = GStatRG_Other_Mem };
|
|
|
|
class SPath
|
|
{
|
|
friend class GCompoundShape;
|
|
public:
|
|
typedef GPointType ValueType;
|
|
|
|
SPath() {}
|
|
|
|
int GetLeftStyle() const { return LStyle; }
|
|
int GetRightStyle() const { return RStyle; }
|
|
int GetLineStyle() const { return LineStyle; }
|
|
|
|
unsigned GetNumVertices() const
|
|
{
|
|
return NumVertices;
|
|
}
|
|
|
|
const GPointType& GetVertex(unsigned i) const
|
|
{
|
|
return Shape->GetVertex(StartVertex + i);
|
|
}
|
|
|
|
private:
|
|
SPath(const GCompoundShape* s, unsigned start,
|
|
int lStyle, int rStyle, int lineStyle) :
|
|
Shape(s),
|
|
NumVertices(0),
|
|
StartVertex(start),
|
|
LStyle(lStyle),
|
|
RStyle(rStyle),
|
|
LineStyle(lineStyle)
|
|
{}
|
|
|
|
const GCompoundShape* Shape;
|
|
unsigned NumVertices;
|
|
unsigned StartVertex;
|
|
int LStyle;
|
|
int RStyle;
|
|
int LineStyle;
|
|
};
|
|
|
|
GCompoundShape() :
|
|
CurveTolerance(1),
|
|
ToleranceSquare((GCoordType)0.0625),
|
|
Vertices(),
|
|
Paths(),
|
|
CurrPath(0),
|
|
MinStyle( 0x7FFFFFFF),
|
|
MaxStyle(-0x7FFFFFFF),
|
|
MinX(1),
|
|
MinY(1),
|
|
MaxX(0),
|
|
MaxY(0),
|
|
NonZeroFill(false)
|
|
{}
|
|
|
|
UPInt GetNumBytes() const;
|
|
|
|
void Clear();
|
|
void ClearAndRelease();
|
|
|
|
void SetCurveTolerance(GCoordType t);
|
|
GCoordType GetCurveTolerance() const { return CurveTolerance; }
|
|
|
|
void BeginPath(int lStyle, int rStyle, int lineStyle);
|
|
|
|
void BeginPath(int lStyle, int rStyle, int lineStyle,
|
|
GCoordType x, GCoordType y);
|
|
|
|
void AddVertex(GCoordType x, GCoordType y);
|
|
|
|
void AddCurve(GCoordType cx, GCoordType cy,
|
|
GCoordType ax, GCoordType ay);
|
|
|
|
void ClosePath();
|
|
|
|
void SetNonZeroFill(bool flag) { NonZeroFill = flag; }
|
|
bool IsNonZeroFill() const { return NonZeroFill; }
|
|
|
|
unsigned GetNumPaths() const { return (unsigned)Paths.GetSize(); }
|
|
const SPath& GetPath(unsigned n) const { return Paths[n]; }
|
|
SPath& GetPath(unsigned n) { return Paths[n]; }
|
|
|
|
unsigned GetNumVertices() const { return (unsigned)Vertices.GetSize(); }
|
|
const GPointType& GetVertex(unsigned n) const { return Vertices[n]; }
|
|
GPointType& GetVertex(unsigned n) { return Vertices[n]; }
|
|
|
|
int GetMinStyle() const { return MinStyle; }
|
|
int GetMaxStyle() const { return MaxStyle; }
|
|
|
|
void PerceiveBounds(GCoordType* x1, GCoordType* y1,
|
|
GCoordType* x2, GCoordType* y2) const;
|
|
|
|
static void ExpandPathBounds(const SPath& path,
|
|
GCoordType* x1, GCoordType* y1,
|
|
GCoordType* x2, GCoordType* y2);
|
|
|
|
bool PointInShape(GCoordType x, GCoordType y, bool nonZero=true) const;
|
|
|
|
void PerceiveBounds();
|
|
bool HasValidBounds() const { return MinX < MaxX && MinY < MaxY; }
|
|
|
|
GCoordType GetMinX() const { return MinX; }
|
|
GCoordType GetMinY() const { return MinY; }
|
|
GCoordType GetMaxX() const { return MaxX; }
|
|
GCoordType GetMaxY() const { return MaxY; }
|
|
|
|
static bool PathsEqual(const SPath& a, const SPath& b);
|
|
|
|
void ScaleAndTranslate(GCoordType kx, GCoordType ky,
|
|
GCoordType dx, GCoordType dy);
|
|
|
|
void RemoveShortSegments(GCoordType maxLen);
|
|
|
|
#ifdef GCONTAINERS_STANDALONE
|
|
template<class VertexSource>
|
|
void AppendPath(VertexSource& vs, unsigned path_id=0)
|
|
{
|
|
double x; // Must remain double
|
|
double y;
|
|
|
|
unsigned cmd;
|
|
vs.rewind(path_id);
|
|
while((cmd = vs.vertex(&x, &y)) != 0)
|
|
{
|
|
if(cmd < 3)
|
|
{
|
|
AddVertex(GCoordType(x), GCoordType(y));
|
|
}
|
|
else
|
|
if(cmd == 3)
|
|
{
|
|
double x2, y2;
|
|
vs.vertex(&x2, &y2);
|
|
AddCurve(GCoordType(x), GCoordType(y),
|
|
GCoordType(x2), GCoordType(y2));
|
|
}
|
|
}
|
|
}
|
|
|
|
template<class VertexSource>
|
|
void AppendMultiPath(VertexSource& vs,
|
|
int lStyle, int rStyle, int lineStyle,
|
|
unsigned path_id=0)
|
|
{
|
|
double x; // Must remain double
|
|
double y;
|
|
|
|
unsigned cmd;
|
|
vs.rewind(path_id);
|
|
while((cmd = vs.vertex(&x, &y)) != 0)
|
|
{
|
|
if(cmd < 3)
|
|
{
|
|
if(cmd == 1)
|
|
{
|
|
BeginPath(lStyle, rStyle, lineStyle);
|
|
}
|
|
AddVertex(GCoordType(x), GCoordType(y));
|
|
}
|
|
else
|
|
if(cmd == 3)
|
|
{
|
|
double x2, y2;
|
|
vs.vertex(&x2, &y2);
|
|
AddCurve(GCoordType(x), GCoordType(y),
|
|
GCoordType(x2), GCoordType(y2));
|
|
}
|
|
else
|
|
if((cmd & 0x4F) == 0x4F) // Magic number "close polygon"
|
|
{
|
|
ClosePath();
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
private:
|
|
void flattenQuadraticCurve(GCoordType x1, GCoordType y1,
|
|
GCoordType x2, GCoordType y2,
|
|
GCoordType x3, GCoordType y3);
|
|
|
|
GCoordType CurveTolerance;
|
|
GCoordType ToleranceSquare;
|
|
GArrayPagedLH_POD<GPointType, 8, 64, SID> Vertices;
|
|
GArrayPagedLH_POD<SPath, 6, 16, SID> Paths;
|
|
SPath* CurrPath;
|
|
int MinStyle;
|
|
int MaxStyle;
|
|
GCoordType MinX;
|
|
GCoordType MinY;
|
|
GCoordType MaxX;
|
|
GCoordType MaxY;
|
|
bool NonZeroFill;
|
|
};
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
GINLINE void GCompoundShape::AddVertex(GCoordType x, GCoordType y)
|
|
{
|
|
Vertices.PushBack(GPointType(x, y));
|
|
CurrPath->NumVertices++;
|
|
}
|
|
|
|
|
|
#endif
|