Files
GTASource/rage/scaleform/Src/GRenderer/GRasterizer.h
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

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