232 lines
7.1 KiB
C++
232 lines
7.1 KiB
C++
/**********************************************************************
|
|
|
|
Filename : GRasterizer.h
|
|
Content :
|
|
Created : 2005-2006
|
|
Authors : Maxim Shemanarev
|
|
|
|
Copyright : (c) 2001-2006 Scaleform Corp. All Rights Reserved.
|
|
|
|
Notes : Scanline rasterizer with anti-aliasing
|
|
|
|
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.
|
|
|
|
----------------------------------------------------------------------
|
|
The code of these classes was taken from the Anti-Grain Geometry
|
|
Project and modified for the use by Scaleform.
|
|
Permission to use without restrictions is hereby granted to
|
|
Scaleform Corporation by the author of Anti-Grain Geometry Project.
|
|
See http://antigtain.com for details.
|
|
|
|
The author of Anti-Grain Geometry gratefully acknowleges the support
|
|
of David Turner, Robert Wilhelm, and Werner Lemberg - the authors of
|
|
the FreeType libray - in producing this work.
|
|
See http://www.freetype.org for details.
|
|
**********************************************************************/
|
|
|
|
#ifndef INC_GRASTERIZER_H
|
|
#define INC_GRASTERIZER_H
|
|
|
|
#include "GArrayUnsafe.h"
|
|
#include "GArrayPaged.h"
|
|
#include "GAlgorithm.h"
|
|
#include "GCompoundShape.h"
|
|
|
|
#ifdef GFC_MATH_H
|
|
#include GFC_MATH_H
|
|
#else
|
|
#include <math.h>
|
|
#endif
|
|
#include <string.h>
|
|
|
|
|
|
// ***** Declared Classes
|
|
class GRasterizer;
|
|
|
|
|
|
|
|
class GRasterizer
|
|
{
|
|
public:
|
|
enum { SID = GStatRG_Rasterizer_Mem };
|
|
|
|
enum
|
|
{
|
|
SubpixelShift = 8,
|
|
SubpixelScale = 1 << SubpixelShift,
|
|
SubpixelMask = SubpixelScale - 1,
|
|
|
|
AntiAliasShift = 8,
|
|
AntiAliasScale = 1 << AntiAliasShift,
|
|
AntiAliasMask = AntiAliasScale - 1,
|
|
AntiAliasScale2 = AntiAliasScale * 2,
|
|
AntiAliasMask2 = AntiAliasScale2 - 1
|
|
};
|
|
|
|
enum FillRuleType
|
|
{
|
|
FillNonZero,
|
|
FillEvenOdd
|
|
};
|
|
|
|
GRasterizer();
|
|
|
|
// Setup (optional)
|
|
//-----------------------------------
|
|
// FillRule = FillNonZero by default
|
|
void SetFillRule(FillRuleType f) { FillRule = f; }
|
|
FillRuleType GetFillRule() const { return FillRule; }
|
|
|
|
void SetGamma(GCoordType g);
|
|
GCoordType GetGamma() const { return Gamma; }
|
|
|
|
UPInt GetNumBytes() const;
|
|
|
|
// "Manual" rasterization interface
|
|
//-----------------------------------
|
|
void Clear();
|
|
void ClearAndRelease();
|
|
void MoveTo(GCoordType x, GCoordType y);
|
|
void LineTo(GCoordType x, GCoordType y);
|
|
void ClosePolygon();
|
|
|
|
// "Automatic" rasterization. Internally it calls
|
|
// MoveTo()/LineTo(). The function accumulates
|
|
// the shapes, so that you can add more than one
|
|
// shape and rasterize it as a whole. Call Reset()
|
|
// if you want to start a new rasterization process.
|
|
//-----------------------------------
|
|
void AddShape(const GCompoundShape& shape,
|
|
GCoordType ratio = 1,
|
|
int activeStyle = -1);
|
|
|
|
void AddShapeScaled(const GCompoundShape& shape,
|
|
GCoordType scaleX, GCoordType scaleY,
|
|
GCoordType transX, GCoordType transY,
|
|
int activeStyle = -1);
|
|
|
|
// After AddShape() or MoveTo()/LineTo() the
|
|
// bounding box is valid, as well as the number of
|
|
// resulting scan lines.
|
|
//-----------------------------------
|
|
int GetMinX() const { return MinX; }
|
|
int GetMinY() const { return MinY; }
|
|
int GetMaxX() const { return MaxX; }
|
|
int GetMaxY() const { return MaxY; }
|
|
UPInt GetNumScanlines() const { return SortedYs.GetSize(); }
|
|
|
|
// Call SortCells() after the shape is added. It
|
|
// returns true if there's something to sweep and
|
|
// false if the shape is empty.
|
|
//-----------------------------------
|
|
bool SortCells();
|
|
|
|
// Sweep one scan line, that is, rasterize it.
|
|
// "pRaster" should point to the beginning of the row
|
|
// of gray-scale pixels. The pRaster[0] corresponds to
|
|
// GetMinX() value. The typical loop is:
|
|
//
|
|
// if(rasterizer.SortCells())
|
|
// {
|
|
// for(unsigned i = 0; i < rasterizer.NumScanlines(); i++)
|
|
// {
|
|
// rasterizer.SweepScanline(i, pRaster + i * rasterWidth);
|
|
// }
|
|
// }
|
|
//-----------------------------------
|
|
void SweepScanline(unsigned scanline, unsigned char* praster,
|
|
unsigned numChannels = 1) const;
|
|
|
|
void SweepScanlineThreshold(unsigned scanline, unsigned char* praster,
|
|
unsigned numChannels = 1,
|
|
unsigned threshold = AntiAliasMask/2) const;
|
|
private:
|
|
struct Cell
|
|
{
|
|
int x, y, Cover, Area;
|
|
};
|
|
|
|
struct SortedY
|
|
{
|
|
unsigned Start, Count;
|
|
};
|
|
|
|
void line(int x1, int y1, int x2, int y2);
|
|
void horLine(int ey, int x1, int y1, int x2, int y2);
|
|
|
|
GINLINE void setCurrCell(int x, int y)
|
|
{
|
|
if((CurrCell.x - x) | (CurrCell.y - y))
|
|
{
|
|
if(CurrCell.Area | CurrCell.Cover)
|
|
{
|
|
Cells.PushBack(CurrCell);
|
|
}
|
|
CurrCell.x = x;
|
|
CurrCell.y = y;
|
|
CurrCell.Cover = 0;
|
|
CurrCell.Area = 0;
|
|
}
|
|
}
|
|
|
|
GINLINE static bool cellXLess(const Cell* a, const Cell* b)
|
|
{
|
|
return a->x < b->x;
|
|
}
|
|
|
|
GINLINE unsigned calcAlpha(int area) const
|
|
{
|
|
int alpha = area >> (SubpixelShift * 2 + 1 - AntiAliasShift);
|
|
|
|
if (alpha < 0)
|
|
alpha = -alpha;
|
|
if (FillRule == FillEvenOdd)
|
|
{
|
|
alpha &= AntiAliasMask2;
|
|
if (alpha > AntiAliasScale)
|
|
alpha = AntiAliasScale2 - alpha;
|
|
}
|
|
if (alpha > AntiAliasMask)
|
|
alpha = AntiAliasMask;
|
|
return GammaLut.GetSize() ? GammaLut[alpha] : alpha;
|
|
}
|
|
|
|
GINLINE unsigned calcAlpha(int area, unsigned threshold) const
|
|
{
|
|
int alpha = area >> (SubpixelShift * 2 + 1 - AntiAliasShift);
|
|
|
|
if (alpha < 0)
|
|
alpha = -alpha;
|
|
if (FillRule == FillEvenOdd)
|
|
{
|
|
alpha &= AntiAliasMask2;
|
|
if (alpha > AntiAliasScale)
|
|
alpha = AntiAliasScale2 - alpha;
|
|
}
|
|
return (alpha <= int(threshold)) ? 0 : AntiAliasMask;
|
|
}
|
|
|
|
|
|
FillRuleType FillRule;
|
|
GCoordType Gamma;
|
|
GArrayUnsafeLH_POD<unsigned, SID> GammaLut;
|
|
GArrayPagedLH_POD<Cell, 8, 64, SID> Cells;
|
|
GArrayUnsafeLH_POD<Cell*, SID> SortedCells;
|
|
GArrayUnsafeLH_POD<SortedY, SID> SortedYs;
|
|
Cell CurrCell;
|
|
int MinX;
|
|
int MinY;
|
|
int MaxX;
|
|
int MaxY;
|
|
int StartX;
|
|
int StartY;
|
|
int LastX;
|
|
int LastY;
|
|
};
|
|
|
|
#endif
|