875 lines
29 KiB
C++
875 lines
29 KiB
C++
/**********************************************************************
|
|
|
|
Filename : GFxPathDataStorage.h
|
|
Content :
|
|
Created : 2007
|
|
Authors : Maxim Shemanarev
|
|
|
|
Copyright : (c) 2001-2007 Scaleform Corp. All Rights Reserved.
|
|
|
|
Notes : Compact path data storage
|
|
|
|
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.
|
|
|
|
For information regarding Commercial License Agreements go to:
|
|
online - http://www.scaleform.com/licensing.html or
|
|
email - sales@scaleform.com
|
|
|
|
**********************************************************************/
|
|
|
|
#ifndef INC_GFxPathDataStorage_H
|
|
#define INC_GFxPathDataStorage_H
|
|
|
|
#include "GTypes.h"
|
|
|
|
//------------------------------------------------------------------------
|
|
// Data types. xxxx - payload, S - sign bit; Bit order in bytes: 76543210
|
|
//
|
|
// Byte 0 Byte 1
|
|
// UInt15: |xxxxxxx|0| : 0...127
|
|
// |xxxxxxx|1| |xxxxxxxx| : 128...32767
|
|
//
|
|
// Byte 0 Byte 1
|
|
// SInt15: |xxxxxxx|0| : -64...63
|
|
// |xxxxxxx|1| |Sxxxxxxx| : -16384...16383
|
|
//
|
|
// Byte 0 Byte 1 Byte 2 Byte 3
|
|
// UInt30: |xxxxxx|00| : 0...63
|
|
// |xxxxxx|01| |xxxxxxxx| : 128...32767
|
|
// |xxxxxx|10| |xxxxxxxx| |xxxxxxxx| : 32768...2^22-1
|
|
// |xxxxxx|11| |xxxxxxxx| |xxxxxxxx| |xxxxxxxx| : 2^22...2^30-1
|
|
//
|
|
// Byte 0 Byte 1 Byte 2 Byte 3
|
|
// SInt30: |xxxxxx|00| : -32...31
|
|
// |xxxxxx|01| |xxxxxxxx| : -8192...8191
|
|
// |xxxxxx|10| |xxxxxxxx| |xxxxxxxx| : -2^21...2^21-1
|
|
// |xxxxxx|11| |xxxxxxxx| |xxxxxxxx| |Sxxxxxxx| : -2^29...2^29-1
|
|
//
|
|
// Edges:
|
|
// Data for the edges consists of 4-bit edge type and the payload in the
|
|
// 4 bits of this byte plus 1...9 next bytes.
|
|
//
|
|
// Byte 0
|
|
// |xxxx|eeee| |xxxxxxxx| ... where "eeee" - 4-bit edge type
|
|
//
|
|
// Edge types:
|
|
// Edge_H12 = 0, // 2 bytes - 12-bit horizontal line (4 + 12 = 16 = 2 bytes)
|
|
// Edge_H20 = 1, // 3 bytes - 20-bit horizontal line (4 + 20 = 24 = 3 bytes)
|
|
// Edge_V12 = 2, // 2 bytes - 12-bit vertical line (4 + 12 = 16 = 2 bytes)
|
|
// Edge_V20 = 3, // 3 bytes - 20-bit vertical line (4 + 20 = 24 = 3 bytes)
|
|
// Edge_L6 = 4, // 2 bytes - 6-bit general line (4 + 6 + 6 = 16 = 2 bytes)
|
|
// Edge_L10 = 5, // 3 bytes - 10-bit general line (4 + 10 + 10 = 24 = 3 bytes)
|
|
// Edge_L14 = 6, // 4 bytes - 14-bit general line (4 + 14 + 14 = 32 = 4 bytes)
|
|
// Edge_L18 = 7, // 5 bytes - 18-bit general line (4 + 18 + 18 = 40 = 5 bytes)
|
|
// Edge_C5 = 8, // 3 bytes - 5-bit quadratic curve (4 + 5 + 5 + 5 + 5 = 3 bytes)
|
|
// Edge_C7 = 9, // 4 bytes - 7-bit quadratic curve (4 + 7 + 7 + 7 + 7 = 4 bytes)
|
|
// Edge_C9 = 10, // 5 bytes - 9-bit quadratic curve (4 + 9 + 9 + 9 + 9 = 5 bytes)
|
|
// Edge_C11 = 11, // 6 bytes - 11-bit quadratic curve (4 + 11 + 11 + 11 + 11 = 6 bytes)
|
|
// Edge_C13 = 12, // 7 bytes - 13-bit quadratic curve (4 + 13 + 13 + 13 + 13 = 7 bytes)
|
|
// Edge_C15 = 13, // 8 bytes - 15-bit quadratic curve (4 + 15 + 15 + 15 + 15 = 8 bytes)
|
|
// Edge_C17 = 14, // 9 bytes - 17-bit quadratic curve (4 + 17 + 17 + 17 + 17 = 9 bytes)
|
|
// Edge_C19 = 15 // 10 bytes - 19-bit quadratic curve (4 + 19 + 19 + 19 + 19 = 10 bytes)
|
|
//
|
|
// Edge data:
|
|
// X,Y may mean absolute values as well as relative ones
|
|
// Horizontal and Vertical lines: X or Y respectively.
|
|
// General Lines: X, Y
|
|
// Quadratic Curves: CX, CY, AX, AY
|
|
//
|
|
// An example of Edge_C7:
|
|
// Byte 0 Byte 1 Byte 2 Byte 3
|
|
// |aaaa|1001| |bbbbb|Aaa| |cccccc|Bb| |Ddddddd|C|
|
|
//
|
|
// Where: Aaaaaaa - CX, Bbbbbbb - CY, Ccccccc - AX, Ddddddd - AY
|
|
// (capital letter means sign bit.)
|
|
//
|
|
//------------------------------------------------------------------------
|
|
struct GFxPathDataTypes
|
|
{
|
|
enum RawEdgeType
|
|
{
|
|
Edge_H12 = 0, // 2 bytes
|
|
Edge_H20 = 1, // 3 bytes
|
|
Edge_V12 = 2, // 2 bytes
|
|
Edge_V20 = 3, // 3 bytes
|
|
Edge_L6 = 4, // 2 bytes
|
|
Edge_L10 = 5, // 3 bytes
|
|
Edge_L14 = 6, // 4 bytes
|
|
Edge_L18 = 7, // 5 bytes
|
|
Edge_C5 = 8, // 3 bytes
|
|
Edge_C7 = 9, // 4 bytes
|
|
Edge_C9 = 10, // 5 bytes
|
|
Edge_C11 = 11, // 6 bytes
|
|
Edge_C13 = 12, // 7 bytes
|
|
Edge_C15 = 13, // 8 bytes
|
|
Edge_C17 = 14, // 9 bytes
|
|
Edge_C19 = 15 // 10 bytes
|
|
};
|
|
|
|
enum RangeType
|
|
{
|
|
MaxUInt6 = (1 << 6) - 1,
|
|
MaxUInt7 = (1 << 7) - 1,
|
|
MaxUInt14 = (1 << 14) - 1,
|
|
MaxUInt22 = (1 << 22) - 1,
|
|
MaxUInt30 = (1 << 30) - 1,
|
|
|
|
MinSInt5 = -(1 << 4),
|
|
MaxSInt5 = (1 << 4) - 1,
|
|
MinSInt6 = -(1 << 5),
|
|
MaxSInt6 = (1 << 5) - 1,
|
|
MinSInt7 = -(1 << 6),
|
|
MaxSInt7 = (1 << 6) - 1,
|
|
MinSInt8 = -(1 << 7),
|
|
MaxSInt8 = (1 << 7) - 1,
|
|
MinSInt9 = -(1 << 8),
|
|
MaxSInt9 = (1 << 8) - 1,
|
|
MinSInt10 = -(1 << 9),
|
|
MaxSInt10 = (1 << 9) - 1,
|
|
MinSInt11 = -(1 << 10),
|
|
MaxSInt11 = (1 << 10) - 1,
|
|
MinSInt12 = -(1 << 11),
|
|
MaxSInt12 = (1 << 11) - 1,
|
|
MinSInt13 = -(1 << 12),
|
|
MaxSInt13 = (1 << 12) - 1,
|
|
MinSInt14 = -(1 << 13),
|
|
MaxSInt14 = (1 << 13) - 1,
|
|
MinSInt15 = -(1 << 14),
|
|
MaxSInt15 = (1 << 14) - 1,
|
|
MinSInt17 = -(1 << 16),
|
|
MaxSInt17 = (1 << 16) - 1,
|
|
MinSInt18 = -(1 << 17),
|
|
MaxSInt18 = (1 << 17) - 1,
|
|
MinSInt19 = -(1 << 18),
|
|
MaxSInt19 = (1 << 18) - 1,
|
|
MinSInt20 = -(1 << 19),
|
|
MaxSInt20 = (1 << 19) - 1,
|
|
MinSInt22 = -(1 << 21),
|
|
MaxSInt22 = (1 << 21) - 1,
|
|
};
|
|
|
|
enum EdgeType
|
|
{
|
|
Edge_HLine,
|
|
Edge_VLine,
|
|
Edge_Line,
|
|
Edge_Quad
|
|
};
|
|
};
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType> class GFxPathDataEncoder : public GFxPathDataTypes
|
|
{
|
|
public:
|
|
GFxPathDataEncoder(ContainerType& data);
|
|
|
|
void Clear();
|
|
|
|
void WriteChar(char v) { Data->PushBack(UInt8(v)); }
|
|
|
|
void WriteUInt16fixlen(UInt v);
|
|
void WriteUInt32fixlen(UInt v);
|
|
|
|
void WriteSInt16fixlen(SInt v);
|
|
void WriteSInt32fixlen(SInt v);
|
|
|
|
void UpdateUInt16fixlen(UInt pos, UInt v);
|
|
void UpdateUInt32fixlen(UInt pos, UInt v);
|
|
|
|
void UpdateSInt16fixlen(UInt pos, SInt v);
|
|
void UpdateSInt32fixlen(UInt pos, SInt v);
|
|
|
|
UInt WriteUInt15(UInt v);
|
|
UInt WriteUInt30(UInt v);
|
|
|
|
UInt WriteSInt15(SInt v);
|
|
UInt WriteSInt30(SInt v);
|
|
|
|
UInt WriteHLine(SInt x);
|
|
UInt WriteVLine(SInt y);
|
|
UInt WriteLine (SInt x, SInt y);
|
|
UInt WriteQuad (SInt cx, SInt cy, SInt ax, SInt ay);
|
|
|
|
void CutAt(UInt pos) { Data->CutAt(pos); }
|
|
|
|
UPInt GetSize() const { return Data->GetSize(); }
|
|
void Serialize(void* ptr, UInt start, UInt size) const;
|
|
void Deserialize(const void* ptr, UInt size);
|
|
|
|
private:
|
|
ContainerType* Data;
|
|
};
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType> class GFxPathDataDecoder : public GFxPathDataTypes
|
|
{
|
|
public:
|
|
GFxPathDataDecoder(const ContainerType& data);
|
|
|
|
UInt GetSize() const { return (UInt)Data->GetSize(); }
|
|
const ContainerType& GetData() const { return *Data; }
|
|
|
|
char ReadChar(UInt pos) const { return (char)Data->ValueAt(pos); }
|
|
|
|
UInt ReadUInt16fixlen(UInt pos) const;
|
|
UInt ReadUInt32fixlen(UInt pos) const;
|
|
|
|
SInt ReadSInt16fixlen(UInt pos) const;
|
|
SInt ReadSInt32fixlen(UInt pos) const;
|
|
|
|
UInt ReadSInt15(UInt pos, SInt* v) const;
|
|
UInt ReadSInt30(UInt pos, SInt* v) const;
|
|
|
|
UInt ReadUInt15(UInt pos, UInt* v) const;
|
|
UInt ReadUInt30(UInt pos, UInt* v) const;
|
|
|
|
UInt ReadRawEdge(UInt pos, UInt8* data) const; // data must be at least UInt8[10];
|
|
UInt ReadEdge (UInt pos, SInt* data) const; // data must be at least SInt[5];
|
|
|
|
private:
|
|
const ContainerType* Data;
|
|
static const UInt8 Sizes[16];
|
|
};
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
GFxPathDataEncoder<ContainerType>::GFxPathDataEncoder(ContainerType& data) :
|
|
Data(&data)
|
|
{
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
void GFxPathDataEncoder<ContainerType>::Clear()
|
|
{
|
|
Data->Clear();
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
inline void GFxPathDataEncoder<ContainerType>::WriteUInt16fixlen(UInt v)
|
|
{
|
|
Data->PushBack(UInt8(v));
|
|
Data->PushBack(UInt8(v >> 8));
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
inline void GFxPathDataEncoder<ContainerType>::WriteUInt32fixlen(UInt v)
|
|
{
|
|
Data->PushBack(UInt8(v));
|
|
Data->PushBack(UInt8(v >> 8));
|
|
Data->PushBack(UInt8(v >> 16));
|
|
Data->PushBack(UInt8(v >> 24));
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
inline void GFxPathDataEncoder<ContainerType>::WriteSInt16fixlen(SInt v)
|
|
{
|
|
Data->PushBack(UInt8(v));
|
|
Data->PushBack(UInt8(v >> 8));
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
inline void GFxPathDataEncoder<ContainerType>::WriteSInt32fixlen(SInt v)
|
|
{
|
|
Data->PushBack(UInt8(v));
|
|
Data->PushBack(UInt8(v >> 8));
|
|
Data->PushBack(UInt8(v >> 16));
|
|
Data->PushBack(UInt8(v >> 24));
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
inline void GFxPathDataEncoder<ContainerType>::UpdateUInt16fixlen(UInt pos, UInt v)
|
|
{
|
|
Data->At(pos ) = UInt8(v);
|
|
Data->At(pos+1) = UInt8(v >> 8);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
inline void GFxPathDataEncoder<ContainerType>::UpdateUInt32fixlen(UInt pos, UInt v)
|
|
{
|
|
Data->At(pos ) = UInt8(v);
|
|
Data->At(pos+1) = UInt8(v >> 8);
|
|
Data->At(pos+2) = UInt8(v >> 16);
|
|
Data->At(pos+3) = UInt8(v >> 24);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
inline void GFxPathDataEncoder<ContainerType>::UpdateSInt16fixlen(UInt pos, SInt v)
|
|
{
|
|
Data->At(pos ) = UInt8(v);
|
|
Data->At(pos+1) = UInt8(v >> 8);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
inline void GFxPathDataEncoder<ContainerType>::UpdateSInt32fixlen(UInt pos, SInt v)
|
|
{
|
|
Data->At(pos ) = UInt8(v);
|
|
Data->At(pos+1) = UInt8(v >> 8);
|
|
Data->At(pos+2) = UInt8(v >> 16);
|
|
Data->At(pos+3) = UInt8(v >> 24);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
inline UInt GFxPathDataEncoder<ContainerType>::WriteUInt15(UInt v)
|
|
{
|
|
if (v <= MaxUInt7)
|
|
{
|
|
Data->PushBack(UInt8(v << 1));
|
|
return 1;
|
|
}
|
|
Data->PushBack(UInt8((v << 1) | 1));
|
|
Data->PushBack(UInt8 (v >> 7));
|
|
return 2;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
inline UInt GFxPathDataEncoder<ContainerType>::WriteSInt15(SInt v)
|
|
{
|
|
if (v >= MinSInt7 && v <= MaxSInt7)
|
|
{
|
|
Data->PushBack(UInt8(v << 1));
|
|
return 1;
|
|
}
|
|
Data->PushBack(UInt8((v << 1) | 1));
|
|
Data->PushBack(UInt8 (v >> 7));
|
|
return 2;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
UInt GFxPathDataEncoder<ContainerType>::WriteUInt30(UInt v)
|
|
{
|
|
if (v <= MaxUInt6)
|
|
{
|
|
Data->PushBack(UInt8(v << 2));
|
|
return 1;
|
|
}
|
|
if (v <= MaxUInt14)
|
|
{
|
|
Data->PushBack(UInt8((v << 2) | 1));
|
|
Data->PushBack(UInt8 (v >> 6));
|
|
return 2;
|
|
}
|
|
if (v <= MaxUInt22)
|
|
{
|
|
Data->PushBack(UInt8((v << 2) | 2));
|
|
Data->PushBack(UInt8 (v >> 6));
|
|
Data->PushBack(UInt8 (v >> 14));
|
|
return 3;
|
|
}
|
|
Data->PushBack(UInt8((v << 2) | 3));
|
|
Data->PushBack(UInt8 (v >> 6));
|
|
Data->PushBack(UInt8 (v >> 14));
|
|
Data->PushBack(UInt8 (v >> 22));
|
|
return 4;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
UInt GFxPathDataEncoder<ContainerType>::WriteSInt30(SInt v)
|
|
{
|
|
if (v >= MinSInt6 && v <= MaxSInt6)
|
|
{
|
|
Data->PushBack(UInt8(v << 2));
|
|
return 1;
|
|
}
|
|
if (v >= MinSInt14 && v <= MaxSInt14)
|
|
{
|
|
Data->PushBack(UInt8((v << 2) | 1));
|
|
Data->PushBack(UInt8 (v >> 6));
|
|
return 2;
|
|
}
|
|
if (v >= MinSInt22 && v <= MaxSInt22)
|
|
{
|
|
Data->PushBack(UInt8((v << 2) | 2));
|
|
Data->PushBack(UInt8 (v >> 6));
|
|
Data->PushBack(UInt8 (v >> 14));
|
|
return 3;
|
|
}
|
|
Data->PushBack(UInt8((v << 2) | 3));
|
|
Data->PushBack(UInt8 (v >> 6));
|
|
Data->PushBack(UInt8 (v >> 14));
|
|
Data->PushBack(UInt8 (v >> 22));
|
|
return 4;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
UInt GFxPathDataEncoder<ContainerType>::WriteHLine(SInt x)
|
|
{
|
|
if (x >= MinSInt12 && x <= MaxSInt12)
|
|
{
|
|
Data->PushBack(UInt8((x << 4) | Edge_H12));
|
|
Data->PushBack(UInt8 (x >> 4));
|
|
return 2;
|
|
}
|
|
Data->PushBack(UInt8((x << 4) | Edge_H20));
|
|
Data->PushBack(UInt8 (x >> 4));
|
|
Data->PushBack(UInt8 (x >> 12));
|
|
return 3;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
UInt GFxPathDataEncoder<ContainerType>::WriteVLine(SInt y)
|
|
{
|
|
if (y >= MinSInt12 && y <= MaxSInt12)
|
|
{
|
|
Data->PushBack(UInt8((y << 4) | Edge_V12));
|
|
Data->PushBack(UInt8 (y >> 4));
|
|
return 2;
|
|
}
|
|
Data->PushBack(UInt8((y << 4) | Edge_V20));
|
|
Data->PushBack(UInt8 (y >> 4));
|
|
Data->PushBack(UInt8 (y >> 12));
|
|
return 3;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
UInt GFxPathDataEncoder<ContainerType>::WriteLine(SInt x, SInt y)
|
|
{
|
|
enum { m2=3, m6=0x3F };
|
|
|
|
if (x >= MinSInt6 && x <= MaxSInt6 && y >= MinSInt6 && y <= MaxSInt6)
|
|
{
|
|
Data->PushBack(UInt8( (x << 4) | Edge_L6));
|
|
Data->PushBack(UInt8(((x >> 4) & m2) | (y << 2)));
|
|
return 2;
|
|
}
|
|
if (x >= MinSInt10 && x <= MaxSInt10 && y >= MinSInt10 && y <= MaxSInt10)
|
|
{
|
|
Data->PushBack(UInt8 ((x << 4) | Edge_L10));
|
|
Data->PushBack(UInt8(((x >> 4) & m6) | (y << 6)));
|
|
Data->PushBack(UInt8 (y >> 2));
|
|
return 3;
|
|
}
|
|
if (x >= MinSInt14 && x <= MaxSInt14 && y >= MinSInt14 && y <= MaxSInt14)
|
|
{
|
|
Data->PushBack(UInt8 ((x << 4) | Edge_L14));
|
|
Data->PushBack(UInt8 (x >> 4));
|
|
Data->PushBack(UInt8(((x >> 12) & m2) | (y << 2)));
|
|
Data->PushBack(UInt8 (y >> 6));
|
|
return 4;
|
|
}
|
|
Data->PushBack(UInt8 ((x << 4) | Edge_L18));
|
|
Data->PushBack(UInt8 (x >> 4));
|
|
Data->PushBack(UInt8(((x >> 12) & m6) | (y << 6)));
|
|
Data->PushBack(UInt8 (y >> 2));
|
|
Data->PushBack(UInt8 (y >> 10));
|
|
return 5;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
UInt GFxPathDataEncoder<ContainerType>::WriteQuad(SInt cx, SInt cy, SInt ax, SInt ay)
|
|
{
|
|
SInt minV = cx;
|
|
SInt maxV = cx;
|
|
if (cy < minV) minV = cy;
|
|
if (cy > maxV) maxV = cy;
|
|
if (ax < minV) minV = ax;
|
|
if (ax > maxV) maxV = ax;
|
|
if (ay < minV) minV = ay;
|
|
if (ay > maxV) maxV = ay;
|
|
|
|
enum { m1=1, m2=3, m3=7, m4=0xF, m5=0x1F, m6=0x3F, m7=0x7F };
|
|
|
|
if (minV >= MinSInt5 && maxV <= MaxSInt5)
|
|
{
|
|
Data->PushBack(UInt8( (cx << 4) | Edge_C5 ));
|
|
Data->PushBack(UInt8( ((cx >> 4) & m1) | ((cy << 1) & m6) | (ax << 6) ));
|
|
Data->PushBack(UInt8( ((ax >> 2) & m3) | (ay << 3) ));
|
|
return 3;
|
|
}
|
|
if (minV >= MinSInt7 && maxV <= MaxSInt7)
|
|
{
|
|
Data->PushBack(UInt8( (cx << 4) | Edge_C7 ));
|
|
Data->PushBack(UInt8( ((cx >> 4) & m3) | (cy << 3) ));
|
|
Data->PushBack(UInt8( ((cy >> 5) & m2) | (ax << 2) ));
|
|
Data->PushBack(UInt8( ((ax >> 6) & m1) | (ay << 1) ));
|
|
return 4;
|
|
}
|
|
if (minV >= MinSInt9 && maxV <= MaxSInt9)
|
|
{
|
|
Data->PushBack(UInt8( (cx << 4) | Edge_C9 ));
|
|
Data->PushBack(UInt8( ((cx >> 4) & m5) | (cy << 5) ));
|
|
Data->PushBack(UInt8( ((cy >> 3) & m6) | (ax << 6) ));
|
|
Data->PushBack(UInt8( ((ax >> 2) & m7) | (ay << 7) ));
|
|
Data->PushBack(UInt8( (ay >> 1) ));
|
|
return 5;
|
|
}
|
|
if (minV >= MinSInt11 && maxV <= MaxSInt11)
|
|
{
|
|
Data->PushBack(UInt8( (cx << 4) | Edge_C11 ));
|
|
Data->PushBack(UInt8( ((cx >> 4) & m7) | (cy << 7) ));
|
|
Data->PushBack(UInt8( (cy >> 1) ));
|
|
Data->PushBack(UInt8( ((cy >> 9) & m2) | (ax << 2) ));
|
|
Data->PushBack(UInt8( ((ax >> 6) & m5) | (ay << 5) ));
|
|
Data->PushBack(UInt8( (ay >> 3) ));
|
|
return 6;
|
|
}
|
|
if (minV >= MinSInt13 && maxV <= MaxSInt13)
|
|
{
|
|
Data->PushBack(UInt8( (cx << 4) | Edge_C13 ));
|
|
Data->PushBack(UInt8( (cx >> 4) ));
|
|
Data->PushBack(UInt8( ((cx >> 12) & m1) | (cy << 1) ));
|
|
Data->PushBack(UInt8( ((cy >> 7) & m6) | (ax << 6) ));
|
|
Data->PushBack(UInt8( (ax >> 2) ));
|
|
Data->PushBack(UInt8( ((ax >> 10) & m3) | (ay << 3) ));
|
|
Data->PushBack(UInt8( (ay >> 5) ));
|
|
return 7;
|
|
}
|
|
if (minV >= MinSInt15 && maxV <= MaxSInt15)
|
|
{
|
|
Data->PushBack(UInt8( (cx << 4) | Edge_C15 ));
|
|
Data->PushBack(UInt8( (cx >> 4) ));
|
|
Data->PushBack(UInt8( ((cx >> 12) & m3) | (cy << 3) ));
|
|
Data->PushBack(UInt8( (cy >> 5) ));
|
|
Data->PushBack(UInt8( ((cy >> 13) & m2) | (ax << 2) ));
|
|
Data->PushBack(UInt8( (ax >> 6) ));
|
|
Data->PushBack(UInt8( ((ax >> 14) & m1) | (ay << 1) ));
|
|
Data->PushBack(UInt8( (ay >> 7) ));
|
|
return 8;
|
|
}
|
|
if (minV >= MinSInt17 && maxV <= MaxSInt17)
|
|
{
|
|
Data->PushBack(UInt8( (cx << 4) | Edge_C17 ));
|
|
Data->PushBack(UInt8( (cx >> 4) ));
|
|
Data->PushBack(UInt8( ((cx >> 12) & m5) | (cy << 5) ));
|
|
Data->PushBack(UInt8( (cy >> 3) ));
|
|
Data->PushBack(UInt8( ((cy >> 11) & m6) | (ax << 6) ));
|
|
Data->PushBack(UInt8( (ax >> 2) ));
|
|
Data->PushBack(UInt8( ((ax >> 10) & m7) | (ay << 7) ));
|
|
Data->PushBack(UInt8( (ay >> 1) ));
|
|
Data->PushBack(UInt8( (ay >> 9) ));
|
|
return 9;
|
|
}
|
|
Data->PushBack(UInt8( (cx << 4) | Edge_C19 ));
|
|
Data->PushBack(UInt8( (cx >> 4) ));
|
|
Data->PushBack(UInt8( ((cx >> 12) & m7) | (cy << 7) ));
|
|
Data->PushBack(UInt8( (cy >> 1) ));
|
|
Data->PushBack(UInt8( (cy >> 9) ));
|
|
Data->PushBack(UInt8( ((cy >> 17) & m2) | (ax << 2) ));
|
|
Data->PushBack(UInt8( (ax >> 6) ));
|
|
Data->PushBack(UInt8( ((ax >> 14) & m5) | (ay << 5) ));
|
|
Data->PushBack(UInt8( (ay >> 3) ));
|
|
Data->PushBack(UInt8( (ay >> 11) ));
|
|
return 10;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
void GFxPathDataEncoder<ContainerType>::Serialize(void* ptr, UInt start, UInt size) const
|
|
{
|
|
UInt8* dst = (UInt8*)ptr;
|
|
for(UInt i = 0; i < size; ++i)
|
|
*dst++ = Data->ValueAt(start + i);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
void GFxPathDataEncoder<ContainerType>::Deserialize(const void* ptr, UInt size)
|
|
{
|
|
const UInt8* src = (const UInt8*)ptr;
|
|
for(UInt i = 0; i < size; ++i)
|
|
Data->PushBack(*src++);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
const UInt8 GFxPathDataDecoder<ContainerType>::Sizes[16] =
|
|
{
|
|
1,2,1,2,1,2,3,4,2,3,4,5,6,7,8,9
|
|
};
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
GFxPathDataDecoder<ContainerType>::GFxPathDataDecoder(const ContainerType& data) :
|
|
Data(&data)
|
|
{
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
inline UInt GFxPathDataDecoder<ContainerType>::ReadUInt16fixlen(UInt pos) const
|
|
{
|
|
return Data->ValueAt(pos) | (Data->ValueAt(pos + 1) << 8);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
inline UInt GFxPathDataDecoder<ContainerType>::ReadUInt32fixlen(UInt pos) const
|
|
{
|
|
return Data->ValueAt(pos)|
|
|
(Data->ValueAt(pos + 1) << 8 )|
|
|
(Data->ValueAt(pos + 2) << 16)|
|
|
(Data->ValueAt(pos + 3) << 24);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
inline SInt GFxPathDataDecoder<ContainerType>::ReadSInt16fixlen(UInt pos) const
|
|
{
|
|
return SInt16(ReadUInt16fixlen(pos));
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
inline SInt GFxPathDataDecoder<ContainerType>::ReadSInt32fixlen(UInt pos) const
|
|
{
|
|
return SInt(ReadUInt32fixlen(pos));
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
inline UInt GFxPathDataDecoder<ContainerType>::ReadUInt15(UInt pos, UInt* v) const
|
|
{
|
|
UInt t = UInt8(Data->ValueAt(pos));
|
|
if ((t & 1) == 0)
|
|
{
|
|
*v = t >> 1;
|
|
return 1;
|
|
}
|
|
t = UInt(t >> 1);
|
|
*v = UInt(t | (UInt8(Data->ValueAt(pos+1)) << 7));
|
|
return 2;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
inline UInt GFxPathDataDecoder<ContainerType>::ReadSInt15(UInt pos, SInt* v) const
|
|
{
|
|
SInt t = SInt8(Data->ValueAt(pos));
|
|
if ((t & 1) == 0)
|
|
{
|
|
*v = t >> 1;
|
|
return 1;
|
|
}
|
|
t = SInt((t >> 1) & MaxUInt7);
|
|
*v = SInt (t | (SInt8(Data->ValueAt(pos+1)) << 7));
|
|
return 2;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
inline UInt GFxPathDataDecoder<ContainerType>::ReadRawEdge(UInt pos, UInt8* data) const
|
|
{
|
|
*data = Data->ValueAt(pos++);
|
|
UInt nb = Sizes[*data & 0xF];
|
|
UInt i;
|
|
++data;
|
|
for (i = 0; i < nb; i++)
|
|
*data++ = Data->ValueAt(pos++);
|
|
|
|
return nb + 1;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
UInt GFxPathDataDecoder<ContainerType>::ReadUInt30(UInt pos, UInt* v) const
|
|
{
|
|
UInt t = UInt8(Data->ValueAt(pos));
|
|
switch(t & 3)
|
|
{
|
|
case 0:
|
|
*v = t >> 2;
|
|
return 1;
|
|
|
|
case 1:
|
|
t = t >> 2;
|
|
*v = t | (Data->ValueAt(pos+1) << 6);
|
|
return 2;
|
|
|
|
case 2:
|
|
t = t >> 2;
|
|
t = t | (Data->ValueAt(pos+1) << 6);
|
|
*v = t | (Data->ValueAt(pos+2) << 14);
|
|
return 3;
|
|
}
|
|
t = t >> 2;
|
|
t = t | (Data->ValueAt(pos+1) << 6);
|
|
t = t | (Data->ValueAt(pos+2) << 14);
|
|
*v = t | (Data->ValueAt(pos+3) << 22);
|
|
return 4;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
UInt GFxPathDataDecoder<ContainerType>::ReadSInt30(UInt pos, SInt* v) const
|
|
{
|
|
SInt t = SInt8(Data->ValueAt(pos));
|
|
switch(t & 3)
|
|
{
|
|
case 0:
|
|
*v = t >> 2;
|
|
return 1;
|
|
|
|
case 1:
|
|
t = SInt((t >> 2) & MaxUInt6);
|
|
*v = SInt (t | (SInt8(Data->ValueAt(pos+1)) << 6));
|
|
return 2;
|
|
|
|
case 2:
|
|
t = SInt((t >> 2) & MaxUInt6);
|
|
t = SInt (t | (UInt8(Data->ValueAt(pos+1)) << 6));
|
|
*v = SInt (t | (SInt8(Data->ValueAt(pos+2)) << 14));
|
|
return 3;
|
|
}
|
|
t = SInt((t >> 2) & MaxUInt6);
|
|
t = SInt (t | (UInt8(Data->ValueAt(pos+1)) << 6));
|
|
t = SInt (t | (UInt8(Data->ValueAt(pos+2)) << 14));
|
|
*v = SInt (t | (SInt8(Data->ValueAt(pos+3)) << 22));
|
|
return 4;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class ContainerType>
|
|
UInt GFxPathDataDecoder<ContainerType>::ReadEdge(UInt pos, SInt* data) const
|
|
{
|
|
UInt8 buff[10];
|
|
UInt nb = ReadRawEdge(pos, buff);
|
|
|
|
switch(buff[0] & 0xF)
|
|
{
|
|
case Edge_H12:
|
|
data[0] = Edge_HLine;
|
|
data[1] = SInt(buff[0] >> 4) | (SInt8(buff[1]) << 4);
|
|
break;
|
|
|
|
case Edge_H20:
|
|
data[0] = Edge_HLine;
|
|
data[1] = SInt(buff[0] >> 4) | SInt(buff[1] << 4) | (SInt8(buff[2]) << 12);
|
|
break;
|
|
|
|
case Edge_V12:
|
|
data[0] = Edge_VLine;
|
|
data[1] = SInt(buff[0] >> 4) | (SInt8(buff[1]) << 4);
|
|
break;
|
|
|
|
case Edge_V20:
|
|
data[0] = Edge_VLine;
|
|
data[1] = SInt(buff[0] >> 4) | SInt(buff[1] << 4) | (SInt8(buff[2]) << 12);
|
|
break;
|
|
|
|
case Edge_L6 :
|
|
data[0] = Edge_Line;
|
|
data[1] = SInt (buff[0] >> 4) | (SInt8(buff[1] << 6) >> 2);
|
|
data[2] = SInt8(buff[1]) >> 2;
|
|
break;
|
|
|
|
case Edge_L10:
|
|
data[0] = Edge_Line;
|
|
data[1] = SInt(buff[0] >> 4) | (SInt8(buff[1] << 2) << 2);
|
|
data[2] = SInt(buff[1] >> 6) | (SInt8(buff[2]) << 2);
|
|
break;
|
|
|
|
case Edge_L14:
|
|
data[0] = Edge_Line;
|
|
data[1] = SInt(buff[0] >> 4) | SInt (buff[1] << 4) | (SInt8(buff[2] << 6) << 6);
|
|
data[2] = SInt(buff[2] >> 2) | (SInt8(buff[3]) << 6);
|
|
break;
|
|
|
|
case Edge_L18:
|
|
data[0] = Edge_Line;
|
|
data[1] = SInt(buff[0] >> 4) | SInt(buff[1] << 4) | (SInt8(buff[2] << 2) << 10);
|
|
data[2] = SInt(buff[2] >> 6) | SInt(buff[3] << 2) | (SInt8(buff[4]) << 10);
|
|
break;
|
|
|
|
case Edge_C5 :
|
|
data[0] = Edge_Quad;
|
|
data[1] = SInt(buff[0] >> 4) | (SInt8(buff[1] << 7) >> 3);
|
|
data[2] = SInt8(buff[1] << 2) >> 3;
|
|
data[3] = SInt(buff[1] >> 6) | (SInt8(buff[2] << 5) >> 3);
|
|
data[4] = SInt8(buff[2]) >> 3;
|
|
break;
|
|
|
|
case Edge_C7 :
|
|
data[0] = Edge_Quad;
|
|
data[1] = SInt(buff[0] >> 4) | (SInt8(buff[1] << 5) >> 1);
|
|
data[2] = SInt(buff[1] >> 3) | (SInt8(buff[2] << 6) >> 1);
|
|
data[3] = SInt(buff[2] >> 2) | (SInt8(buff[3] << 7) >> 1);
|
|
data[4] = SInt8(buff[3]) >> 1;
|
|
break;
|
|
|
|
case Edge_C9 :
|
|
data[0] = Edge_Quad;
|
|
data[1] = SInt(buff[0] >> 4) | (SInt8(buff[1] << 3) << 1);
|
|
data[2] = SInt(buff[1] >> 5) | (SInt8(buff[2] << 2) << 1);
|
|
data[3] = SInt(buff[2] >> 6) | (SInt8(buff[3] << 1) << 1);
|
|
data[4] = SInt(buff[3] >> 7) | (SInt8(buff[4] ) << 1);
|
|
break;
|
|
|
|
case Edge_C11:
|
|
data[0] = Edge_Quad;
|
|
data[1] = SInt(buff[0] >> 4) | (SInt8(buff[1] << 1) << 3);
|
|
data[2] = SInt(buff[1] >> 7) | SInt(buff[2] << 1) | (SInt8(buff[3] << 6) << 3);
|
|
data[3] = SInt(buff[3] >> 2) | (SInt8(buff[4] << 3) << 3);
|
|
data[4] = SInt(buff[4] >> 5) | (SInt8(buff[5] ) << 3);
|
|
break;
|
|
|
|
case Edge_C13:
|
|
data[0] = Edge_Quad;
|
|
data[1] = SInt(buff[0] >> 4) | SInt(buff[1] << 4) | (SInt8(buff[2] << 7) << 5);
|
|
data[2] = SInt(buff[2] >> 1) | (SInt8(buff[3] << 2) << 5);
|
|
data[3] = SInt(buff[3] >> 6) | SInt(buff[4] << 2) | (SInt8(buff[5] << 5) << 5);
|
|
data[4] = SInt(buff[5] >> 3) | (SInt8(buff[6] ) << 5);
|
|
break;
|
|
|
|
case Edge_C15:
|
|
data[0] = Edge_Quad;
|
|
data[1] = SInt(buff[0] >> 4) | SInt(buff[1] << 4) | (SInt8(buff[2] << 5) << 7);
|
|
data[2] = SInt(buff[2] >> 3) | SInt(buff[3] << 5) | (SInt8(buff[4] << 6) << 7);
|
|
data[3] = SInt(buff[4] >> 2) | SInt(buff[5] << 6) | (SInt8(buff[6] << 7) << 7);
|
|
data[4] = SInt(buff[6] >> 1) | (SInt8(buff[7] ) << 7);
|
|
break;
|
|
|
|
case Edge_C17:
|
|
data[0] = Edge_Quad;
|
|
data[1] = SInt(buff[0] >> 4) | SInt(buff[1] << 4) | (SInt8(buff[2] << 3) << 9);
|
|
data[2] = SInt(buff[2] >> 5) | SInt(buff[3] << 3) | (SInt8(buff[4] << 2) << 9);
|
|
data[3] = SInt(buff[4] >> 6) | SInt(buff[5] << 2) | (SInt8(buff[6] << 1) << 9);
|
|
data[4] = SInt(buff[6] >> 7) | SInt(buff[7] << 1) | (SInt8(buff[8] ) << 9);
|
|
break;
|
|
|
|
case Edge_C19:
|
|
data[0] = Edge_Quad;
|
|
data[1] = SInt(buff[0] >> 4) | SInt(buff[1] << 4) | (SInt8(buff[2] << 1) << 11);
|
|
data[2] = SInt(buff[2] >> 7) | SInt(buff[3] << 1) | SInt (buff[4] << 9) | (SInt8(buff[5] << 6) << 11);
|
|
data[3] = SInt(buff[5] >> 2) | SInt(buff[6] << 6) | (SInt8(buff[7] << 3) << 11);
|
|
data[4] = SInt(buff[7] >> 5) | SInt(buff[8] << 3) | (SInt8(buff[9] ) << 11);
|
|
break;
|
|
}
|
|
return nb;
|
|
}
|
|
|
|
|
|
#endif
|