antigrain geometry renderer and static lib
This commit is contained in:
parent
b671d2dc37
commit
20bbb21f56
|
@ -0,0 +1,177 @@
|
|||
#include "GPU.h"
|
||||
#include "NDSSystem.h"
|
||||
|
||||
#include "agg_renderer_base.h"
|
||||
#include "agg_renderer_primitives.h"
|
||||
#include "agg_renderer_scanline.h"
|
||||
#include "agg_bounding_rect.h"
|
||||
#include "agg_trans_affine.h"
|
||||
#include "agg_path_storage.h"
|
||||
#include "agg_color_rgba.h"
|
||||
|
||||
#include "agg_rasterizer_scanline_aa.h"
|
||||
#include "agg_scanline_p.h"
|
||||
|
||||
//raster text
|
||||
#include "agg_glyph_raster_bin.h"
|
||||
#include "agg_embedded_raster_fonts.h"
|
||||
#include "agg_renderer_raster_text.h"
|
||||
|
||||
#define AGG_RGB555 //pixfmt will be rgb555
|
||||
#include "pixel_formats.h" //this file is in agg/examples
|
||||
|
||||
// The AGG base renderer
|
||||
typedef agg::renderer_base<pixfmt> RendererBase;
|
||||
|
||||
// The AGG primitives renderer
|
||||
typedef agg::renderer_primitives<RendererBase> RendererPrimitives;
|
||||
|
||||
// The AGG solid renderer
|
||||
typedef agg::renderer_scanline_aa_solid<RendererBase> RendererSolid;
|
||||
|
||||
// AGG always wants a pointer to the
|
||||
// beginning of the buffer, no matter what the stride. (AGG does handle
|
||||
// negative strides correctly.)
|
||||
const int stride = 512;
|
||||
|
||||
//width and height of emu's rendering buffer
|
||||
const int width = 256;
|
||||
const int height = 384;
|
||||
|
||||
agg::rendering_buffer rBuf; // AGG's rendering buffer, pointing into the emu's rendering buffer
|
||||
|
||||
void agg_draw_solid_ellipse(int x, int y, int rx, int ry, int r, int g, int b, int a){
|
||||
|
||||
rBuf.attach(GPU_tempScreen, width, height, stride);
|
||||
|
||||
pixfmt pixf(rBuf);
|
||||
RendererBase rbase(pixf);
|
||||
RendererPrimitives rprim(rbase);
|
||||
|
||||
rprim.fill_color(pixfmt::color_type(r, g, b, a));
|
||||
|
||||
rprim.solid_ellipse(x, y, rx, ry);
|
||||
|
||||
}
|
||||
|
||||
void agg_draw_solid_rectangle(int x1, int y1, int x2, int y2, int r, int g, int b, int a){
|
||||
|
||||
rBuf.attach(GPU_tempScreen, width, height, stride);
|
||||
|
||||
pixfmt pixf(rBuf);
|
||||
RendererBase rbase(pixf);
|
||||
RendererPrimitives rprim(rbase);
|
||||
|
||||
rprim.fill_color(pixfmt::color_type(r, g, b, a));
|
||||
|
||||
rprim.solid_rectangle(x1, y1, x2, y2);
|
||||
|
||||
}
|
||||
|
||||
void agg_draw_solid_triangle(int x1, int y1, int x2, int y2, int x3, int y3, int r, int g, int b, int a, int gamma){
|
||||
|
||||
rBuf.attach(GPU_tempScreen, width, height, stride);
|
||||
|
||||
pixfmt pixf(rBuf);
|
||||
RendererBase rbase(pixf);
|
||||
|
||||
RendererSolid ren_aa(rbase);
|
||||
agg::rasterizer_scanline_aa<> m_ras;
|
||||
agg::scanline_p8 m_sl_p8;
|
||||
|
||||
agg::path_storage path;
|
||||
|
||||
path.move_to(x1, y1);
|
||||
path.line_to(x2, y2);
|
||||
path.line_to(x3, y3);
|
||||
path.close_polygon();
|
||||
|
||||
ren_aa.color(agg::rgba(r, g, b, a));
|
||||
|
||||
m_ras.gamma(agg::gamma_power(gamma * 2.0));
|
||||
m_ras.add_path(path);
|
||||
agg::render_scanlines(m_ras, m_sl_p8, ren_aa);
|
||||
|
||||
}
|
||||
|
||||
void agg_draw_raster_font(int x, int y, int r, int g, int b, int a, char* strbuf, char* fontchoice){
|
||||
|
||||
typedef agg::renderer_base<pixfmt> ren_base;
|
||||
typedef agg::glyph_raster_bin<agg::rgba8> glyph_gen;
|
||||
|
||||
int flipy = 0;
|
||||
|
||||
struct font_type
|
||||
{
|
||||
const agg::int8u* font;
|
||||
const char* name;
|
||||
}
|
||||
fonts[] =
|
||||
{
|
||||
{ agg::gse4x6, "gse4x6" },
|
||||
{ agg::gse4x8, "gse4x8" },
|
||||
{ agg::gse5x7, "gse5x7" },
|
||||
{ agg::gse5x9, "gse5x9" },
|
||||
{ agg::gse6x9, "gse6x9" },
|
||||
{ agg::gse6x12, "gse6x12" },
|
||||
{ agg::gse7x11, "gse7x11" },
|
||||
{ agg::gse7x11_bold, "gse7x11_bold" },
|
||||
{ agg::gse7x15, "gse7x15" },
|
||||
{ agg::gse7x15_bold, "gse7x15_bold" },
|
||||
{ agg::gse8x16, "gse8x16" },
|
||||
{ agg::gse8x16_bold, "gse8x16_bold" },
|
||||
{ agg::mcs11_prop, "mcs11_prop" },
|
||||
{ agg::mcs11_prop_condensed, "mcs11_prop_condensed" },
|
||||
{ agg::mcs12_prop, "mcs12_prop" },
|
||||
{ agg::mcs13_prop, "mcs13_prop" },
|
||||
{ agg::mcs5x10_mono, "mcs5x10_mono" },
|
||||
{ agg::mcs5x11_mono, "mcs5x11_mono" },
|
||||
{ agg::mcs6x10_mono, "mcs6x10_mono" },
|
||||
{ agg::mcs6x11_mono, "mcs6x11_mono" },
|
||||
{ agg::mcs7x12_mono_high, "mcs7x12_mono_high" },
|
||||
{ agg::mcs7x12_mono_low, "mcs7x12_mono_low" },
|
||||
{ agg::verdana12, "verdana12" },
|
||||
{ agg::verdana12_bold, "verdana12_bold" },
|
||||
{ agg::verdana13, "verdana13" },
|
||||
{ agg::verdana13_bold, "verdana13_bold" },
|
||||
{ agg::verdana14, "verdana14" },
|
||||
{ agg::verdana14_bold, "verdana14_bold" },
|
||||
{ agg::verdana16, "verdana16" },
|
||||
{ agg::verdana16_bold, "verdana16_bold" },
|
||||
{ agg::verdana17, "verdana17" },
|
||||
{ agg::verdana17_bold, "verdana17_bold" },
|
||||
{ agg::verdana18, "verdana18" },
|
||||
{ agg::verdana18_bold, "verdana18_bold" },
|
||||
0, 0
|
||||
};
|
||||
|
||||
int fontnumber = 0;
|
||||
|
||||
for(int i = 0; fonts[i].font; i++) {
|
||||
if(!strcmp(fonts[i].name, fontchoice))
|
||||
fontnumber = i;
|
||||
}
|
||||
|
||||
glyph_gen glyph(0);
|
||||
|
||||
rBuf.attach(GPU_tempScreen, width, height, stride);
|
||||
|
||||
pixfmt pixf(rBuf);
|
||||
ren_base rb(pixf);
|
||||
|
||||
agg::renderer_raster_htext_solid<ren_base, glyph_gen> rt(rb, glyph);
|
||||
|
||||
rt.color(agg::rgba(r,g,b,a));
|
||||
|
||||
glyph.font(fonts[fontnumber].font);
|
||||
rt.render_text(x, y, strbuf, !flipy);
|
||||
|
||||
}
|
||||
//temporary, just for testing the lib
|
||||
void AGGDraw() {
|
||||
|
||||
agg_draw_solid_triangle(0, 60, 200, 170, 100, 310, 255, 64, 64, 128, 99999);
|
||||
agg_draw_solid_rectangle(100, 100, 200, 200, 0, 255, 0, 128);
|
||||
agg_draw_solid_ellipse(70, 80, 50, 50, 255, 0, 0, 128);
|
||||
agg_draw_raster_font(60, 60, 255, 0, 255, 128, "testing testing testing", "verdana18_bold");
|
||||
}
|
|
@ -51,7 +51,7 @@
|
|||
FavorSizeOrSpeed="0"
|
||||
EnableFiberSafeOptimizations="false"
|
||||
WholeProgramOptimization="false"
|
||||
AdditionalIncludeDirectories=".;..;"lua\lua-5.1.4\src";"glib-2.20.1\build";"glib-2.20.1\build\glib";.\zlib123;.\zziplib;.\winpcap;userconfig;defaultconfig"
|
||||
AdditionalIncludeDirectories=".;..;"lua\lua-5.1.4\src";"glib-2.20.1\build";"glib-2.20.1\build\glib";.\zlib123;.\zziplib;.\winpcap;userconfig;defaultconfig;.\agg\include;.\agg\examples"
|
||||
PreprocessorDefinitions="DEBUG;_CRT_SECURE_NO_DEPRECATE;WIN32;SPU_INTERPOLATE;HAVE_LIBZ;HAVE_LIBZZIP;NOMINMAX;DEBUG;EXPERIMENTAL_WIFI"
|
||||
ExceptionHandling="1"
|
||||
BasicRuntimeChecks="0"
|
||||
|
@ -75,7 +75,7 @@
|
|||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="lua-5.1.4-x86.lib glib-2.20.1-x86.lib vfw32.lib winmm.lib opengl32.lib glu32.lib ws2_32.lib user32.lib gdi32.lib directx\dxguid.lib shell32.lib comdlg32.lib directx\dxerr8.lib directx\dsound.lib directx\dinput8.lib directx\ddraw.lib zlib-2005-x32.lib zziplib-2005-x32.lib shlwapi.lib winpcap\wpcap.lib 7zip.lib"
|
||||
AdditionalDependencies="agg-2.5.lib lua-5.1.4-x86.lib glib-2.20.1-x86.lib vfw32.lib winmm.lib opengl32.lib glu32.lib ws2_32.lib user32.lib gdi32.lib directx\dxguid.lib shell32.lib comdlg32.lib directx\dxerr8.lib directx\dsound.lib directx\dinput8.lib directx\ddraw.lib zlib-2005-x32.lib zziplib-2005-x32.lib shlwapi.lib winpcap\wpcap.lib 7zip.lib"
|
||||
OutputFile="$(OutDir)\$(ProjectName)_debug.exe"
|
||||
AdditionalLibraryDirectories=".\zlib123;.\zziplib;glib-2.20.1\lib;.\lua\lib;.\7z"
|
||||
DelayLoadDLLs="wpcap.dll"
|
||||
|
@ -243,7 +243,7 @@
|
|||
OmitFramePointers="true"
|
||||
EnableFiberSafeOptimizations="true"
|
||||
WholeProgramOptimization="false"
|
||||
AdditionalIncludeDirectories=".;..;"lua\lua-5.1.4\src";"glib-2.20.1\build";"glib-2.20.1\build\glib";.\zlib123;.\zziplib;.\winpcap;userconfig;defaultconfig"
|
||||
AdditionalIncludeDirectories=".;..;"lua\lua-5.1.4\src";"glib-2.20.1\build";"glib-2.20.1\build\glib";.\zlib123;.\zziplib;.\winpcap;userconfig;defaultconfig;.\agg\include;.\agg\examples"
|
||||
PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32;HAVE_LIBZ;HAVE_LIBZZIP;SPU_INTERPOLATE;NOMINMAX;NDEBUG;RELEASE;EXPERIMENTAL_WIFI"
|
||||
StringPooling="true"
|
||||
ExceptionHandling="1"
|
||||
|
@ -270,7 +270,7 @@
|
|||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="lua-5.1.4-x86.lib glib-2.20.1-x86.lib vfw32.lib winmm.lib opengl32.lib glu32.lib ws2_32.lib user32.lib gdi32.lib directx\dxguid.lib shell32.lib comdlg32.lib directx\dxerr8.lib directx\dsound.lib directx\dinput8.lib directx\ddraw.lib zlib-2005-x32.lib zziplib-2005-x32.lib shlwapi.lib winpcap\wpcap.lib 7zip.lib"
|
||||
AdditionalDependencies="agg-2.5.lib lua-5.1.4-x86.lib glib-2.20.1-x86.lib vfw32.lib winmm.lib opengl32.lib glu32.lib ws2_32.lib user32.lib gdi32.lib directx\dxguid.lib shell32.lib comdlg32.lib directx\dxerr8.lib directx\dsound.lib directx\dinput8.lib directx\ddraw.lib zlib-2005-x32.lib zziplib-2005-x32.lib shlwapi.lib winpcap\wpcap.lib 7zip.lib"
|
||||
OutputFile="$(OutDir)\$(ProjectName)_releaseFastBuild.exe"
|
||||
AdditionalLibraryDirectories=".\zlib123;.\zziplib;glib-2.20.1\lib;.\lua\lib;.\7z"
|
||||
DelayLoadDLLs="wpcap.dll"
|
||||
|
@ -754,6 +754,10 @@
|
|||
RelativePath="..\addons.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\aggdraw.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ARM9.h"
|
||||
>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="shift_jis"?>
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
|
@ -235,7 +235,7 @@
|
|||
OmitFramePointers="true"
|
||||
EnableFiberSafeOptimizations="true"
|
||||
WholeProgramOptimization="false"
|
||||
AdditionalIncludeDirectories=".;..;"lua\lua-5.1.4\src";"glib-2.20.1\build";"glib-2.20.1\build\glib";.\zlib123;.\zziplib;.\winpcap;userconfig;defaultconfig;.\7z"
|
||||
AdditionalIncludeDirectories=".;..;"lua\lua-5.1.4\src";"glib-2.20.1\build";"glib-2.20.1\build\glib";.\zlib123;.\zziplib;.\winpcap;userconfig;defaultconfig;.\7z;.\agg\include;.\agg\examples"
|
||||
PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32;HAVE_LIBZ;HAVE_LIBZZIP;SSE2;SPU_INTERPOLATE;NOMINMAX;RELEASE;EXPERIMENTAL_WIFI;NDEBUG"
|
||||
StringPooling="true"
|
||||
ExceptionHandling="1"
|
||||
|
@ -259,9 +259,9 @@
|
|||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="lua-5.1.4-x86.lib glib-2.20.1-x86.lib vfw32.lib winmm.lib opengl32.lib glu32.lib ws2_32.lib user32.lib gdi32.lib directx\dxguid.lib shell32.lib comdlg32.lib directx\dxerr8.lib directx\dsound.lib directx\dinput8.lib directx\ddraw.lib zlib-2005-x32.lib zziplib-2005-x32.lib shlwapi.lib winpcap\wpcap.lib 7zip.lib"
|
||||
AdditionalDependencies="lua-5.1.4-x86.lib glib-2.20.1-x86.lib vfw32.lib winmm.lib opengl32.lib glu32.lib ws2_32.lib user32.lib gdi32.lib directx\dxguid.lib shell32.lib comdlg32.lib directx\dxerr8.lib directx\dsound.lib directx\dinput8.lib directx\ddraw.lib zlib-2005-x32.lib zziplib-2005-x32.lib shlwapi.lib winpcap\wpcap.lib 7zip.lib agg-2.5.lib"
|
||||
OutputFile="$(OutDir)\$(ProjectName)_releaseFastBuild.exe"
|
||||
AdditionalLibraryDirectories=".\zlib123;.\zziplib;glib-2.20.1\lib;lua\lib;.\7z"
|
||||
AdditionalLibraryDirectories=".\zlib123;.\zziplib;"glib-2.20.1\lib";lua\lib;.\7z;.\agg"
|
||||
DelayLoadDLLs="wpcap.dll"
|
||||
GenerateDebugInformation="true"
|
||||
OptimizeReferences="2"
|
||||
|
@ -309,6 +309,10 @@
|
|||
RelativePath="..\addons.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\aggdraw.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\arm_instructions.cpp"
|
||||
>
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,20 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual Studio 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "agg-2.5", "agg-2.5.vcproj", "{887D5BD9-14EB-4B81-AABA-71E1E1063044}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{887D5BD9-14EB-4B81-AABA-71E1E1063044}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{887D5BD9-14EB-4B81-AABA-71E1E1063044}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{887D5BD9-14EB-4B81-AABA-71E1E1063044}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{887D5BD9-14EB-4B81-AABA-71E1E1063044}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,883 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="agg-2.5"
|
||||
ProjectGUID="{887D5BD9-14EB-4B81-AABA-71E1E1063044}"
|
||||
RootNamespace="agg-2.5"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="0"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="4"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=".\;.\include"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="4"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="true"
|
||||
EnableFiberSafeOptimizations="true"
|
||||
AdditionalIncludeDirectories=".\;.\include"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;"
|
||||
StringPooling="true"
|
||||
BasicRuntimeChecks="0"
|
||||
SmallerTypeCheck="false"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="3"
|
||||
OmitDefaultLibName="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\include\agg_alpha_mask_u8.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_arc.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_array.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_arrowhead.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_basics.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_bezier_arc.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\ctrl\agg_bezier_ctrl.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_bitset_iterator.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_blur.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_bounding_rect.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_bspline.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\ctrl\agg_cbox_ctrl.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_clip_liang_barsky.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\util\agg_color_conv.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\util\agg_color_conv_rgb16.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\util\agg_color_conv_rgb8.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_color_gray.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_color_rgba.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_config.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_conv_adaptor_vcgen.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_conv_adaptor_vpgen.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_conv_bspline.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_conv_clip_polygon.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_conv_clip_polyline.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_conv_close_polygon.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_conv_concat.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_conv_contour.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_conv_curve.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_conv_dash.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_conv_gpc.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_conv_marker.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_conv_marker_adaptor.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_conv_segmentator.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_conv_shorten_path.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_conv_smooth_poly1.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_conv_stroke.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_conv_transform.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_conv_unclose_polygon.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\ctrl\agg_ctrl.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_curves.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_dda_line.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_ellipse.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_ellipse_bresenham.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_embedded_raster_fonts.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_font_cache_manager.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\font_win32_tt\agg_font_win32_tt.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\ctrl\agg_gamma_ctrl.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_gamma_functions.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_gamma_lut.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\ctrl\agg_gamma_spline.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_glyph_raster_bin.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_gradient_lut.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_gsv_text.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_image_accessors.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_image_filters.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_line_aa_basics.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_math.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_math_stroke.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_path_length.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_path_storage.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_path_storage_integer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_pattern_filters_rgba.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_pixfmt_amask_adaptor.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_pixfmt_gray.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_pixfmt_rgb.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_pixfmt_rgb_packed.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_pixfmt_rgba.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_pixfmt_transposer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\platform\agg_platform_support.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\ctrl\agg_polygon_ctrl.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_rasterizer_cells_aa.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_rasterizer_compound_aa.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_rasterizer_outline.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_rasterizer_outline_aa.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_rasterizer_scanline_aa.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_rasterizer_sl_clip.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\ctrl\agg_rbox_ctrl.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_renderer_base.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_renderer_markers.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_renderer_mclip.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_renderer_outline_aa.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_renderer_outline_image.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_renderer_primitives.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_renderer_raster_text.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_renderer_scanline.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_rendering_buffer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_rendering_buffer_dynarow.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_rounded_rect.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\ctrl\agg_scale_ctrl.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_scanline_bin.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_scanline_boolean_algebra.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_scanline_p.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_scanline_storage_aa.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_scanline_storage_bin.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_scanline_u.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_shorten_path.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_simul_eq.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\ctrl\agg_slider_ctrl.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_span_allocator.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_span_converter.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_span_gouraud.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_span_gouraud_gray.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_span_gouraud_rgba.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_span_gradient.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_span_gradient_alpha.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_span_image_filter.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_span_image_filter_gray.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_span_image_filter_rgb.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_span_image_filter_rgba.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_span_interpolator_adaptor.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_span_interpolator_linear.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_span_interpolator_persp.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_span_interpolator_trans.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_span_pattern_gray.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_span_pattern_rgb.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_span_pattern_rgba.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_span_solid.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_span_subdiv_adaptor.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\ctrl\agg_spline_ctrl.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_trans_affine.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_trans_bilinear.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_trans_double_path.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_trans_perspective.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_trans_single_path.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_trans_viewport.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_trans_warp_magnifier.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_vcgen_bspline.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_vcgen_contour.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_vcgen_dash.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_vcgen_markers_term.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_vcgen_smooth_poly1.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_vcgen_stroke.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_vcgen_vertex_sequence.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_vertex_sequence.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_vpgen_clip_polygon.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_vpgen_clip_polyline.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\agg_vpgen_segmentator.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\platform\win32\agg_win32_bmp.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\gpc\gpc.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\agg_arc.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\agg_arrowhead.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\agg_bezier_arc.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\ctrl\agg_bezier_ctrl.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\agg_bspline.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\ctrl\agg_cbox_ctrl.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\agg_curves.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\agg_embedded_raster_fonts.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\font_win32_tt\agg_font_win32_tt.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\ctrl\agg_gamma_ctrl.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\ctrl\agg_gamma_spline.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\agg_gsv_text.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\agg_image_filters.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\agg_line_aa_basics.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\agg_line_profile_aa.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\platform\win32\agg_platform_support.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\ctrl\agg_polygon_ctrl.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\ctrl\agg_rbox_ctrl.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\agg_rounded_rect.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\ctrl\agg_scale_ctrl.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\ctrl\agg_slider_ctrl.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\ctrl\agg_spline_ctrl.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\agg_sqrt_tables.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\agg_trans_affine.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\agg_trans_double_path.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\agg_trans_single_path.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\agg_trans_warp_magnifier.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\agg_vcgen_bspline.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\agg_vcgen_contour.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\agg_vcgen_dash.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\agg_vcgen_markers_term.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\agg_vcgen_smooth_poly1.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\agg_vcgen_stroke.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\agg_vpgen_clip_polygon.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\agg_vpgen_clip_polyline.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\agg_vpgen_segmentator.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\platform\win32\agg_win32_bmp.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\gpc\gpc.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
|
@ -0,0 +1,184 @@
|
|||
#ifndef PIXEL_FORMATS_INCLUDED
|
||||
#define PIXEL_FORMATS_INCLUDED
|
||||
|
||||
#if defined(AGG_GRAY8)
|
||||
|
||||
#include "agg_pixfmt_gray.h"
|
||||
#define pix_format agg::pix_format_gray8
|
||||
typedef agg::pixfmt_gray8 pixfmt;
|
||||
typedef agg::pixfmt_gray8_pre pixfmt_pre;
|
||||
typedef agg::gray8 color_type;
|
||||
|
||||
#elif defined(AGG_GRAY16)
|
||||
|
||||
#include "agg_pixfmt_gray.h"
|
||||
#define pix_format agg::pix_format_gray16
|
||||
typedef agg::pixfmt_gray16 pixfmt;
|
||||
typedef agg::pixfmt_gray16_pre pixfmt_pre;
|
||||
typedef agg::gray16 color_type;
|
||||
|
||||
#elif defined(AGG_BGR24)
|
||||
|
||||
#include "agg_pixfmt_rgb.h"
|
||||
#define pix_format agg::pix_format_bgr24
|
||||
typedef agg::pixfmt_bgr24 pixfmt;
|
||||
typedef agg::pixfmt_bgr24_pre pixfmt_pre;
|
||||
#define pixfmt_gamma agg::pixfmt_bgr24_gamma
|
||||
typedef agg::rgba8 color_type;
|
||||
typedef agg::order_bgr component_order;
|
||||
|
||||
#elif defined(AGG_RGB24)
|
||||
|
||||
#include "agg_pixfmt_rgb.h"
|
||||
#define pix_format agg::pix_format_rgb24
|
||||
typedef agg::pixfmt_rgb24 pixfmt;
|
||||
typedef agg::pixfmt_rgb24_pre pixfmt_pre;
|
||||
#define pixfmt_gamma agg::pixfmt_rgb24_gamma
|
||||
typedef agg::rgba8 color_type;
|
||||
typedef agg::order_rgb component_order;
|
||||
|
||||
#elif defined(AGG_BGR48)
|
||||
|
||||
#include "agg_pixfmt_rgb.h"
|
||||
#define pix_format agg::pix_format_bgr48
|
||||
typedef agg::pixfmt_bgr48 pixfmt;
|
||||
typedef agg::pixfmt_bgr48_pre pixfmt_pre;
|
||||
#define pixfmt_gamma agg::pixfmt_bgr48_gamma
|
||||
typedef agg::rgba16 color_type;
|
||||
typedef agg::order_bgr component_order;
|
||||
|
||||
#elif defined(AGG_RGB48)
|
||||
|
||||
#include "agg_pixfmt_rgb.h"
|
||||
#define pix_format agg::pix_format_rgb48
|
||||
typedef agg::pixfmt_rgb48 pixfmt;
|
||||
typedef agg::pixfmt_rgb48_pre pixfmt_pre;
|
||||
#define pixfmt_gamma agg::pixfmt_rgb48_gamma
|
||||
typedef agg::rgba16 color_type;
|
||||
typedef agg::order_rgb component_order;
|
||||
|
||||
#elif defined(AGG_BGRA32)
|
||||
|
||||
#include "agg_pixfmt_rgba.h"
|
||||
#define pix_format agg::pix_format_bgra32
|
||||
typedef agg::pixfmt_bgra32 pixfmt;
|
||||
typedef agg::pixfmt_bgra32_pre pixfmt_pre;
|
||||
typedef agg::rgba8 color_type;
|
||||
typedef agg::order_bgra component_order;
|
||||
|
||||
#elif defined(AGG_RGBA32)
|
||||
|
||||
#include "agg_pixfmt_rgba.h"
|
||||
#define pix_format agg::pix_format_rgba32
|
||||
typedef agg::pixfmt_rgba32 pixfmt;
|
||||
typedef agg::pixfmt_rgba32_pre pixfmt_pre;
|
||||
typedef agg::rgba8 color_type;
|
||||
typedef agg::order_rgba component_order;
|
||||
|
||||
#elif defined(AGG_ARGB32)
|
||||
|
||||
#include "agg_pixfmt_rgba.h"
|
||||
#define pix_format agg::pix_format_argb32
|
||||
typedef agg::pixfmt_argb32 pixfmt;
|
||||
typedef agg::pixfmt_argb32_pre pixfmt_pre;
|
||||
typedef agg::rgba8 color_type;
|
||||
typedef agg::order_argb component_order;
|
||||
|
||||
#elif defined(AGG_ABGR32)
|
||||
|
||||
#include "agg_pixfmt_rgba.h"
|
||||
#define pix_format agg::pix_format_abgr32
|
||||
typedef agg::pixfmt_abgr32 pixfmt;
|
||||
typedef agg::pixfmt_abgr32_pre pixfmt_pre;
|
||||
typedef agg::rgba8 color_type;
|
||||
typedef agg::order_argb component_order;
|
||||
|
||||
#elif defined(AGG_BGRA64)
|
||||
|
||||
#include "agg_pixfmt_rgba.h"
|
||||
#define pix_format agg::pix_format_bgra64
|
||||
typedef agg::pixfmt_bgra64 pixfmt;
|
||||
typedef agg::pixfmt_bgra64_pre pixfmt_pre;
|
||||
typedef agg::rgba16 color_type;
|
||||
typedef agg::order_bgra component_order;
|
||||
|
||||
#elif defined(AGG_RGBA64)
|
||||
|
||||
#include "agg_pixfmt_rgba.h"
|
||||
#define pix_format agg::pix_format_rgba64
|
||||
typedef agg::pixfmt_rgba64 pixfmt;
|
||||
typedef agg::pixfmt_rgba64_pre pixfmt_pre;
|
||||
typedef agg::rgba16 color_type;
|
||||
typedef agg::order_rgba component_order;
|
||||
|
||||
#elif defined(AGG_ARGB64)
|
||||
|
||||
#include "agg_pixfmt_rgba.h"
|
||||
#define pix_format agg::pix_format_argb64
|
||||
typedef agg::pixfmt_argb64 pixfmt;
|
||||
typedef agg::pixfmt_argb64_pre pixfmt_pre;
|
||||
typedef agg::rgba16 color_type;
|
||||
typedef agg::order_argb component_order;
|
||||
|
||||
#elif defined(AGG_ABGR64)
|
||||
|
||||
#include "agg_pixfmt_rgba.h"
|
||||
#define pix_format agg::pix_format_abgr64
|
||||
typedef agg::pixfmt_abgr64 pixfmt;
|
||||
typedef agg::pixfmt_abgr64_pre pixfmt_pre;
|
||||
typedef agg::rgba16 color_type;
|
||||
typedef agg::order_argb component_order;
|
||||
|
||||
#elif defined(AGG_RGB565)
|
||||
|
||||
#include "agg_pixfmt_rgb_packed.h"
|
||||
#define pix_format agg::pix_format_rgb565
|
||||
typedef agg::pixfmt_rgb565 pixfmt;
|
||||
typedef agg::pixfmt_rgb565_pre pixfmt_pre;
|
||||
typedef agg::rgba8 color_type;
|
||||
|
||||
#elif defined(AGG_RGB555)
|
||||
|
||||
#include "agg_pixfmt_rgb_packed.h"
|
||||
#define pix_format agg::pix_format_rgb555
|
||||
typedef agg::pixfmt_rgb555 pixfmt;
|
||||
typedef agg::pixfmt_rgb555_pre pixfmt_pre;
|
||||
typedef agg::rgba8 color_type;
|
||||
|
||||
#elif defined(AGG_RGB_AAA)
|
||||
|
||||
#include "agg_pixfmt_rgb_packed.h"
|
||||
#define pix_format agg::pix_format_rgbAAA
|
||||
typedef agg::pixfmt_rgbAAA pixfmt;
|
||||
typedef agg::pixfmt_rgbAAA_pre pixfmt_pre;
|
||||
typedef agg::rgba16 color_type;
|
||||
|
||||
#elif defined(AGG_BGR_AAA)
|
||||
|
||||
#include "agg_pixfmt_rgb_packed.h"
|
||||
#define pix_format agg::pix_format_bgrAAA
|
||||
typedef agg::pixfmt_bgrAAA pixfmt;
|
||||
typedef agg::pixfmt_bgrAAA_pre pixfmt_pre;
|
||||
typedef agg::rgba16 color_type;
|
||||
|
||||
#elif defined(AGG_RGB_BBA)
|
||||
|
||||
#include "agg_pixfmt_rgb_packed.h"
|
||||
#define pix_format agg::pix_format_rgbBBA
|
||||
typedef agg::pixfmt_rgbBBA pixfmt;
|
||||
typedef agg::pixfmt_rgbBBA_pre pixfmt_pre;
|
||||
typedef agg::rgba16 color_type;
|
||||
|
||||
#elif defined(AGG_BGR_ABB)
|
||||
|
||||
#include "agg_pixfmt_rgb_packed.h"
|
||||
#define pix_format agg::pix_format_bgrABB
|
||||
typedef agg::pixfmt_bgrABB pixfmt;
|
||||
typedef agg::pixfmt_bgrABB_pre pixfmt_pre;
|
||||
typedef agg::rgba16 color_type;
|
||||
|
||||
#else
|
||||
#error Please define pixel format: AGG_GRAY8, AGG_BGR24, AGG_RGB24, etc. See this file above
|
||||
#endif
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,201 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_FONT_FREETYPE_INCLUDED
|
||||
#define AGG_FONT_FREETYPE_INCLUDED
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
|
||||
#include "agg_scanline_storage_aa.h"
|
||||
#include "agg_scanline_storage_bin.h"
|
||||
#include "agg_scanline_u.h"
|
||||
#include "agg_scanline_bin.h"
|
||||
#include "agg_path_storage_integer.h"
|
||||
#include "agg_rasterizer_scanline_aa.h"
|
||||
#include "agg_conv_curve.h"
|
||||
#include "agg_font_cache_manager.h"
|
||||
#include "agg_trans_affine.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
|
||||
//-----------------------------------------------font_engine_freetype_base
|
||||
class font_engine_freetype_base
|
||||
{
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
typedef serialized_scanlines_adaptor_aa<int8u> gray8_adaptor_type;
|
||||
typedef serialized_scanlines_adaptor_bin mono_adaptor_type;
|
||||
typedef scanline_storage_aa8 scanlines_aa_type;
|
||||
typedef scanline_storage_bin scanlines_bin_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
~font_engine_freetype_base();
|
||||
font_engine_freetype_base(bool flag32, unsigned max_faces = 32);
|
||||
|
||||
// Set font parameters
|
||||
//--------------------------------------------------------------------
|
||||
void resolution(unsigned dpi);
|
||||
bool load_font(const char* font_name, unsigned face_index, glyph_rendering ren_type,
|
||||
const char* font_mem = 0, const long font_mem_size = 0);
|
||||
bool attach(const char* file_name);
|
||||
bool char_map(FT_Encoding map);
|
||||
bool height(double h);
|
||||
bool width(double w);
|
||||
void hinting(bool h);
|
||||
void flip_y(bool f);
|
||||
void transform(const trans_affine& affine);
|
||||
|
||||
// Set Gamma
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaF> void gamma(const GammaF& f)
|
||||
{
|
||||
m_rasterizer.gamma(f);
|
||||
}
|
||||
|
||||
// Accessors
|
||||
//--------------------------------------------------------------------
|
||||
int last_error() const { return m_last_error; }
|
||||
unsigned resolution() const { return m_resolution; }
|
||||
const char* name() const { return m_name; }
|
||||
unsigned num_faces() const;
|
||||
FT_Encoding char_map() const { return m_char_map; }
|
||||
double height() const { return double(m_height) / 64.0; }
|
||||
double width() const { return double(m_width) / 64.0; }
|
||||
double ascender() const;
|
||||
double descender() const;
|
||||
bool hinting() const { return m_hinting; }
|
||||
bool flip_y() const { return m_flip_y; }
|
||||
|
||||
|
||||
// Interface mandatory to implement for font_cache_manager
|
||||
//--------------------------------------------------------------------
|
||||
const char* font_signature() const { return m_signature; }
|
||||
int change_stamp() const { return m_change_stamp; }
|
||||
|
||||
bool prepare_glyph(unsigned glyph_code);
|
||||
unsigned glyph_index() const { return m_glyph_index; }
|
||||
unsigned data_size() const { return m_data_size; }
|
||||
glyph_data_type data_type() const { return m_data_type; }
|
||||
const rect_i& bounds() const { return m_bounds; }
|
||||
double advance_x() const { return m_advance_x; }
|
||||
double advance_y() const { return m_advance_y; }
|
||||
void write_glyph_to(int8u* data) const;
|
||||
bool add_kerning(unsigned first, unsigned second,
|
||||
double* x, double* y);
|
||||
|
||||
private:
|
||||
font_engine_freetype_base(const font_engine_freetype_base&);
|
||||
const font_engine_freetype_base& operator = (const font_engine_freetype_base&);
|
||||
|
||||
void update_char_size();
|
||||
void update_signature();
|
||||
int find_face(const char* face_name) const;
|
||||
|
||||
bool m_flag32;
|
||||
int m_change_stamp;
|
||||
int m_last_error;
|
||||
char* m_name;
|
||||
unsigned m_name_len;
|
||||
unsigned m_face_index;
|
||||
FT_Encoding m_char_map;
|
||||
char* m_signature;
|
||||
unsigned m_height;
|
||||
unsigned m_width;
|
||||
bool m_hinting;
|
||||
bool m_flip_y;
|
||||
bool m_library_initialized;
|
||||
FT_Library m_library; // handle to library
|
||||
FT_Face* m_faces; // A pool of font faces
|
||||
char** m_face_names;
|
||||
unsigned m_num_faces;
|
||||
unsigned m_max_faces;
|
||||
FT_Face m_cur_face; // handle to the current face object
|
||||
int m_resolution;
|
||||
glyph_rendering m_glyph_rendering;
|
||||
unsigned m_glyph_index;
|
||||
unsigned m_data_size;
|
||||
glyph_data_type m_data_type;
|
||||
rect_i m_bounds;
|
||||
double m_advance_x;
|
||||
double m_advance_y;
|
||||
trans_affine m_affine;
|
||||
|
||||
path_storage_integer<int16, 6> m_path16;
|
||||
path_storage_integer<int32, 6> m_path32;
|
||||
conv_curve<path_storage_integer<int16, 6> > m_curves16;
|
||||
conv_curve<path_storage_integer<int32, 6> > m_curves32;
|
||||
scanline_u8 m_scanline_aa;
|
||||
scanline_bin m_scanline_bin;
|
||||
scanlines_aa_type m_scanlines_aa;
|
||||
scanlines_bin_type m_scanlines_bin;
|
||||
rasterizer_scanline_aa<> m_rasterizer;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------font_engine_freetype_int16
|
||||
// This class uses values of type int16 (10.6 format) for the vector cache.
|
||||
// The vector cache is compact, but when rendering glyphs of height
|
||||
// more that 200 there integer overflow can occur.
|
||||
//
|
||||
class font_engine_freetype_int16 : public font_engine_freetype_base
|
||||
{
|
||||
public:
|
||||
typedef serialized_integer_path_adaptor<int16, 6> path_adaptor_type;
|
||||
typedef font_engine_freetype_base::gray8_adaptor_type gray8_adaptor_type;
|
||||
typedef font_engine_freetype_base::mono_adaptor_type mono_adaptor_type;
|
||||
typedef font_engine_freetype_base::scanlines_aa_type scanlines_aa_type;
|
||||
typedef font_engine_freetype_base::scanlines_bin_type scanlines_bin_type;
|
||||
|
||||
font_engine_freetype_int16(unsigned max_faces = 32) :
|
||||
font_engine_freetype_base(false, max_faces) {}
|
||||
};
|
||||
|
||||
//------------------------------------------------font_engine_freetype_int32
|
||||
// This class uses values of type int32 (26.6 format) for the vector cache.
|
||||
// The vector cache is twice larger than in font_engine_freetype_int16,
|
||||
// but it allows you to render glyphs of very large sizes.
|
||||
//
|
||||
class font_engine_freetype_int32 : public font_engine_freetype_base
|
||||
{
|
||||
public:
|
||||
typedef serialized_integer_path_adaptor<int32, 6> path_adaptor_type;
|
||||
typedef font_engine_freetype_base::gray8_adaptor_type gray8_adaptor_type;
|
||||
typedef font_engine_freetype_base::mono_adaptor_type mono_adaptor_type;
|
||||
typedef font_engine_freetype_base::scanlines_aa_type scanlines_aa_type;
|
||||
typedef font_engine_freetype_base::scanlines_bin_type scanlines_bin_type;
|
||||
|
||||
font_engine_freetype_int32(unsigned max_faces = 32) :
|
||||
font_engine_freetype_base(true, max_faces) {}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,946 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include "agg_font_win32_tt.h"
|
||||
#include "agg_bitset_iterator.h"
|
||||
#include "agg_renderer_scanline.h"
|
||||
|
||||
#ifdef AGG_WIN9X_COMPLIANT
|
||||
#define GetGlyphOutlineX GetGlyphOutline
|
||||
#else
|
||||
#define GetGlyphOutlineX GetGlyphOutlineW
|
||||
#endif
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// This code implements the AUTODIN II polynomial
|
||||
// The variable corresponding to the macro argument "crc" should
|
||||
// be an unsigned long.
|
||||
// Oroginal code by Spencer Garrett <srg@quick.com>
|
||||
//
|
||||
|
||||
// generated using the AUTODIN II polynomial
|
||||
// x^32 + x^26 + x^23 + x^22 + x^16 +
|
||||
// x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static const unsigned crc32tab[256] =
|
||||
{
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
|
||||
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
|
||||
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
|
||||
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
|
||||
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
|
||||
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
|
||||
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
|
||||
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
|
||||
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
|
||||
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
|
||||
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
|
||||
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
|
||||
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
|
||||
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
|
||||
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
|
||||
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
|
||||
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
|
||||
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
|
||||
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
|
||||
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
|
||||
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
|
||||
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
|
||||
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
|
||||
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
|
||||
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
|
||||
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
|
||||
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
|
||||
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
|
||||
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
|
||||
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
|
||||
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
|
||||
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
|
||||
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
|
||||
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
|
||||
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
|
||||
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
|
||||
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
|
||||
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
|
||||
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static unsigned calc_crc32(const unsigned char* buf, unsigned size)
|
||||
{
|
||||
unsigned crc = (unsigned)~0;
|
||||
const unsigned char* p;
|
||||
unsigned len = 0;
|
||||
unsigned nr = size;
|
||||
|
||||
for (len += nr, p = buf; nr--; ++p)
|
||||
{
|
||||
crc = (crc >> 8) ^ crc32tab[(crc ^ *p) & 0xff];
|
||||
}
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static inline FIXED dbl_to_fx(double d)
|
||||
{
|
||||
int l;
|
||||
l = int(d * 65536.0);
|
||||
return *(FIXED*)&l;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static inline int dbl_to_plain_fx(double d)
|
||||
{
|
||||
return int(d * 65536.0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static inline FIXED negate_fx(const FIXED& fx)
|
||||
{
|
||||
int l = -(*(int*)(&fx));
|
||||
return *(FIXED*)&l;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static inline double fx_to_dbl(const FIXED& p)
|
||||
{
|
||||
return double(p.value) + double(p.fract) * (1.0 / 65536.0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static inline int fx_to_plain_int(const FIXED& fx)
|
||||
{
|
||||
return *(int*)(&fx);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static inline int fx_to_int26p6(const FIXED& p)
|
||||
{
|
||||
return (int(p.value) << 6) + (int(p.fract) >> 10);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static inline int dbl_to_int26p6(double p)
|
||||
{
|
||||
return int(p * 64.0 + 0.5);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Scanline, class ScanlineStorage>
|
||||
void decompose_win32_glyph_bitmap_mono(const char* gbuf,
|
||||
int w, int h,
|
||||
int x, int y,
|
||||
bool flip_y,
|
||||
Scanline& sl,
|
||||
ScanlineStorage& storage)
|
||||
{
|
||||
int i;
|
||||
int pitch = ((w + 31) >> 5) << 2;
|
||||
const int8u* buf = (const int8u*)gbuf;
|
||||
sl.reset(x, x + w);
|
||||
storage.prepare();
|
||||
if(flip_y)
|
||||
{
|
||||
buf += pitch * (h - 1);
|
||||
y += h;
|
||||
pitch = -pitch;
|
||||
}
|
||||
for(i = 0; i < h; i++)
|
||||
{
|
||||
sl.reset_spans();
|
||||
bitset_iterator bits(buf, 0);
|
||||
int j;
|
||||
for(j = 0; j < w; j++)
|
||||
{
|
||||
if(bits.bit()) sl.add_cell(x + j, cover_full);
|
||||
++bits;
|
||||
}
|
||||
buf += pitch;
|
||||
if(sl.num_spans())
|
||||
{
|
||||
sl.finalize(y - i - 1);
|
||||
storage.render(sl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Rasterizer, class Scanline, class ScanlineStorage>
|
||||
void decompose_win32_glyph_bitmap_gray8(const char* gbuf,
|
||||
int w, int h,
|
||||
int x, int y,
|
||||
bool flip_y,
|
||||
Rasterizer& ras,
|
||||
Scanline& sl,
|
||||
ScanlineStorage& storage)
|
||||
{
|
||||
int i, j;
|
||||
int pitch = ((w + 3) >> 2) << 2;
|
||||
const int8u* buf = (const int8u*)gbuf;
|
||||
sl.reset(x, x + w);
|
||||
storage.prepare();
|
||||
if(flip_y)
|
||||
{
|
||||
buf += pitch * (h - 1);
|
||||
y += h;
|
||||
pitch = -pitch;
|
||||
}
|
||||
for(i = 0; i < h; i++)
|
||||
{
|
||||
sl.reset_spans();
|
||||
const int8u* p = buf;
|
||||
for(j = 0; j < w; j++)
|
||||
{
|
||||
if(*p)
|
||||
{
|
||||
unsigned v = *p;
|
||||
if(v == 64) v = 255;
|
||||
else v <<= 2;
|
||||
sl.add_cell(x + j, ras.apply_gamma(v));
|
||||
}
|
||||
++p;
|
||||
}
|
||||
buf += pitch;
|
||||
if(sl.num_spans())
|
||||
{
|
||||
sl.finalize(y - i - 1);
|
||||
storage.render(sl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class PathStorage>
|
||||
bool decompose_win32_glyph_outline(const char* gbuf,
|
||||
unsigned total_size,
|
||||
bool flip_y,
|
||||
const trans_affine& mtx,
|
||||
PathStorage& path)
|
||||
{
|
||||
const char* cur_glyph = gbuf;
|
||||
const char* end_glyph = gbuf + total_size;
|
||||
double x, y;
|
||||
typedef typename PathStorage::value_type value_type;
|
||||
|
||||
while(cur_glyph < end_glyph)
|
||||
{
|
||||
const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
|
||||
|
||||
const char* end_poly = cur_glyph + th->cb;
|
||||
const char* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
|
||||
|
||||
x = fx_to_dbl(th->pfxStart.x);
|
||||
y = fx_to_dbl(th->pfxStart.y);
|
||||
if(flip_y) y = -y;
|
||||
mtx.transform(&x, &y);
|
||||
path.move_to(value_type(dbl_to_int26p6(x)),
|
||||
value_type(dbl_to_int26p6(y)));
|
||||
|
||||
while(cur_poly < end_poly)
|
||||
{
|
||||
const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
|
||||
|
||||
if (pc->wType == TT_PRIM_LINE)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < pc->cpfx; i++)
|
||||
{
|
||||
x = fx_to_dbl(pc->apfx[i].x);
|
||||
y = fx_to_dbl(pc->apfx[i].y);
|
||||
if(flip_y) y = -y;
|
||||
mtx.transform(&x, &y);
|
||||
path.line_to(value_type(dbl_to_int26p6(x)),
|
||||
value_type(dbl_to_int26p6(y)));
|
||||
}
|
||||
}
|
||||
|
||||
if (pc->wType == TT_PRIM_QSPLINE)
|
||||
{
|
||||
int u;
|
||||
for (u = 0; u < pc->cpfx - 1; u++) // Walk through points in spline
|
||||
{
|
||||
POINTFX pnt_b = pc->apfx[u]; // B is always the current point
|
||||
POINTFX pnt_c = pc->apfx[u+1];
|
||||
|
||||
if (u < pc->cpfx - 2) // If not on last spline, compute C
|
||||
{
|
||||
// midpoint (x,y)
|
||||
*(int*)&pnt_c.x = (*(int*)&pnt_b.x + *(int*)&pnt_c.x) / 2;
|
||||
*(int*)&pnt_c.y = (*(int*)&pnt_b.y + *(int*)&pnt_c.y) / 2;
|
||||
}
|
||||
|
||||
double x2, y2;
|
||||
x = fx_to_dbl(pnt_b.x);
|
||||
y = fx_to_dbl(pnt_b.y);
|
||||
x2 = fx_to_dbl(pnt_c.x);
|
||||
y2 = fx_to_dbl(pnt_c.y);
|
||||
if(flip_y) { y = -y; y2 = -y2; }
|
||||
mtx.transform(&x, &y);
|
||||
mtx.transform(&x2, &y2);
|
||||
path.curve3(value_type(dbl_to_int26p6(x)),
|
||||
value_type(dbl_to_int26p6(y)),
|
||||
value_type(dbl_to_int26p6(x2)),
|
||||
value_type(dbl_to_int26p6(y2)));
|
||||
}
|
||||
}
|
||||
cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx;
|
||||
}
|
||||
cur_glyph += th->cb;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
font_engine_win32_tt_base::~font_engine_win32_tt_base()
|
||||
{
|
||||
delete [] m_kerning_pairs;
|
||||
delete [] m_gbuf;
|
||||
delete [] m_signature;
|
||||
delete [] m_typeface;
|
||||
if(m_dc && m_old_font) ::SelectObject(m_dc, m_old_font);
|
||||
unsigned i;
|
||||
for(i = 0; i < m_num_fonts; ++i)
|
||||
{
|
||||
delete [] m_font_names[i];
|
||||
::DeleteObject(m_fonts[i]);
|
||||
}
|
||||
delete [] m_font_names;
|
||||
delete [] m_fonts;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
font_engine_win32_tt_base::font_engine_win32_tt_base(bool flag32,
|
||||
HDC dc,
|
||||
unsigned max_fonts) :
|
||||
m_flag32(flag32),
|
||||
m_dc(dc),
|
||||
m_old_font(m_dc ? (HFONT)::GetCurrentObject(m_dc, OBJ_FONT) : 0),
|
||||
m_fonts(new HFONT [max_fonts]),
|
||||
m_num_fonts(0),
|
||||
m_max_fonts(max_fonts),
|
||||
m_font_names(new char* [max_fonts]),
|
||||
m_cur_font(0),
|
||||
|
||||
m_change_stamp(0),
|
||||
m_typeface(new char [256-16]),
|
||||
m_typeface_len(256-16-1),
|
||||
m_signature(new char [256+256-16]),
|
||||
m_height(0),
|
||||
m_width(0),
|
||||
m_weight(FW_REGULAR),
|
||||
m_italic(false),
|
||||
m_char_set(DEFAULT_CHARSET),
|
||||
m_pitch_and_family(FF_DONTCARE),
|
||||
m_hinting(true),
|
||||
m_flip_y(false),
|
||||
m_font_created(false),
|
||||
m_resolution(0),
|
||||
m_glyph_rendering(glyph_ren_native_gray8),
|
||||
m_glyph_index(0),
|
||||
m_data_size(0),
|
||||
m_data_type(glyph_data_invalid),
|
||||
m_bounds(1,1,0,0),
|
||||
m_advance_x(0.0),
|
||||
m_advance_y(0.0),
|
||||
m_gbuf(new char [buf_size]),
|
||||
m_kerning_pairs(0),
|
||||
m_num_kerning_pairs(0),
|
||||
m_max_kerning_pairs(0),
|
||||
|
||||
m_path16(),
|
||||
m_path32(),
|
||||
m_curves16(m_path16),
|
||||
m_curves32(m_path32),
|
||||
m_scanline_aa(),
|
||||
m_scanline_bin(),
|
||||
m_scanlines_aa(),
|
||||
m_scanlines_bin(),
|
||||
m_rasterizer()
|
||||
{
|
||||
m_curves16.approximation_scale(4.0);
|
||||
m_curves32.approximation_scale(4.0);
|
||||
memset(&m_matrix, 0, sizeof(m_matrix));
|
||||
m_matrix.eM11.value = 1;
|
||||
m_matrix.eM22.value = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
int font_engine_win32_tt_base::find_font(const char* name) const
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < m_num_fonts; ++i)
|
||||
{
|
||||
if(strcmp(name, m_font_names[i]) == 0) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool font_engine_win32_tt_base::create_font(const char* typeface_,
|
||||
glyph_rendering ren_type)
|
||||
{
|
||||
if(m_dc)
|
||||
{
|
||||
unsigned len = strlen(typeface_);
|
||||
if(len > m_typeface_len)
|
||||
{
|
||||
delete [] m_signature;
|
||||
delete [] m_typeface;
|
||||
m_typeface = new char [len + 32];
|
||||
m_signature = new char [len + 32 + 256];
|
||||
m_typeface_len = len + 32 - 1;
|
||||
}
|
||||
|
||||
strcpy(m_typeface, typeface_);
|
||||
|
||||
int h = m_height;
|
||||
int w = m_width;
|
||||
|
||||
if(m_resolution)
|
||||
{
|
||||
h = ::MulDiv(m_height, m_resolution, 72);
|
||||
w = ::MulDiv(m_width, m_resolution, 72);
|
||||
}
|
||||
|
||||
m_glyph_rendering = ren_type;
|
||||
update_signature();
|
||||
int idx = find_font(m_signature);
|
||||
if(idx >= 0)
|
||||
{
|
||||
m_cur_font = m_fonts[idx];
|
||||
::SelectObject(m_dc, m_cur_font);
|
||||
m_num_kerning_pairs = 0;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cur_font = ::CreateFont(-h, // height of font
|
||||
w, // average character width
|
||||
0, // angle of escapement
|
||||
0, // base-line orientation angle
|
||||
m_weight, // font weight
|
||||
m_italic, // italic attribute option
|
||||
0, // underline attribute option
|
||||
0, // strikeout attribute option
|
||||
m_char_set, // character set identifier
|
||||
OUT_DEFAULT_PRECIS, // output precision
|
||||
CLIP_DEFAULT_PRECIS, // clipping precision
|
||||
ANTIALIASED_QUALITY, // output quality
|
||||
m_pitch_and_family, // pitch and family
|
||||
m_typeface); // typeface name
|
||||
if(m_cur_font)
|
||||
{
|
||||
if(m_num_fonts >= m_max_fonts)
|
||||
{
|
||||
delete [] m_font_names[0];
|
||||
if(m_old_font) ::SelectObject(m_dc, m_old_font);
|
||||
::DeleteObject(m_fonts[0]);
|
||||
memcpy(m_fonts,
|
||||
m_fonts + 1,
|
||||
(m_max_fonts - 1) * sizeof(HFONT));
|
||||
memcpy(m_font_names,
|
||||
m_font_names + 1,
|
||||
(m_max_fonts - 1) * sizeof(char*));
|
||||
m_num_fonts = m_max_fonts - 1;
|
||||
}
|
||||
|
||||
update_signature();
|
||||
m_font_names[m_num_fonts] = new char[strlen(m_signature) + 1];
|
||||
strcpy(m_font_names[m_num_fonts], m_signature);
|
||||
m_fonts[m_num_fonts] = m_cur_font;
|
||||
++m_num_fonts;
|
||||
::SelectObject(m_dc, m_cur_font);
|
||||
m_num_kerning_pairs = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool font_engine_win32_tt_base::create_font(const char* typeface_,
|
||||
glyph_rendering ren_type,
|
||||
double height_,
|
||||
double width_,
|
||||
int weight_,
|
||||
bool italic_,
|
||||
DWORD char_set_,
|
||||
DWORD pitch_and_family_)
|
||||
{
|
||||
height(height_);
|
||||
width(width_);
|
||||
weight(weight_);
|
||||
italic(italic_);
|
||||
char_set(char_set_);
|
||||
pitch_and_family(pitch_and_family_);
|
||||
return create_font(typeface_, ren_type);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void font_engine_win32_tt_base::update_signature()
|
||||
{
|
||||
m_signature[0] = 0;
|
||||
if(m_dc && m_cur_font)
|
||||
{
|
||||
unsigned gamma_hash = 0;
|
||||
if(m_glyph_rendering == glyph_ren_native_gray8 ||
|
||||
m_glyph_rendering == glyph_ren_agg_mono ||
|
||||
m_glyph_rendering == glyph_ren_agg_gray8)
|
||||
{
|
||||
unsigned char gamma_table[rasterizer_scanline_aa<>::aa_scale];
|
||||
unsigned i;
|
||||
for(i = 0; i < rasterizer_scanline_aa<>::aa_scale; ++i)
|
||||
{
|
||||
gamma_table[i] = m_rasterizer.apply_gamma(i);
|
||||
}
|
||||
gamma_hash = calc_crc32(gamma_table, sizeof(gamma_table));
|
||||
}
|
||||
|
||||
sprintf(m_signature,
|
||||
"%s,%u,%d,%d:%dx%d,%d,%d,%d,%d,%d,%08X",
|
||||
m_typeface,
|
||||
m_char_set,
|
||||
int(m_glyph_rendering),
|
||||
m_resolution,
|
||||
m_height,
|
||||
m_width,
|
||||
m_weight,
|
||||
int(m_italic),
|
||||
int(m_hinting),
|
||||
int(m_flip_y),
|
||||
int(m_pitch_and_family),
|
||||
gamma_hash);
|
||||
|
||||
if(m_glyph_rendering == glyph_ren_outline ||
|
||||
m_glyph_rendering == glyph_ren_agg_mono ||
|
||||
m_glyph_rendering == glyph_ren_agg_gray8)
|
||||
{
|
||||
double mtx[6];
|
||||
char buf[100];
|
||||
m_affine.store_to(mtx);
|
||||
sprintf(buf, ",%08X%08X%08X%08X%08X%08X",
|
||||
dbl_to_plain_fx(mtx[0]),
|
||||
dbl_to_plain_fx(mtx[1]),
|
||||
dbl_to_plain_fx(mtx[2]),
|
||||
dbl_to_plain_fx(mtx[3]),
|
||||
dbl_to_plain_fx(mtx[4]),
|
||||
dbl_to_plain_fx(mtx[5]));
|
||||
strcat(m_signature, buf);
|
||||
}
|
||||
++m_change_stamp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool font_engine_win32_tt_base::prepare_glyph(unsigned glyph_code)
|
||||
{
|
||||
if(m_dc && m_cur_font)
|
||||
{
|
||||
int format = GGO_BITMAP;
|
||||
|
||||
switch(m_glyph_rendering)
|
||||
{
|
||||
case glyph_ren_native_gray8:
|
||||
format = GGO_GRAY8_BITMAP;
|
||||
break;
|
||||
|
||||
case glyph_ren_outline:
|
||||
case glyph_ren_agg_mono:
|
||||
case glyph_ren_agg_gray8:
|
||||
format = GGO_NATIVE;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef GGO_UNHINTED // For compatibility with old SDKs.
|
||||
#define GGO_UNHINTED 0x0100
|
||||
#endif
|
||||
if(!m_hinting) format |= GGO_UNHINTED;
|
||||
|
||||
GLYPHMETRICS gm;
|
||||
int total_size = GetGlyphOutlineX(m_dc,
|
||||
glyph_code,
|
||||
format,
|
||||
&gm,
|
||||
buf_size,
|
||||
(void*)m_gbuf,
|
||||
&m_matrix);
|
||||
|
||||
if(total_size < 0)
|
||||
{
|
||||
// GetGlyphOutline() fails when being called for
|
||||
// GGO_GRAY8_BITMAP and white space (stupid Microsoft).
|
||||
// It doesn't even initialize the glyph metrics
|
||||
// structure. So, we have to query the metrics
|
||||
// separately (basically we need gmCellIncX).
|
||||
int total_size = GetGlyphOutlineX(m_dc,
|
||||
glyph_code,
|
||||
GGO_METRICS,
|
||||
&gm,
|
||||
buf_size,
|
||||
(void*)m_gbuf,
|
||||
&m_matrix);
|
||||
|
||||
if(total_size < 0) return false;
|
||||
gm.gmBlackBoxX = gm.gmBlackBoxY = 0;
|
||||
total_size = 0;
|
||||
}
|
||||
|
||||
m_glyph_index = glyph_code;
|
||||
m_advance_x = gm.gmCellIncX;
|
||||
m_advance_y = -gm.gmCellIncY;
|
||||
|
||||
switch(m_glyph_rendering)
|
||||
{
|
||||
case glyph_ren_native_mono:
|
||||
decompose_win32_glyph_bitmap_mono(m_gbuf,
|
||||
gm.gmBlackBoxX,
|
||||
gm.gmBlackBoxY,
|
||||
gm.gmptGlyphOrigin.x,
|
||||
m_flip_y ? -gm.gmptGlyphOrigin.y :
|
||||
gm.gmptGlyphOrigin.y,
|
||||
m_flip_y,
|
||||
m_scanline_bin,
|
||||
m_scanlines_bin);
|
||||
m_bounds.x1 = m_scanlines_bin.min_x();
|
||||
m_bounds.y1 = m_scanlines_bin.min_y();
|
||||
m_bounds.x2 = m_scanlines_bin.max_x() + 1;
|
||||
m_bounds.y2 = m_scanlines_bin.max_y() + 1;
|
||||
m_data_size = m_scanlines_bin.byte_size();
|
||||
m_data_type = glyph_data_mono;
|
||||
return true;
|
||||
|
||||
case glyph_ren_native_gray8:
|
||||
decompose_win32_glyph_bitmap_gray8(m_gbuf,
|
||||
gm.gmBlackBoxX,
|
||||
gm.gmBlackBoxY,
|
||||
gm.gmptGlyphOrigin.x,
|
||||
m_flip_y ? -gm.gmptGlyphOrigin.y :
|
||||
gm.gmptGlyphOrigin.y,
|
||||
m_flip_y,
|
||||
m_rasterizer,
|
||||
m_scanline_aa,
|
||||
m_scanlines_aa);
|
||||
m_bounds.x1 = m_scanlines_aa.min_x();
|
||||
m_bounds.y1 = m_scanlines_aa.min_y();
|
||||
m_bounds.x2 = m_scanlines_aa.max_x() + 1;
|
||||
m_bounds.y2 = m_scanlines_aa.max_y() + 1;
|
||||
m_data_size = m_scanlines_aa.byte_size();
|
||||
m_data_type = glyph_data_gray8;
|
||||
return true;
|
||||
|
||||
case glyph_ren_outline:
|
||||
m_affine.transform(&m_advance_x, &m_advance_y);
|
||||
if(m_flag32)
|
||||
{
|
||||
m_path32.remove_all();
|
||||
if(decompose_win32_glyph_outline(m_gbuf,
|
||||
total_size,
|
||||
m_flip_y,
|
||||
m_affine,
|
||||
m_path32))
|
||||
{
|
||||
rect_d bnd = m_path32.bounding_rect();
|
||||
m_data_size = m_path32.byte_size();
|
||||
m_data_type = glyph_data_outline;
|
||||
m_bounds.x1 = int(floor(bnd.x1));
|
||||
m_bounds.y1 = int(floor(bnd.y1));
|
||||
m_bounds.x2 = int(ceil(bnd.x2));
|
||||
m_bounds.y2 = int(ceil(bnd.y2));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_path16.remove_all();
|
||||
if(decompose_win32_glyph_outline(m_gbuf,
|
||||
total_size,
|
||||
m_flip_y,
|
||||
m_affine,
|
||||
m_path16))
|
||||
{
|
||||
rect_d bnd = m_path16.bounding_rect();
|
||||
m_data_size = m_path16.byte_size();
|
||||
m_data_type = glyph_data_outline;
|
||||
m_bounds.x1 = int(floor(bnd.x1));
|
||||
m_bounds.y1 = int(floor(bnd.y1));
|
||||
m_bounds.x2 = int(ceil(bnd.x2));
|
||||
m_bounds.y2 = int(ceil(bnd.y2));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case glyph_ren_agg_mono:
|
||||
m_rasterizer.reset();
|
||||
m_affine.transform(&m_advance_x, &m_advance_y);
|
||||
if(m_flag32)
|
||||
{
|
||||
m_path32.remove_all();
|
||||
decompose_win32_glyph_outline(m_gbuf,
|
||||
total_size,
|
||||
m_flip_y,
|
||||
m_affine,
|
||||
m_path32);
|
||||
m_rasterizer.add_path(m_curves32);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_path16.remove_all();
|
||||
decompose_win32_glyph_outline(m_gbuf,
|
||||
total_size,
|
||||
m_flip_y,
|
||||
m_affine,
|
||||
m_path16);
|
||||
m_rasterizer.add_path(m_curves16);
|
||||
}
|
||||
m_scanlines_bin.prepare(); // Remove all
|
||||
render_scanlines(m_rasterizer, m_scanline_bin, m_scanlines_bin);
|
||||
m_bounds.x1 = m_scanlines_bin.min_x();
|
||||
m_bounds.y1 = m_scanlines_bin.min_y();
|
||||
m_bounds.x2 = m_scanlines_bin.max_x() + 1;
|
||||
m_bounds.y2 = m_scanlines_bin.max_y() + 1;
|
||||
m_data_size = m_scanlines_bin.byte_size();
|
||||
m_data_type = glyph_data_mono;
|
||||
return true;
|
||||
|
||||
case glyph_ren_agg_gray8:
|
||||
m_rasterizer.reset();
|
||||
m_affine.transform(&m_advance_x, &m_advance_y);
|
||||
if(m_flag32)
|
||||
{
|
||||
m_path32.remove_all();
|
||||
decompose_win32_glyph_outline(m_gbuf,
|
||||
total_size,
|
||||
m_flip_y,
|
||||
m_affine,
|
||||
m_path32);
|
||||
m_rasterizer.add_path(m_curves32);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_path16.remove_all();
|
||||
decompose_win32_glyph_outline(m_gbuf,
|
||||
total_size,
|
||||
m_flip_y,
|
||||
m_affine,
|
||||
m_path16);
|
||||
m_rasterizer.add_path(m_curves16);
|
||||
}
|
||||
m_scanlines_aa.prepare(); // Remove all
|
||||
render_scanlines(m_rasterizer, m_scanline_aa, m_scanlines_aa);
|
||||
m_bounds.x1 = m_scanlines_aa.min_x();
|
||||
m_bounds.y1 = m_scanlines_aa.min_y();
|
||||
m_bounds.x2 = m_scanlines_aa.max_x() + 1;
|
||||
m_bounds.y2 = m_scanlines_aa.max_y() + 1;
|
||||
m_data_size = m_scanlines_aa.byte_size();
|
||||
m_data_type = glyph_data_gray8;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void font_engine_win32_tt_base::write_glyph_to(int8u* data) const
|
||||
{
|
||||
if(data && m_data_size)
|
||||
{
|
||||
switch(m_data_type)
|
||||
{
|
||||
case glyph_data_mono: m_scanlines_bin.serialize(data); break;
|
||||
case glyph_data_gray8: m_scanlines_aa.serialize(data); break;
|
||||
case glyph_data_outline:
|
||||
if(m_flag32)
|
||||
{
|
||||
m_path32.serialize(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_path16.serialize(data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static bool pair_less(const KERNINGPAIR& v1, const KERNINGPAIR& v2)
|
||||
{
|
||||
if(v1.wFirst != v2.wFirst) return v1.wFirst < v2.wFirst;
|
||||
return v1.wSecond < v2.wSecond;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void font_engine_win32_tt_base::sort_kerning_pairs()
|
||||
{
|
||||
pod_array_adaptor<KERNINGPAIR> pairs(m_kerning_pairs, m_num_kerning_pairs);
|
||||
quick_sort(pairs, pair_less);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void font_engine_win32_tt_base::load_kerning_pairs()
|
||||
{
|
||||
if(m_dc && m_cur_font)
|
||||
{
|
||||
if(m_kerning_pairs == 0)
|
||||
{
|
||||
m_kerning_pairs = new KERNINGPAIR [16384-16];
|
||||
m_max_kerning_pairs = 16384-16;
|
||||
}
|
||||
m_num_kerning_pairs = ::GetKerningPairs(m_dc,
|
||||
m_max_kerning_pairs,
|
||||
m_kerning_pairs);
|
||||
|
||||
if(m_num_kerning_pairs)
|
||||
{
|
||||
// Check to see if the kerning pairs are sorted and
|
||||
// sort them if they are not.
|
||||
//----------------
|
||||
unsigned i;
|
||||
for(i = 1; i < m_num_kerning_pairs; ++i)
|
||||
{
|
||||
if(!pair_less(m_kerning_pairs[i - 1], m_kerning_pairs[i]))
|
||||
{
|
||||
sort_kerning_pairs();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool font_engine_win32_tt_base::add_kerning(unsigned first, unsigned second,
|
||||
double* x, double* y)
|
||||
{
|
||||
if(m_dc && m_cur_font)
|
||||
{
|
||||
if(m_num_kerning_pairs == 0)
|
||||
{
|
||||
load_kerning_pairs();
|
||||
}
|
||||
|
||||
int end = m_num_kerning_pairs - 1;
|
||||
int beg = 0;
|
||||
KERNINGPAIR t;
|
||||
t.wFirst = (WORD)first;
|
||||
t.wSecond = (WORD)second;
|
||||
while(beg <= end)
|
||||
{
|
||||
int mid = (end + beg) / 2;
|
||||
if(m_kerning_pairs[mid].wFirst == t.wFirst &&
|
||||
m_kerning_pairs[mid].wSecond == t.wSecond)
|
||||
{
|
||||
double dx = m_kerning_pairs[mid].iKernAmount;
|
||||
double dy = 0.0;
|
||||
if(m_glyph_rendering == glyph_ren_outline ||
|
||||
m_glyph_rendering == glyph_ren_agg_mono ||
|
||||
m_glyph_rendering == glyph_ren_agg_gray8)
|
||||
{
|
||||
m_affine.transform_2x2(&dx, &dy);
|
||||
}
|
||||
*x += dx;
|
||||
*y += dy;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if(pair_less(t, m_kerning_pairs[mid]))
|
||||
{
|
||||
end = mid - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
beg = mid + 1;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_FONT_WIN32_TT_INCLUDED
|
||||
#define AGG_FONT_WIN32_TT_INCLUDED
|
||||
|
||||
#include <windows.h>
|
||||
#include "agg_scanline_storage_aa.h"
|
||||
#include "agg_scanline_storage_bin.h"
|
||||
#include "agg_scanline_u.h"
|
||||
#include "agg_scanline_bin.h"
|
||||
#include "agg_path_storage_integer.h"
|
||||
#include "agg_rasterizer_scanline_aa.h"
|
||||
#include "agg_conv_curve.h"
|
||||
#include "agg_trans_affine.h"
|
||||
#include "agg_font_cache_manager.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-----------------------------------------------font_engine_win32_tt_base
|
||||
class font_engine_win32_tt_base
|
||||
{
|
||||
enum { buf_size = 32768-32 };
|
||||
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
typedef serialized_scanlines_adaptor_aa<int8u> gray8_adaptor_type;
|
||||
typedef serialized_scanlines_adaptor_bin mono_adaptor_type;
|
||||
typedef scanline_storage_aa8 scanlines_aa_type;
|
||||
typedef scanline_storage_bin scanlines_bin_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
~font_engine_win32_tt_base();
|
||||
font_engine_win32_tt_base(bool flag32, HDC dc, unsigned max_fonts = 32);
|
||||
|
||||
// Set font parameters
|
||||
//--------------------------------------------------------------------
|
||||
void resolution(unsigned dpi) { m_resolution = unsigned(dpi); }
|
||||
void height(double h) { m_height = unsigned(h); }
|
||||
void width(double w) { m_width = unsigned(w); }
|
||||
void weight(int w) { m_weight = w; }
|
||||
void italic(bool it) { m_italic = it; }
|
||||
void char_set(DWORD c) { m_char_set = c; }
|
||||
void pitch_and_family(DWORD p){ m_pitch_and_family = p; }
|
||||
void flip_y(bool flip) { m_flip_y = flip; }
|
||||
void hinting(bool h) { m_hinting = h; }
|
||||
bool create_font(const char* typeface_, glyph_rendering ren_type);
|
||||
|
||||
bool create_font(const char* typeface_,
|
||||
glyph_rendering ren_type,
|
||||
double height_,
|
||||
double width_=0.0,
|
||||
int weight_=FW_REGULAR,
|
||||
bool italic_=false,
|
||||
DWORD char_set_=ANSI_CHARSET,
|
||||
DWORD pitch_and_family_=FF_DONTCARE);
|
||||
|
||||
// Set Gamma
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaF> void gamma(const GammaF& f)
|
||||
{
|
||||
m_rasterizer.gamma(f);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void transform(const agg::trans_affine& mtx)
|
||||
{
|
||||
m_affine = mtx;
|
||||
}
|
||||
|
||||
// Accessors
|
||||
//--------------------------------------------------------------------
|
||||
unsigned resolution() const { return m_resolution; }
|
||||
const char* typeface() const { return m_typeface; }
|
||||
double height() const { return m_height; }
|
||||
double width() const { return m_width; }
|
||||
int weight() const { return m_weight; }
|
||||
bool italic() const { return m_italic; }
|
||||
DWORD char_set() const { return m_char_set; }
|
||||
DWORD pitch_and_family() const { return m_pitch_and_family; }
|
||||
bool hinting() const { return m_hinting; }
|
||||
bool flip_y() const { return m_flip_y; }
|
||||
|
||||
|
||||
// Interface mandatory to implement for font_cache_manager
|
||||
//--------------------------------------------------------------------
|
||||
const char* font_signature() const { return m_signature; }
|
||||
int change_stamp() const { return m_change_stamp; }
|
||||
|
||||
bool prepare_glyph(unsigned glyph_code);
|
||||
unsigned glyph_index() const { return m_glyph_index; }
|
||||
unsigned data_size() const { return m_data_size; }
|
||||
glyph_data_type data_type() const { return m_data_type; }
|
||||
const rect_i& bounds() const { return m_bounds; }
|
||||
double advance_x() const { return m_advance_x; }
|
||||
double advance_y() const { return m_advance_y; }
|
||||
void write_glyph_to(int8u* data) const;
|
||||
bool add_kerning(unsigned first, unsigned second,
|
||||
double* x, double* y);
|
||||
|
||||
private:
|
||||
font_engine_win32_tt_base(const font_engine_win32_tt_base&);
|
||||
const font_engine_win32_tt_base& operator = (const font_engine_win32_tt_base&);
|
||||
|
||||
void update_signature();
|
||||
void load_kerning_pairs();
|
||||
void sort_kerning_pairs();
|
||||
int find_font(const char* name) const;
|
||||
|
||||
bool m_flag32;
|
||||
HDC m_dc;
|
||||
HFONT m_old_font;
|
||||
HFONT* m_fonts;
|
||||
unsigned m_num_fonts;
|
||||
unsigned m_max_fonts;
|
||||
char** m_font_names;
|
||||
HFONT m_cur_font;
|
||||
|
||||
int m_change_stamp;
|
||||
char* m_typeface;
|
||||
unsigned m_typeface_len;
|
||||
char* m_signature;
|
||||
unsigned m_height;
|
||||
unsigned m_width;
|
||||
int m_weight;
|
||||
bool m_italic;
|
||||
DWORD m_char_set;
|
||||
DWORD m_pitch_and_family;
|
||||
bool m_hinting;
|
||||
bool m_flip_y;
|
||||
|
||||
bool m_font_created;
|
||||
unsigned m_resolution;
|
||||
glyph_rendering m_glyph_rendering;
|
||||
unsigned m_glyph_index;
|
||||
unsigned m_data_size;
|
||||
glyph_data_type m_data_type;
|
||||
rect_i m_bounds;
|
||||
double m_advance_x;
|
||||
double m_advance_y;
|
||||
MAT2 m_matrix;
|
||||
char* m_gbuf;
|
||||
KERNINGPAIR* m_kerning_pairs;
|
||||
unsigned m_num_kerning_pairs;
|
||||
unsigned m_max_kerning_pairs;
|
||||
trans_affine m_affine;
|
||||
|
||||
path_storage_integer<int16, 6> m_path16;
|
||||
path_storage_integer<int32, 6> m_path32;
|
||||
conv_curve<path_storage_integer<int16, 6> > m_curves16;
|
||||
conv_curve<path_storage_integer<int32, 6> > m_curves32;
|
||||
scanline_u8 m_scanline_aa;
|
||||
scanline_bin m_scanline_bin;
|
||||
scanlines_aa_type m_scanlines_aa;
|
||||
scanlines_bin_type m_scanlines_bin;
|
||||
rasterizer_scanline_aa<> m_rasterizer;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------font_engine_win32_tt_int16
|
||||
// This class uses values of type int16 (10.6 format) for the vector cache.
|
||||
// The vector cache is compact, but when rendering glyphs of height
|
||||
// more that 200 there integer overflow can occur.
|
||||
//
|
||||
class font_engine_win32_tt_int16 : public font_engine_win32_tt_base
|
||||
{
|
||||
public:
|
||||
typedef serialized_integer_path_adaptor<int16, 6> path_adaptor_type;
|
||||
typedef font_engine_win32_tt_base::gray8_adaptor_type gray8_adaptor_type;
|
||||
typedef font_engine_win32_tt_base::mono_adaptor_type mono_adaptor_type;
|
||||
typedef font_engine_win32_tt_base::scanlines_aa_type scanlines_aa_type;
|
||||
typedef font_engine_win32_tt_base::scanlines_bin_type scanlines_bin_type;
|
||||
|
||||
font_engine_win32_tt_int16(HDC dc, unsigned max_fonts = 32) :
|
||||
font_engine_win32_tt_base(false, dc, max_fonts) {}
|
||||
};
|
||||
|
||||
//------------------------------------------------font_engine_win32_tt_int32
|
||||
// This class uses values of type int32 (26.6 format) for the vector cache.
|
||||
// The vector cache is twice larger than in font_engine_win32_tt_int16,
|
||||
// but it allows you to render glyphs of very large sizes.
|
||||
//
|
||||
class font_engine_win32_tt_int32 : public font_engine_win32_tt_base
|
||||
{
|
||||
public:
|
||||
typedef serialized_integer_path_adaptor<int32, 6> path_adaptor_type;
|
||||
typedef font_engine_win32_tt_base::gray8_adaptor_type gray8_adaptor_type;
|
||||
typedef font_engine_win32_tt_base::mono_adaptor_type mono_adaptor_type;
|
||||
typedef font_engine_win32_tt_base::scanlines_aa_type scanlines_aa_type;
|
||||
typedef font_engine_win32_tt_base::scanlines_bin_type scanlines_bin_type;
|
||||
|
||||
font_engine_win32_tt_int32(HDC dc, unsigned max_fonts = 32) :
|
||||
font_engine_win32_tt_base(true, dc, max_fonts) {}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,123 @@
|
|||
|
||||
Generic Polygon Clipper (gpc) Revision History
|
||||
==============================================
|
||||
|
||||
|
||||
v2.32 17th Dec 2004
|
||||
---------------------
|
||||
Fixed occasional memory leak occurring when processing some
|
||||
degenerate polygon arrangements.
|
||||
Added explicit type casting to memory allocator in support of
|
||||
increased code portability.
|
||||
|
||||
v2.31 4th Jun 1999
|
||||
---------------------
|
||||
Separated edge merging measure based on a user-defined GPC_EPSILON
|
||||
value from general numeric equality testing and ordering, which now
|
||||
uses direct arithmetic comparison rather an EPSILON based proximity
|
||||
test.
|
||||
Fixed problem with numerical equality test during construction of
|
||||
local minima and scanbeam tables, leading to occasional crash.
|
||||
Fixed hole array memory leak in gpc_add_contour.
|
||||
Fixed uninitialised hole field bug in gpc_polygon_clip result.
|
||||
|
||||
v2.30 11th Apr 1999
|
||||
---------------------
|
||||
Major re-write.
|
||||
Minor API change: additional 'hole' array field added to gpc_polygon
|
||||
datatype to indicate which constituent contours are internal holes,
|
||||
and which form external boundaries.
|
||||
Minor API change: additional 'hole' argument to gpc_add_contour
|
||||
to indicate whether the new contour is a hole or external contour.
|
||||
Minor API change: additional parameter to gpc_read_polygon and
|
||||
gpc_write_polygon to indicate whether or not to read or write
|
||||
contour hole flags.
|
||||
Fixed NULL pointer bug in add/merge left/right operations.
|
||||
Fixed numerical problem in intersection table generation.
|
||||
Fixed zero byte malloc problem.
|
||||
Fixed problem producing occasional 2 vertex contours.
|
||||
Added bounding box test optimisations.
|
||||
Simplified edge bundle creation, detection of scanbeam internal
|
||||
edge intersections and tristrip scanbeam boundary code.
|
||||
Renamed 'class' variable to be C++ friendly.
|
||||
|
||||
v2.22 17th Oct 1998
|
||||
---------------------
|
||||
Re-implemented edge interpolation and intersection calculations
|
||||
to improve numerical robustness.
|
||||
Simplified setting of GPC_EPSILON.
|
||||
|
||||
v2.21 19th Aug 1998
|
||||
---------------------
|
||||
Fixed problem causing occasional incorrect output when processing
|
||||
self-intersecting polygons (bow-ties etc).
|
||||
Removed bug which may lead to non-generation of uppermost triangle
|
||||
in tristrip output.
|
||||
|
||||
v2.20 26th May 1998
|
||||
---------------------
|
||||
Major re-write.
|
||||
Added exclusive-or polygon set operation.
|
||||
Replaced table-based processing of edge intersections with
|
||||
rule-based system.
|
||||
Replaced two-pass approach to scanbeam interior processing with
|
||||
single pass method.
|
||||
|
||||
v2.10a 14th May 1998
|
||||
---------------------
|
||||
Minor bug-fixes to counter some v2.10 reliability problems.
|
||||
|
||||
v2.10 11th May 1998
|
||||
---------------------
|
||||
Major re-write.
|
||||
Incorporated edge bundle processing of AET to overcome coincident
|
||||
edge problems present in previous releases.
|
||||
Replaced Vatti's method for processing scanbeam interior regions
|
||||
with an adapted version of the scanbeam boundary processing
|
||||
algorithm.
|
||||
|
||||
v2.02 16th Apr 1998 (unreleased)
|
||||
----------------------------------
|
||||
Fixed internal minimum vertex duplication in gpc_polygon_clip
|
||||
result.
|
||||
Improved line intersection code discourage superfluous
|
||||
intersections near line ends.
|
||||
Removed limited precision number formatting in gpc_write_polygon.
|
||||
Modification to allow subject or clip polygon to be reused as the
|
||||
result in gpc_polygon_clip without memory leakage.
|
||||
|
||||
v2.01 23rd Feb 1998
|
||||
---------------------
|
||||
Removed bug causing duplicated vertices in output polygon.
|
||||
Fixed scanbeam table index overrun problem.
|
||||
|
||||
v2.00 25th Nov 1997
|
||||
---------------------
|
||||
Major re-write.
|
||||
Replaced temporary horizontal edge work-around (using tilting)
|
||||
with true horizontal edge handling.
|
||||
Trapezoidal output replaced by tristrips.
|
||||
gpc_op constants now feature a `GPC_' prefix.
|
||||
Data structures now passed by reference to gpc functions.
|
||||
Replaced AET search by proxy addressing in polygon table.
|
||||
Eliminated most (all?) coincident vertex / edge crashes.
|
||||
|
||||
v1.02 18th Oct 1997 (unreleased)
|
||||
----------------------------------
|
||||
Significantly reduced number of mallocs in build_lmt.
|
||||
Scanbeam table now built using heapsort rather than insertion
|
||||
sort.
|
||||
|
||||
v1.01 12th Oct 1997
|
||||
---------------------
|
||||
Fixed memory leak during output polygon build in
|
||||
gpc_clip_polygon.
|
||||
Removed superfluous logfile debug code.
|
||||
Commented out malloc counts.
|
||||
Added missing horizontal edge tilt-correction code in
|
||||
gpc_clip_polygon.
|
||||
|
||||
v1.00 8th Oct 1997
|
||||
--------------------
|
||||
First release.
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
http://www.cs.man.ac.uk/aig/staff/alan/software/
|
||||
|
||||
Author: Alan Murta (email: gpc@cs.man.ac.uk)
|
||||
Version: 2.31
|
||||
Date: 4th June 1999
|
||||
|
||||
Copyright: (C) 1997-1999, Advanced Interfaces Group,
|
||||
University of Manchester.
|
||||
|
||||
This software is free for non-commercial use. It may be copied,
|
||||
modified, and redistributed provided that this copyright notice
|
||||
is preserved on all copies. The intellectual property rights of
|
||||
the algorithms used reside with the University of Manchester
|
||||
Advanced Interfaces Group.
|
||||
|
||||
You may not use this software, in whole or in part, in support
|
||||
of any commercial product without the express consent of the
|
||||
author.
|
||||
|
||||
There is no warranty or other guarantee of fitness of this
|
||||
software for any purpose. It is provided solely "as is".
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
===========================================================================
|
||||
|
||||
Project: Generic Polygon Clipper
|
||||
|
||||
A new algorithm for calculating the difference, intersection,
|
||||
exclusive-or or union of arbitrary polygon sets.
|
||||
|
||||
File: gpc.h
|
||||
Author: Alan Murta (email: gpc@cs.man.ac.uk)
|
||||
Version: 2.32
|
||||
Date: 17th December 2004
|
||||
|
||||
Copyright: (C) 1997-2004, Advanced Interfaces Group,
|
||||
University of Manchester.
|
||||
|
||||
This software is free for non-commercial use. It may be copied,
|
||||
modified, and redistributed provided that this copyright notice
|
||||
is preserved on all copies. The intellectual property rights of
|
||||
the algorithms used reside with the University of Manchester
|
||||
Advanced Interfaces Group.
|
||||
|
||||
You may not use this software, in whole or in part, in support
|
||||
of any commercial product without the express consent of the
|
||||
author.
|
||||
|
||||
There is no warranty or other guarantee of fitness of this
|
||||
software for any purpose. It is provided solely "as is".
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#ifndef __gpc_h
|
||||
#define __gpc_h
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
/*
|
||||
===========================================================================
|
||||
Constants
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
/* Increase GPC_EPSILON to encourage merging of near coincident edges */
|
||||
|
||||
#define GPC_EPSILON (DBL_EPSILON)
|
||||
|
||||
#define GPC_VERSION "2.32"
|
||||
|
||||
|
||||
/*
|
||||
===========================================================================
|
||||
Public Data Types
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
typedef enum /* Set operation type */
|
||||
{
|
||||
GPC_DIFF, /* Difference */
|
||||
GPC_INT, /* Intersection */
|
||||
GPC_XOR, /* Exclusive or */
|
||||
GPC_UNION /* Union */
|
||||
} gpc_op;
|
||||
|
||||
typedef struct /* Polygon vertex structure */
|
||||
{
|
||||
double x; /* Vertex x component */
|
||||
double y; /* vertex y component */
|
||||
} gpc_vertex;
|
||||
|
||||
typedef struct /* Vertex list structure */
|
||||
{
|
||||
int num_vertices; /* Number of vertices in list */
|
||||
gpc_vertex *vertex; /* Vertex array pointer */
|
||||
} gpc_vertex_list;
|
||||
|
||||
typedef struct /* Polygon set structure */
|
||||
{
|
||||
int num_contours; /* Number of contours in polygon */
|
||||
int *hole; /* Hole / external contour flags */
|
||||
gpc_vertex_list *contour; /* Contour array pointer */
|
||||
} gpc_polygon;
|
||||
|
||||
typedef struct /* Tristrip set structure */
|
||||
{
|
||||
int num_strips; /* Number of tristrips */
|
||||
gpc_vertex_list *strip; /* Tristrip array pointer */
|
||||
} gpc_tristrip;
|
||||
|
||||
|
||||
/*
|
||||
===========================================================================
|
||||
Public Function Prototypes
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
void gpc_read_polygon (FILE *infile_ptr,
|
||||
int read_hole_flags,
|
||||
gpc_polygon *polygon);
|
||||
|
||||
void gpc_write_polygon (FILE *outfile_ptr,
|
||||
int write_hole_flags,
|
||||
gpc_polygon *polygon);
|
||||
|
||||
void gpc_add_contour (gpc_polygon *polygon,
|
||||
gpc_vertex_list *contour,
|
||||
int hole);
|
||||
|
||||
void gpc_polygon_clip (gpc_op set_operation,
|
||||
gpc_polygon *subject_polygon,
|
||||
gpc_polygon *clip_polygon,
|
||||
gpc_polygon *result_polygon);
|
||||
|
||||
void gpc_tristrip_clip (gpc_op set_operation,
|
||||
gpc_polygon *subject_polygon,
|
||||
gpc_polygon *clip_polygon,
|
||||
gpc_tristrip *result_tristrip);
|
||||
|
||||
void gpc_polygon_to_tristrip (gpc_polygon *polygon,
|
||||
gpc_tristrip *tristrip);
|
||||
|
||||
void gpc_free_polygon (gpc_polygon *polygon);
|
||||
|
||||
void gpc_free_tristrip (gpc_tristrip *tristrip);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
===========================================================================
|
||||
End of file: gpc.h
|
||||
===========================================================================
|
||||
*/
|
|
@ -0,0 +1,505 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_ALPHA_MASK_U8_INCLUDED
|
||||
#define AGG_ALPHA_MASK_U8_INCLUDED
|
||||
|
||||
#include <string.h>
|
||||
#include "agg_basics.h"
|
||||
#include "agg_rendering_buffer.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//===================================================one_component_mask_u8
|
||||
struct one_component_mask_u8
|
||||
{
|
||||
static unsigned calculate(const int8u* p) { return *p; }
|
||||
};
|
||||
|
||||
|
||||
//=====================================================rgb_to_gray_mask_u8
|
||||
template<unsigned R, unsigned G, unsigned B>
|
||||
struct rgb_to_gray_mask_u8
|
||||
{
|
||||
static unsigned calculate(const int8u* p)
|
||||
{
|
||||
return (p[R]*77 + p[G]*150 + p[B]*29) >> 8;
|
||||
}
|
||||
};
|
||||
|
||||
//==========================================================alpha_mask_u8
|
||||
template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8>
|
||||
class alpha_mask_u8
|
||||
{
|
||||
public:
|
||||
typedef int8u cover_type;
|
||||
typedef alpha_mask_u8<Step, Offset, MaskF> self_type;
|
||||
enum cover_scale_e
|
||||
{
|
||||
cover_shift = 8,
|
||||
cover_none = 0,
|
||||
cover_full = 255
|
||||
};
|
||||
|
||||
alpha_mask_u8() : m_rbuf(0) {}
|
||||
explicit alpha_mask_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
|
||||
|
||||
void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; }
|
||||
|
||||
MaskF& mask_function() { return m_mask_function; }
|
||||
const MaskF& mask_function() const { return m_mask_function; }
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
cover_type pixel(int x, int y) const
|
||||
{
|
||||
if(x >= 0 && y >= 0 &&
|
||||
x < (int)m_rbuf->width() &&
|
||||
y < (int)m_rbuf->height())
|
||||
{
|
||||
return (cover_type)m_mask_function.calculate(
|
||||
m_rbuf->row_ptr(y) + x * Step + Offset);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
cover_type combine_pixel(int x, int y, cover_type val) const
|
||||
{
|
||||
if(x >= 0 && y >= 0 &&
|
||||
x < (int)m_rbuf->width() &&
|
||||
y < (int)m_rbuf->height())
|
||||
{
|
||||
return (cover_type)((cover_full + val *
|
||||
m_mask_function.calculate(
|
||||
m_rbuf->row_ptr(y) + x * Step + Offset)) >>
|
||||
cover_shift);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void fill_hspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
int xmax = m_rbuf->width() - 1;
|
||||
int ymax = m_rbuf->height() - 1;
|
||||
|
||||
int count = num_pix;
|
||||
cover_type* covers = dst;
|
||||
|
||||
if(y < 0 || y > ymax)
|
||||
{
|
||||
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
|
||||
if(x < 0)
|
||||
{
|
||||
count += x;
|
||||
if(count <= 0)
|
||||
{
|
||||
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
memset(covers, 0, -x * sizeof(cover_type));
|
||||
covers -= x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
if(x + count > xmax)
|
||||
{
|
||||
int rest = x + count - xmax - 1;
|
||||
count -= rest;
|
||||
if(count <= 0)
|
||||
{
|
||||
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
memset(covers + count, 0, rest * sizeof(cover_type));
|
||||
}
|
||||
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
do
|
||||
{
|
||||
*covers++ = (cover_type)m_mask_function.calculate(mask);
|
||||
mask += Step;
|
||||
}
|
||||
while(--count);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
int xmax = m_rbuf->width() - 1;
|
||||
int ymax = m_rbuf->height() - 1;
|
||||
|
||||
int count = num_pix;
|
||||
cover_type* covers = dst;
|
||||
|
||||
if(y < 0 || y > ymax)
|
||||
{
|
||||
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
|
||||
if(x < 0)
|
||||
{
|
||||
count += x;
|
||||
if(count <= 0)
|
||||
{
|
||||
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
memset(covers, 0, -x * sizeof(cover_type));
|
||||
covers -= x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
if(x + count > xmax)
|
||||
{
|
||||
int rest = x + count - xmax - 1;
|
||||
count -= rest;
|
||||
if(count <= 0)
|
||||
{
|
||||
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
memset(covers + count, 0, rest * sizeof(cover_type));
|
||||
}
|
||||
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
do
|
||||
{
|
||||
*covers = (cover_type)((cover_full + (*covers) *
|
||||
m_mask_function.calculate(mask)) >>
|
||||
cover_shift);
|
||||
++covers;
|
||||
mask += Step;
|
||||
}
|
||||
while(--count);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void fill_vspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
int xmax = m_rbuf->width() - 1;
|
||||
int ymax = m_rbuf->height() - 1;
|
||||
|
||||
int count = num_pix;
|
||||
cover_type* covers = dst;
|
||||
|
||||
if(x < 0 || x > xmax)
|
||||
{
|
||||
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
|
||||
if(y < 0)
|
||||
{
|
||||
count += y;
|
||||
if(count <= 0)
|
||||
{
|
||||
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
memset(covers, 0, -y * sizeof(cover_type));
|
||||
covers -= y;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
if(y + count > ymax)
|
||||
{
|
||||
int rest = y + count - ymax - 1;
|
||||
count -= rest;
|
||||
if(count <= 0)
|
||||
{
|
||||
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
memset(covers + count, 0, rest * sizeof(cover_type));
|
||||
}
|
||||
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
do
|
||||
{
|
||||
*covers++ = (cover_type)m_mask_function.calculate(mask);
|
||||
mask += m_rbuf->stride();
|
||||
}
|
||||
while(--count);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void combine_vspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
int xmax = m_rbuf->width() - 1;
|
||||
int ymax = m_rbuf->height() - 1;
|
||||
|
||||
int count = num_pix;
|
||||
cover_type* covers = dst;
|
||||
|
||||
if(x < 0 || x > xmax)
|
||||
{
|
||||
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
|
||||
if(y < 0)
|
||||
{
|
||||
count += y;
|
||||
if(count <= 0)
|
||||
{
|
||||
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
memset(covers, 0, -y * sizeof(cover_type));
|
||||
covers -= y;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
if(y + count > ymax)
|
||||
{
|
||||
int rest = y + count - ymax - 1;
|
||||
count -= rest;
|
||||
if(count <= 0)
|
||||
{
|
||||
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
memset(covers + count, 0, rest * sizeof(cover_type));
|
||||
}
|
||||
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
do
|
||||
{
|
||||
*covers = (cover_type)((cover_full + (*covers) *
|
||||
m_mask_function.calculate(mask)) >>
|
||||
cover_shift);
|
||||
++covers;
|
||||
mask += m_rbuf->stride();
|
||||
}
|
||||
while(--count);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
alpha_mask_u8(const self_type&);
|
||||
const self_type& operator = (const self_type&);
|
||||
|
||||
rendering_buffer* m_rbuf;
|
||||
MaskF m_mask_function;
|
||||
};
|
||||
|
||||
|
||||
typedef alpha_mask_u8<1, 0> alpha_mask_gray8; //----alpha_mask_gray8
|
||||
|
||||
typedef alpha_mask_u8<3, 0> alpha_mask_rgb24r; //----alpha_mask_rgb24r
|
||||
typedef alpha_mask_u8<3, 1> alpha_mask_rgb24g; //----alpha_mask_rgb24g
|
||||
typedef alpha_mask_u8<3, 2> alpha_mask_rgb24b; //----alpha_mask_rgb24b
|
||||
|
||||
typedef alpha_mask_u8<3, 2> alpha_mask_bgr24r; //----alpha_mask_bgr24r
|
||||
typedef alpha_mask_u8<3, 1> alpha_mask_bgr24g; //----alpha_mask_bgr24g
|
||||
typedef alpha_mask_u8<3, 0> alpha_mask_bgr24b; //----alpha_mask_bgr24b
|
||||
|
||||
typedef alpha_mask_u8<4, 0> alpha_mask_rgba32r; //----alpha_mask_rgba32r
|
||||
typedef alpha_mask_u8<4, 1> alpha_mask_rgba32g; //----alpha_mask_rgba32g
|
||||
typedef alpha_mask_u8<4, 2> alpha_mask_rgba32b; //----alpha_mask_rgba32b
|
||||
typedef alpha_mask_u8<4, 3> alpha_mask_rgba32a; //----alpha_mask_rgba32a
|
||||
|
||||
typedef alpha_mask_u8<4, 1> alpha_mask_argb32r; //----alpha_mask_argb32r
|
||||
typedef alpha_mask_u8<4, 2> alpha_mask_argb32g; //----alpha_mask_argb32g
|
||||
typedef alpha_mask_u8<4, 3> alpha_mask_argb32b; //----alpha_mask_argb32b
|
||||
typedef alpha_mask_u8<4, 0> alpha_mask_argb32a; //----alpha_mask_argb32a
|
||||
|
||||
typedef alpha_mask_u8<4, 2> alpha_mask_bgra32r; //----alpha_mask_bgra32r
|
||||
typedef alpha_mask_u8<4, 1> alpha_mask_bgra32g; //----alpha_mask_bgra32g
|
||||
typedef alpha_mask_u8<4, 0> alpha_mask_bgra32b; //----alpha_mask_bgra32b
|
||||
typedef alpha_mask_u8<4, 3> alpha_mask_bgra32a; //----alpha_mask_bgra32a
|
||||
|
||||
typedef alpha_mask_u8<4, 3> alpha_mask_abgr32r; //----alpha_mask_abgr32r
|
||||
typedef alpha_mask_u8<4, 2> alpha_mask_abgr32g; //----alpha_mask_abgr32g
|
||||
typedef alpha_mask_u8<4, 1> alpha_mask_abgr32b; //----alpha_mask_abgr32b
|
||||
typedef alpha_mask_u8<4, 0> alpha_mask_abgr32a; //----alpha_mask_abgr32a
|
||||
|
||||
typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgb24gray; //----alpha_mask_rgb24gray
|
||||
typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgr24gray; //----alpha_mask_bgr24gray
|
||||
typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgba32gray; //----alpha_mask_rgba32gray
|
||||
typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_argb32gray; //----alpha_mask_argb32gray
|
||||
typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgra32gray; //----alpha_mask_bgra32gray
|
||||
typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_abgr32gray; //----alpha_mask_abgr32gray
|
||||
|
||||
|
||||
|
||||
//==========================================================amask_no_clip_u8
|
||||
template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8>
|
||||
class amask_no_clip_u8
|
||||
{
|
||||
public:
|
||||
typedef int8u cover_type;
|
||||
typedef amask_no_clip_u8<Step, Offset, MaskF> self_type;
|
||||
enum cover_scale_e
|
||||
{
|
||||
cover_shift = 8,
|
||||
cover_none = 0,
|
||||
cover_full = 255
|
||||
};
|
||||
|
||||
amask_no_clip_u8() : m_rbuf(0) {}
|
||||
explicit amask_no_clip_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
|
||||
|
||||
void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; }
|
||||
|
||||
MaskF& mask_function() { return m_mask_function; }
|
||||
const MaskF& mask_function() const { return m_mask_function; }
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
cover_type pixel(int x, int y) const
|
||||
{
|
||||
return (cover_type)m_mask_function.calculate(
|
||||
m_rbuf->row_ptr(y) + x * Step + Offset);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
cover_type combine_pixel(int x, int y, cover_type val) const
|
||||
{
|
||||
return (cover_type)((cover_full + val *
|
||||
m_mask_function.calculate(
|
||||
m_rbuf->row_ptr(y) + x * Step + Offset)) >>
|
||||
cover_shift);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void fill_hspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
do
|
||||
{
|
||||
*dst++ = (cover_type)m_mask_function.calculate(mask);
|
||||
mask += Step;
|
||||
}
|
||||
while(--num_pix);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
do
|
||||
{
|
||||
*dst = (cover_type)((cover_full + (*dst) *
|
||||
m_mask_function.calculate(mask)) >>
|
||||
cover_shift);
|
||||
++dst;
|
||||
mask += Step;
|
||||
}
|
||||
while(--num_pix);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void fill_vspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
do
|
||||
{
|
||||
*dst++ = (cover_type)m_mask_function.calculate(mask);
|
||||
mask += m_rbuf->stride();
|
||||
}
|
||||
while(--num_pix);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void combine_vspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
do
|
||||
{
|
||||
*dst = (cover_type)((cover_full + (*dst) *
|
||||
m_mask_function.calculate(mask)) >>
|
||||
cover_shift);
|
||||
++dst;
|
||||
mask += m_rbuf->stride();
|
||||
}
|
||||
while(--num_pix);
|
||||
}
|
||||
|
||||
private:
|
||||
amask_no_clip_u8(const self_type&);
|
||||
const self_type& operator = (const self_type&);
|
||||
|
||||
rendering_buffer* m_rbuf;
|
||||
MaskF m_mask_function;
|
||||
};
|
||||
|
||||
|
||||
typedef amask_no_clip_u8<1, 0> amask_no_clip_gray8; //----amask_no_clip_gray8
|
||||
|
||||
typedef amask_no_clip_u8<3, 0> amask_no_clip_rgb24r; //----amask_no_clip_rgb24r
|
||||
typedef amask_no_clip_u8<3, 1> amask_no_clip_rgb24g; //----amask_no_clip_rgb24g
|
||||
typedef amask_no_clip_u8<3, 2> amask_no_clip_rgb24b; //----amask_no_clip_rgb24b
|
||||
|
||||
typedef amask_no_clip_u8<3, 2> amask_no_clip_bgr24r; //----amask_no_clip_bgr24r
|
||||
typedef amask_no_clip_u8<3, 1> amask_no_clip_bgr24g; //----amask_no_clip_bgr24g
|
||||
typedef amask_no_clip_u8<3, 0> amask_no_clip_bgr24b; //----amask_no_clip_bgr24b
|
||||
|
||||
typedef amask_no_clip_u8<4, 0> amask_no_clip_rgba32r; //----amask_no_clip_rgba32r
|
||||
typedef amask_no_clip_u8<4, 1> amask_no_clip_rgba32g; //----amask_no_clip_rgba32g
|
||||
typedef amask_no_clip_u8<4, 2> amask_no_clip_rgba32b; //----amask_no_clip_rgba32b
|
||||
typedef amask_no_clip_u8<4, 3> amask_no_clip_rgba32a; //----amask_no_clip_rgba32a
|
||||
|
||||
typedef amask_no_clip_u8<4, 1> amask_no_clip_argb32r; //----amask_no_clip_argb32r
|
||||
typedef amask_no_clip_u8<4, 2> amask_no_clip_argb32g; //----amask_no_clip_argb32g
|
||||
typedef amask_no_clip_u8<4, 3> amask_no_clip_argb32b; //----amask_no_clip_argb32b
|
||||
typedef amask_no_clip_u8<4, 0> amask_no_clip_argb32a; //----amask_no_clip_argb32a
|
||||
|
||||
typedef amask_no_clip_u8<4, 2> amask_no_clip_bgra32r; //----amask_no_clip_bgra32r
|
||||
typedef amask_no_clip_u8<4, 1> amask_no_clip_bgra32g; //----amask_no_clip_bgra32g
|
||||
typedef amask_no_clip_u8<4, 0> amask_no_clip_bgra32b; //----amask_no_clip_bgra32b
|
||||
typedef amask_no_clip_u8<4, 3> amask_no_clip_bgra32a; //----amask_no_clip_bgra32a
|
||||
|
||||
typedef amask_no_clip_u8<4, 3> amask_no_clip_abgr32r; //----amask_no_clip_abgr32r
|
||||
typedef amask_no_clip_u8<4, 2> amask_no_clip_abgr32g; //----amask_no_clip_abgr32g
|
||||
typedef amask_no_clip_u8<4, 1> amask_no_clip_abgr32b; //----amask_no_clip_abgr32b
|
||||
typedef amask_no_clip_u8<4, 0> amask_no_clip_abgr32a; //----amask_no_clip_abgr32a
|
||||
|
||||
typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgb24gray; //----amask_no_clip_rgb24gray
|
||||
typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgr24gray; //----amask_no_clip_bgr24gray
|
||||
typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgba32gray; //----amask_no_clip_rgba32gray
|
||||
typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_argb32gray; //----amask_no_clip_argb32gray
|
||||
typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgra32gray; //----amask_no_clip_bgra32gray
|
||||
typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_abgr32gray; //----amask_no_clip_abgr32gray
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,79 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_ARC_INCLUDED
|
||||
#define AGG_ARC_INCLUDED
|
||||
|
||||
#include <math.h>
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=====================================================================arc
|
||||
//
|
||||
// See Implementation agg_arc.cpp
|
||||
//
|
||||
class arc
|
||||
{
|
||||
public:
|
||||
arc() : m_scale(1.0), m_initialized(false) {}
|
||||
arc(double x, double y,
|
||||
double rx, double ry,
|
||||
double a1, double a2,
|
||||
bool ccw=true);
|
||||
|
||||
void init(double x, double y,
|
||||
double rx, double ry,
|
||||
double a1, double a2,
|
||||
bool ccw=true);
|
||||
|
||||
void approximation_scale(double s);
|
||||
double approximation_scale() const { return m_scale; }
|
||||
|
||||
void rewind(unsigned);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
void normalize(double a1, double a2, bool ccw);
|
||||
|
||||
double m_x;
|
||||
double m_y;
|
||||
double m_rx;
|
||||
double m_ry;
|
||||
double m_angle;
|
||||
double m_start;
|
||||
double m_end;
|
||||
double m_scale;
|
||||
double m_da;
|
||||
bool m_ccw;
|
||||
bool m_initialized;
|
||||
unsigned m_path_cmd;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,88 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_ARROWHEAD_INCLUDED
|
||||
#define AGG_ARROWHEAD_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//===============================================================arrowhead
|
||||
//
|
||||
// See implementation agg_arrowhead.cpp
|
||||
//
|
||||
class arrowhead
|
||||
{
|
||||
public:
|
||||
arrowhead();
|
||||
|
||||
void head(double d1, double d2, double d3, double d4)
|
||||
{
|
||||
m_head_d1 = d1;
|
||||
m_head_d2 = d2;
|
||||
m_head_d3 = d3;
|
||||
m_head_d4 = d4;
|
||||
m_head_flag = true;
|
||||
}
|
||||
|
||||
void head() { m_head_flag = true; }
|
||||
void no_head() { m_head_flag = false; }
|
||||
|
||||
void tail(double d1, double d2, double d3, double d4)
|
||||
{
|
||||
m_tail_d1 = d1;
|
||||
m_tail_d2 = d2;
|
||||
m_tail_d3 = d3;
|
||||
m_tail_d4 = d4;
|
||||
m_tail_flag = true;
|
||||
}
|
||||
|
||||
void tail() { m_tail_flag = true; }
|
||||
void no_tail() { m_tail_flag = false; }
|
||||
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
double m_head_d1;
|
||||
double m_head_d2;
|
||||
double m_head_d3;
|
||||
double m_head_d4;
|
||||
double m_tail_d1;
|
||||
double m_tail_d2;
|
||||
double m_tail_d3;
|
||||
double m_tail_d4;
|
||||
bool m_head_flag;
|
||||
bool m_tail_flag;
|
||||
double m_coord[16];
|
||||
unsigned m_cmd[8];
|
||||
unsigned m_curr_id;
|
||||
unsigned m_curr_coord;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,539 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_BASICS_INCLUDED
|
||||
#define AGG_BASICS_INCLUDED
|
||||
|
||||
#include <math.h>
|
||||
#include "agg_config.h"
|
||||
|
||||
//---------------------------------------------------------AGG_CUSTOM_ALLOCATOR
|
||||
#ifdef AGG_CUSTOM_ALLOCATOR
|
||||
#include "agg_allocator.h"
|
||||
#else
|
||||
namespace agg
|
||||
{
|
||||
// The policy of all AGG containers and memory allocation strategy
|
||||
// in general is that no allocated data requires explicit construction.
|
||||
// It means that the allocator can be really simple; you can even
|
||||
// replace new/delete to malloc/free. The constructors and destructors
|
||||
// won't be called in this case, however everything will remain working.
|
||||
// The second argument of deallocate() is the size of the allocated
|
||||
// block. You can use this information if you wish.
|
||||
//------------------------------------------------------------pod_allocator
|
||||
template<class T> struct pod_allocator
|
||||
{
|
||||
static T* allocate(unsigned num) { return new T [num]; }
|
||||
static void deallocate(T* ptr, unsigned) { delete [] ptr; }
|
||||
};
|
||||
|
||||
// Single object allocator. It's also can be replaced with your custom
|
||||
// allocator. The difference is that it can only allocate a single
|
||||
// object and the constructor and destructor must be called.
|
||||
// In AGG there is no need to allocate an array of objects with
|
||||
// calling their constructors (only single ones). So that, if you
|
||||
// replace these new/delete to malloc/free make sure that the in-place
|
||||
// new is called and take care of calling the destructor too.
|
||||
//------------------------------------------------------------obj_allocator
|
||||
template<class T> struct obj_allocator
|
||||
{
|
||||
static T* allocate() { return new T; }
|
||||
static void deallocate(T* ptr) { delete ptr; }
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//-------------------------------------------------------- Default basic types
|
||||
//
|
||||
// If the compiler has different capacity of the basic types you can redefine
|
||||
// them via the compiler command line or by generating agg_config.h that is
|
||||
// empty by default.
|
||||
//
|
||||
#ifndef AGG_INT8
|
||||
#define AGG_INT8 signed char
|
||||
#endif
|
||||
|
||||
#ifndef AGG_INT8U
|
||||
#define AGG_INT8U unsigned char
|
||||
#endif
|
||||
|
||||
#ifndef AGG_INT16
|
||||
#define AGG_INT16 short
|
||||
#endif
|
||||
|
||||
#ifndef AGG_INT16U
|
||||
#define AGG_INT16U unsigned short
|
||||
#endif
|
||||
|
||||
#ifndef AGG_INT32
|
||||
#define AGG_INT32 int
|
||||
#endif
|
||||
|
||||
#ifndef AGG_INT32U
|
||||
#define AGG_INT32U unsigned
|
||||
#endif
|
||||
|
||||
#ifndef AGG_INT64
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
#define AGG_INT64 signed __int64
|
||||
#else
|
||||
#define AGG_INT64 signed long long
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef AGG_INT64U
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
#define AGG_INT64U unsigned __int64
|
||||
#else
|
||||
#define AGG_INT64U unsigned long long
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//------------------------------------------------ Some fixes for MS Visual C++
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable:4786) // Identifier was truncated...
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define AGG_INLINE __forceinline
|
||||
#else
|
||||
#define AGG_INLINE inline
|
||||
#endif
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//-------------------------------------------------------------------------
|
||||
typedef AGG_INT8 int8; //----int8
|
||||
typedef AGG_INT8U int8u; //----int8u
|
||||
typedef AGG_INT16 int16; //----int16
|
||||
typedef AGG_INT16U int16u; //----int16u
|
||||
typedef AGG_INT32 int32; //----int32
|
||||
typedef AGG_INT32U int32u; //----int32u
|
||||
typedef AGG_INT64 int64; //----int64
|
||||
typedef AGG_INT64U int64u; //----int64u
|
||||
|
||||
#if defined(AGG_FISTP)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4035) //Disable warning "no return value"
|
||||
AGG_INLINE int iround(double v) //-------iround
|
||||
{
|
||||
int t;
|
||||
__asm fld qword ptr [v]
|
||||
__asm fistp dword ptr [t]
|
||||
__asm mov eax, dword ptr [t]
|
||||
}
|
||||
AGG_INLINE unsigned uround(double v) //-------uround
|
||||
{
|
||||
unsigned t;
|
||||
__asm fld qword ptr [v]
|
||||
__asm fistp dword ptr [t]
|
||||
__asm mov eax, dword ptr [t]
|
||||
}
|
||||
#pragma warning(pop)
|
||||
AGG_INLINE unsigned ufloor(double v) //-------ufloor
|
||||
{
|
||||
return unsigned(floor(v));
|
||||
}
|
||||
AGG_INLINE unsigned uceil(double v) //--------uceil
|
||||
{
|
||||
return unsigned(ceil(v));
|
||||
}
|
||||
#elif defined(AGG_QIFIST)
|
||||
AGG_INLINE int iround(double v)
|
||||
{
|
||||
return int(v);
|
||||
}
|
||||
AGG_INLINE int uround(double v)
|
||||
{
|
||||
return unsigned(v);
|
||||
}
|
||||
AGG_INLINE unsigned ufloor(double v)
|
||||
{
|
||||
return unsigned(floor(v));
|
||||
}
|
||||
AGG_INLINE unsigned uceil(double v)
|
||||
{
|
||||
return unsigned(ceil(v));
|
||||
}
|
||||
#else
|
||||
AGG_INLINE int iround(double v)
|
||||
{
|
||||
return int((v < 0.0) ? v - 0.5 : v + 0.5);
|
||||
}
|
||||
AGG_INLINE int uround(double v)
|
||||
{
|
||||
return unsigned(v + 0.5);
|
||||
}
|
||||
AGG_INLINE unsigned ufloor(double v)
|
||||
{
|
||||
return unsigned(v);
|
||||
}
|
||||
AGG_INLINE unsigned uceil(double v)
|
||||
{
|
||||
return unsigned(ceil(v));
|
||||
}
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------saturation
|
||||
template<int Limit> struct saturation
|
||||
{
|
||||
AGG_INLINE static int iround(double v)
|
||||
{
|
||||
if(v < double(-Limit)) return -Limit;
|
||||
if(v > double( Limit)) return Limit;
|
||||
return agg::iround(v);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------mul_one
|
||||
template<unsigned Shift> struct mul_one
|
||||
{
|
||||
AGG_INLINE static unsigned mul(unsigned a, unsigned b)
|
||||
{
|
||||
register unsigned q = a * b + (1 << (Shift-1));
|
||||
return (q + (q >> Shift)) >> Shift;
|
||||
}
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
typedef unsigned char cover_type; //----cover_type
|
||||
enum cover_scale_e
|
||||
{
|
||||
cover_shift = 8, //----cover_shift
|
||||
cover_size = 1 << cover_shift, //----cover_size
|
||||
cover_mask = cover_size - 1, //----cover_mask
|
||||
cover_none = 0, //----cover_none
|
||||
cover_full = cover_mask //----cover_full
|
||||
};
|
||||
|
||||
//----------------------------------------------------poly_subpixel_scale_e
|
||||
// These constants determine the subpixel accuracy, to be more precise,
|
||||
// the number of bits of the fractional part of the coordinates.
|
||||
// The possible coordinate capacity in bits can be calculated by formula:
|
||||
// sizeof(int) * 8 - poly_subpixel_shift, i.e, for 32-bit integers and
|
||||
// 8-bits fractional part the capacity is 24 bits.
|
||||
enum poly_subpixel_scale_e
|
||||
{
|
||||
poly_subpixel_shift = 8, //----poly_subpixel_shift
|
||||
poly_subpixel_scale = 1<<poly_subpixel_shift, //----poly_subpixel_scale
|
||||
poly_subpixel_mask = poly_subpixel_scale-1, //----poly_subpixel_mask
|
||||
};
|
||||
|
||||
//----------------------------------------------------------filling_rule_e
|
||||
enum filling_rule_e
|
||||
{
|
||||
fill_non_zero,
|
||||
fill_even_odd
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------pi
|
||||
const double pi = 3.14159265358979323846;
|
||||
|
||||
//------------------------------------------------------------------deg2rad
|
||||
inline double deg2rad(double deg)
|
||||
{
|
||||
return deg * pi / 180.0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------rad2deg
|
||||
inline double rad2deg(double rad)
|
||||
{
|
||||
return rad * 180.0 / pi;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------rect_base
|
||||
template<class T> struct rect_base
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef rect_base<T> self_type;
|
||||
T x1, y1, x2, y2;
|
||||
|
||||
rect_base() {}
|
||||
rect_base(T x1_, T y1_, T x2_, T y2_) :
|
||||
x1(x1_), y1(y1_), x2(x2_), y2(y2_) {}
|
||||
|
||||
void init(T x1_, T y1_, T x2_, T y2_)
|
||||
{
|
||||
x1 = x1_; y1 = y1_; x2 = x2_; y2 = y2_;
|
||||
}
|
||||
|
||||
const self_type& normalize()
|
||||
{
|
||||
T t;
|
||||
if(x1 > x2) { t = x1; x1 = x2; x2 = t; }
|
||||
if(y1 > y2) { t = y1; y1 = y2; y2 = t; }
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool clip(const self_type& r)
|
||||
{
|
||||
if(x2 > r.x2) x2 = r.x2;
|
||||
if(y2 > r.y2) y2 = r.y2;
|
||||
if(x1 < r.x1) x1 = r.x1;
|
||||
if(y1 < r.y1) y1 = r.y1;
|
||||
return x1 <= x2 && y1 <= y2;
|
||||
}
|
||||
|
||||
bool is_valid() const
|
||||
{
|
||||
return x1 <= x2 && y1 <= y2;
|
||||
}
|
||||
|
||||
bool hit_test(T x, T y) const
|
||||
{
|
||||
return (x >= x1 && x <= x2 && y >= y1 && y <= y2);
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------intersect_rectangles
|
||||
template<class Rect>
|
||||
inline Rect intersect_rectangles(const Rect& r1, const Rect& r2)
|
||||
{
|
||||
Rect r = r1;
|
||||
|
||||
// First process x2,y2 because the other order
|
||||
// results in Internal Compiler Error under
|
||||
// Microsoft Visual C++ .NET 2003 69462-335-0000007-18038 in
|
||||
// case of "Maximize Speed" optimization option.
|
||||
//-----------------
|
||||
if(r.x2 > r2.x2) r.x2 = r2.x2;
|
||||
if(r.y2 > r2.y2) r.y2 = r2.y2;
|
||||
if(r.x1 < r2.x1) r.x1 = r2.x1;
|
||||
if(r.y1 < r2.y1) r.y1 = r2.y1;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------unite_rectangles
|
||||
template<class Rect>
|
||||
inline Rect unite_rectangles(const Rect& r1, const Rect& r2)
|
||||
{
|
||||
Rect r = r1;
|
||||
if(r.x2 < r2.x2) r.x2 = r2.x2;
|
||||
if(r.y2 < r2.y2) r.y2 = r2.y2;
|
||||
if(r.x1 > r2.x1) r.x1 = r2.x1;
|
||||
if(r.y1 > r2.y1) r.y1 = r2.y1;
|
||||
return r;
|
||||
}
|
||||
|
||||
typedef rect_base<int> rect_i; //----rect_i
|
||||
typedef rect_base<float> rect_f; //----rect_f
|
||||
typedef rect_base<double> rect_d; //----rect_d
|
||||
|
||||
//---------------------------------------------------------path_commands_e
|
||||
enum path_commands_e
|
||||
{
|
||||
path_cmd_stop = 0, //----path_cmd_stop
|
||||
path_cmd_move_to = 1, //----path_cmd_move_to
|
||||
path_cmd_line_to = 2, //----path_cmd_line_to
|
||||
path_cmd_curve3 = 3, //----path_cmd_curve3
|
||||
path_cmd_curve4 = 4, //----path_cmd_curve4
|
||||
path_cmd_curveN = 5, //----path_cmd_curveN
|
||||
path_cmd_catrom = 6, //----path_cmd_catrom
|
||||
path_cmd_ubspline = 7, //----path_cmd_ubspline
|
||||
path_cmd_end_poly = 0x0F, //----path_cmd_end_poly
|
||||
path_cmd_mask = 0x0F //----path_cmd_mask
|
||||
};
|
||||
|
||||
//------------------------------------------------------------path_flags_e
|
||||
enum path_flags_e
|
||||
{
|
||||
path_flags_none = 0, //----path_flags_none
|
||||
path_flags_ccw = 0x10, //----path_flags_ccw
|
||||
path_flags_cw = 0x20, //----path_flags_cw
|
||||
path_flags_close = 0x40, //----path_flags_close
|
||||
path_flags_mask = 0xF0 //----path_flags_mask
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------is_vertex
|
||||
inline bool is_vertex(unsigned c)
|
||||
{
|
||||
return c >= path_cmd_move_to && c < path_cmd_end_poly;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------is_drawing
|
||||
inline bool is_drawing(unsigned c)
|
||||
{
|
||||
return c >= path_cmd_line_to && c < path_cmd_end_poly;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------is_stop
|
||||
inline bool is_stop(unsigned c)
|
||||
{
|
||||
return c == path_cmd_stop;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------is_move_to
|
||||
inline bool is_move_to(unsigned c)
|
||||
{
|
||||
return c == path_cmd_move_to;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------is_line_to
|
||||
inline bool is_line_to(unsigned c)
|
||||
{
|
||||
return c == path_cmd_line_to;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------is_curve
|
||||
inline bool is_curve(unsigned c)
|
||||
{
|
||||
return c == path_cmd_curve3 || c == path_cmd_curve4;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------is_curve3
|
||||
inline bool is_curve3(unsigned c)
|
||||
{
|
||||
return c == path_cmd_curve3;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------is_curve4
|
||||
inline bool is_curve4(unsigned c)
|
||||
{
|
||||
return c == path_cmd_curve4;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------is_end_poly
|
||||
inline bool is_end_poly(unsigned c)
|
||||
{
|
||||
return (c & path_cmd_mask) == path_cmd_end_poly;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------is_close
|
||||
inline bool is_close(unsigned c)
|
||||
{
|
||||
return (c & ~(path_flags_cw | path_flags_ccw)) ==
|
||||
(path_cmd_end_poly | path_flags_close);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------is_next_poly
|
||||
inline bool is_next_poly(unsigned c)
|
||||
{
|
||||
return is_stop(c) || is_move_to(c) || is_end_poly(c);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------is_cw
|
||||
inline bool is_cw(unsigned c)
|
||||
{
|
||||
return (c & path_flags_cw) != 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------is_ccw
|
||||
inline bool is_ccw(unsigned c)
|
||||
{
|
||||
return (c & path_flags_ccw) != 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------is_oriented
|
||||
inline bool is_oriented(unsigned c)
|
||||
{
|
||||
return (c & (path_flags_cw | path_flags_ccw)) != 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------is_closed
|
||||
inline bool is_closed(unsigned c)
|
||||
{
|
||||
return (c & path_flags_close) != 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------get_close_flag
|
||||
inline unsigned get_close_flag(unsigned c)
|
||||
{
|
||||
return c & path_flags_close;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------clear_orientation
|
||||
inline unsigned clear_orientation(unsigned c)
|
||||
{
|
||||
return c & ~(path_flags_cw | path_flags_ccw);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------get_orientation
|
||||
inline unsigned get_orientation(unsigned c)
|
||||
{
|
||||
return c & (path_flags_cw | path_flags_ccw);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------set_orientation
|
||||
inline unsigned set_orientation(unsigned c, unsigned o)
|
||||
{
|
||||
return clear_orientation(c) | o;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------point_base
|
||||
template<class T> struct point_base
|
||||
{
|
||||
typedef T value_type;
|
||||
T x,y;
|
||||
point_base() {}
|
||||
point_base(T x_, T y_) : x(x_), y(y_) {}
|
||||
};
|
||||
typedef point_base<int> point_i; //-----point_i
|
||||
typedef point_base<float> point_f; //-----point_f
|
||||
typedef point_base<double> point_d; //-----point_d
|
||||
|
||||
//-------------------------------------------------------------vertex_base
|
||||
template<class T> struct vertex_base
|
||||
{
|
||||
typedef T value_type;
|
||||
T x,y;
|
||||
unsigned cmd;
|
||||
vertex_base() {}
|
||||
vertex_base(T x_, T y_, unsigned cmd_) : x(x_), y(y_), cmd(cmd_) {}
|
||||
};
|
||||
typedef vertex_base<int> vertex_i; //-----vertex_i
|
||||
typedef vertex_base<float> vertex_f; //-----vertex_f
|
||||
typedef vertex_base<double> vertex_d; //-----vertex_d
|
||||
|
||||
//----------------------------------------------------------------row_info
|
||||
template<class T> struct row_info
|
||||
{
|
||||
int x1, x2;
|
||||
T* ptr;
|
||||
row_info() {}
|
||||
row_info(int x1_, int x2_, T* ptr_) : x1(x1_), x2(x2_), ptr(ptr_) {}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------const_row_info
|
||||
template<class T> struct const_row_info
|
||||
{
|
||||
int x1, x2;
|
||||
const T* ptr;
|
||||
const_row_info() {}
|
||||
const_row_info(int x1_, int x2_, const T* ptr_) :
|
||||
x1(x1_), x2(x2_), ptr(ptr_) {}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------is_equal_eps
|
||||
template<class T> inline bool is_equal_eps(T v1, T v2, T epsilon)
|
||||
{
|
||||
return fabs(v1 - v2) <= double(epsilon);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_BEZIER_ARC_INCLUDED
|
||||
#define AGG_BEZIER_ARC_INCLUDED
|
||||
|
||||
#include "agg_conv_transform.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void arc_to_bezier(double cx, double cy, double rx, double ry,
|
||||
double start_angle, double sweep_angle,
|
||||
double* curve);
|
||||
|
||||
|
||||
//==============================================================bezier_arc
|
||||
//
|
||||
// See implemantaion agg_bezier_arc.cpp
|
||||
//
|
||||
class bezier_arc
|
||||
{
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
bezier_arc() : m_vertex(26), m_num_vertices(0), m_cmd(path_cmd_line_to) {}
|
||||
bezier_arc(double x, double y,
|
||||
double rx, double ry,
|
||||
double start_angle,
|
||||
double sweep_angle)
|
||||
{
|
||||
init(x, y, rx, ry, start_angle, sweep_angle);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void init(double x, double y,
|
||||
double rx, double ry,
|
||||
double start_angle,
|
||||
double sweep_angle);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void rewind(unsigned)
|
||||
{
|
||||
m_vertex = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
if(m_vertex >= m_num_vertices) return path_cmd_stop;
|
||||
*x = m_vertices[m_vertex];
|
||||
*y = m_vertices[m_vertex + 1];
|
||||
m_vertex += 2;
|
||||
return (m_vertex == 2) ? path_cmd_move_to : m_cmd;
|
||||
}
|
||||
|
||||
// Supplemantary functions. num_vertices() actually returns doubled
|
||||
// number of vertices. That is, for 1 vertex it returns 2.
|
||||
//--------------------------------------------------------------------
|
||||
unsigned num_vertices() const { return m_num_vertices; }
|
||||
const double* vertices() const { return m_vertices; }
|
||||
double* vertices() { return m_vertices; }
|
||||
|
||||
private:
|
||||
unsigned m_vertex;
|
||||
unsigned m_num_vertices;
|
||||
double m_vertices[26];
|
||||
unsigned m_cmd;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//==========================================================bezier_arc_svg
|
||||
// Compute an SVG-style bezier arc.
|
||||
//
|
||||
// Computes an elliptical arc from (x1, y1) to (x2, y2). The size and
|
||||
// orientation of the ellipse are defined by two radii (rx, ry)
|
||||
// and an x-axis-rotation, which indicates how the ellipse as a whole
|
||||
// is rotated relative to the current coordinate system. The center
|
||||
// (cx, cy) of the ellipse is calculated automatically to satisfy the
|
||||
// constraints imposed by the other parameters.
|
||||
// large-arc-flag and sweep-flag contribute to the automatic calculations
|
||||
// and help determine how the arc is drawn.
|
||||
class bezier_arc_svg
|
||||
{
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
bezier_arc_svg() : m_arc(), m_radii_ok(false) {}
|
||||
|
||||
bezier_arc_svg(double x1, double y1,
|
||||
double rx, double ry,
|
||||
double angle,
|
||||
bool large_arc_flag,
|
||||
bool sweep_flag,
|
||||
double x2, double y2) :
|
||||
m_arc(), m_radii_ok(false)
|
||||
{
|
||||
init(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void init(double x1, double y1,
|
||||
double rx, double ry,
|
||||
double angle,
|
||||
bool large_arc_flag,
|
||||
bool sweep_flag,
|
||||
double x2, double y2);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
bool radii_ok() const { return m_radii_ok; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void rewind(unsigned)
|
||||
{
|
||||
m_arc.rewind(0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
return m_arc.vertex(x, y);
|
||||
}
|
||||
|
||||
// Supplemantary functions. num_vertices() actually returns doubled
|
||||
// number of vertices. That is, for 1 vertex it returns 2.
|
||||
//--------------------------------------------------------------------
|
||||
unsigned num_vertices() const { return m_arc.num_vertices(); }
|
||||
const double* vertices() const { return m_arc.vertices(); }
|
||||
double* vertices() { return m_arc.vertices(); }
|
||||
|
||||
private:
|
||||
bezier_arc m_arc;
|
||||
bool m_radii_ok;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,63 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_BITSET_ITERATOR_INCLUDED
|
||||
#define AGG_BITSET_ITERATOR_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
class bitset_iterator
|
||||
{
|
||||
public:
|
||||
bitset_iterator(const int8u* bits, unsigned offset = 0) :
|
||||
m_bits(bits + (offset >> 3)),
|
||||
m_mask(0x80 >> (offset & 7))
|
||||
{}
|
||||
|
||||
void operator ++ ()
|
||||
{
|
||||
m_mask >>= 1;
|
||||
if(m_mask == 0)
|
||||
{
|
||||
++m_bits;
|
||||
m_mask = 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned bit() const
|
||||
{
|
||||
return (*m_bits) & m_mask;
|
||||
}
|
||||
|
||||
private:
|
||||
const int8u* m_bits;
|
||||
int8u m_mask;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,122 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_BOUNDING_RECT_INCLUDED
|
||||
#define AGG_BOUNDING_RECT_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-----------------------------------------------------------bounding_rect
|
||||
template<class VertexSource, class GetId, class CoordT>
|
||||
bool bounding_rect(VertexSource& vs, GetId& gi,
|
||||
unsigned start, unsigned num,
|
||||
CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2)
|
||||
{
|
||||
unsigned i;
|
||||
double x;
|
||||
double y;
|
||||
bool first = true;
|
||||
|
||||
*x1 = CoordT(1);
|
||||
*y1 = CoordT(1);
|
||||
*x2 = CoordT(0);
|
||||
*y2 = CoordT(0);
|
||||
|
||||
for(i = 0; i < num; i++)
|
||||
{
|
||||
vs.rewind(gi[start + i]);
|
||||
unsigned cmd;
|
||||
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||
{
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
if(first)
|
||||
{
|
||||
*x1 = CoordT(x);
|
||||
*y1 = CoordT(y);
|
||||
*x2 = CoordT(x);
|
||||
*y2 = CoordT(y);
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(CoordT(x) < *x1) *x1 = CoordT(x);
|
||||
if(CoordT(y) < *y1) *y1 = CoordT(y);
|
||||
if(CoordT(x) > *x2) *x2 = CoordT(x);
|
||||
if(CoordT(y) > *y2) *y2 = CoordT(y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return *x1 <= *x2 && *y1 <= *y2;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------bounding_rect_single
|
||||
template<class VertexSource, class CoordT>
|
||||
bool bounding_rect_single(VertexSource& vs, unsigned path_id,
|
||||
CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2)
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
bool first = true;
|
||||
|
||||
*x1 = CoordT(1);
|
||||
*y1 = CoordT(1);
|
||||
*x2 = CoordT(0);
|
||||
*y2 = CoordT(0);
|
||||
|
||||
vs.rewind(path_id);
|
||||
unsigned cmd;
|
||||
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||
{
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
if(first)
|
||||
{
|
||||
*x1 = CoordT(x);
|
||||
*y1 = CoordT(y);
|
||||
*x2 = CoordT(x);
|
||||
*y2 = CoordT(y);
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(CoordT(x) < *x1) *x1 = CoordT(x);
|
||||
if(CoordT(y) < *y1) *y1 = CoordT(y);
|
||||
if(CoordT(x) > *x2) *x2 = CoordT(x);
|
||||
if(CoordT(y) > *y2) *y2 = CoordT(y);
|
||||
}
|
||||
}
|
||||
}
|
||||
return *x1 <= *x2 && *y1 <= *y2;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,81 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_BSPLINE_INCLUDED
|
||||
#define AGG_BSPLINE_INCLUDED
|
||||
|
||||
#include "agg_array.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//----------------------------------------------------------------bspline
|
||||
// A very simple class of Bi-cubic Spline interpolation.
|
||||
// First call init(num, x[], y[]) where num - number of source points,
|
||||
// x, y - arrays of X and Y values respectively. Here Y must be a function
|
||||
// of X. It means that all the X-coordinates must be arranged in the ascending
|
||||
// order.
|
||||
// Then call get(x) that calculates a value Y for the respective X.
|
||||
// The class supports extrapolation, i.e. you can call get(x) where x is
|
||||
// outside the given with init() X-range. Extrapolation is a simple linear
|
||||
// function.
|
||||
//
|
||||
// See Implementation agg_bspline.cpp
|
||||
//------------------------------------------------------------------------
|
||||
class bspline
|
||||
{
|
||||
public:
|
||||
bspline();
|
||||
bspline(int num);
|
||||
bspline(int num, const double* x, const double* y);
|
||||
|
||||
void init(int num);
|
||||
void add_point(double x, double y);
|
||||
void prepare();
|
||||
|
||||
void init(int num, const double* x, const double* y);
|
||||
|
||||
double get(double x) const;
|
||||
double get_stateful(double x) const;
|
||||
|
||||
private:
|
||||
bspline(const bspline&);
|
||||
const bspline& operator = (const bspline&);
|
||||
|
||||
static void bsearch(int n, const double *x, double x0, int *i);
|
||||
double extrapolation_left(double x) const;
|
||||
double extrapolation_right(double x) const;
|
||||
double interpolation(double x, int i) const;
|
||||
|
||||
int m_max;
|
||||
int m_num;
|
||||
double* m_x;
|
||||
double* m_y;
|
||||
pod_array<double> m_am;
|
||||
mutable int m_last_idx;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,339 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CLIP_LIANG_BARSKY_INCLUDED
|
||||
#define AGG_CLIP_LIANG_BARSKY_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
enum clipping_flags_e
|
||||
{
|
||||
clipping_flags_x1_clipped = 4,
|
||||
clipping_flags_x2_clipped = 1,
|
||||
clipping_flags_y1_clipped = 8,
|
||||
clipping_flags_y2_clipped = 2,
|
||||
clipping_flags_x_clipped = clipping_flags_x1_clipped | clipping_flags_x2_clipped,
|
||||
clipping_flags_y_clipped = clipping_flags_y1_clipped | clipping_flags_y2_clipped
|
||||
};
|
||||
|
||||
//----------------------------------------------------------clipping_flags
|
||||
// Determine the clipping code of the vertex according to the
|
||||
// Cyrus-Beck line clipping algorithm
|
||||
//
|
||||
// | |
|
||||
// 0110 | 0010 | 0011
|
||||
// | |
|
||||
// -------+--------+-------- clip_box.y2
|
||||
// | |
|
||||
// 0100 | 0000 | 0001
|
||||
// | |
|
||||
// -------+--------+-------- clip_box.y1
|
||||
// | |
|
||||
// 1100 | 1000 | 1001
|
||||
// | |
|
||||
// clip_box.x1 clip_box.x2
|
||||
//
|
||||
//
|
||||
template<class T>
|
||||
inline unsigned clipping_flags(T x, T y, const rect_base<T>& clip_box)
|
||||
{
|
||||
return (x > clip_box.x2) |
|
||||
((y > clip_box.y2) << 1) |
|
||||
((x < clip_box.x1) << 2) |
|
||||
((y < clip_box.y1) << 3);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------clipping_flags_x
|
||||
template<class T>
|
||||
inline unsigned clipping_flags_x(T x, const rect_base<T>& clip_box)
|
||||
{
|
||||
return (x > clip_box.x2) | ((x < clip_box.x1) << 2);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------clipping_flags_y
|
||||
template<class T>
|
||||
inline unsigned clipping_flags_y(T y, const rect_base<T>& clip_box)
|
||||
{
|
||||
return ((y > clip_box.y2) << 1) | ((y < clip_box.y1) << 3);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------clip_liang_barsky
|
||||
template<class T>
|
||||
inline unsigned clip_liang_barsky(T x1, T y1, T x2, T y2,
|
||||
const rect_base<T>& clip_box,
|
||||
T* x, T* y)
|
||||
{
|
||||
const double nearzero = 1e-30;
|
||||
|
||||
double deltax = x2 - x1;
|
||||
double deltay = y2 - y1;
|
||||
double xin;
|
||||
double xout;
|
||||
double yin;
|
||||
double yout;
|
||||
double tinx;
|
||||
double tiny;
|
||||
double toutx;
|
||||
double touty;
|
||||
double tin1;
|
||||
double tin2;
|
||||
double tout1;
|
||||
unsigned np = 0;
|
||||
|
||||
if(deltax == 0.0)
|
||||
{
|
||||
// bump off of the vertical
|
||||
deltax = (x1 > clip_box.x1) ? -nearzero : nearzero;
|
||||
}
|
||||
|
||||
if(deltay == 0.0)
|
||||
{
|
||||
// bump off of the horizontal
|
||||
deltay = (y1 > clip_box.y1) ? -nearzero : nearzero;
|
||||
}
|
||||
|
||||
if(deltax > 0.0)
|
||||
{
|
||||
// points to right
|
||||
xin = clip_box.x1;
|
||||
xout = clip_box.x2;
|
||||
}
|
||||
else
|
||||
{
|
||||
xin = clip_box.x2;
|
||||
xout = clip_box.x1;
|
||||
}
|
||||
|
||||
if(deltay > 0.0)
|
||||
{
|
||||
// points up
|
||||
yin = clip_box.y1;
|
||||
yout = clip_box.y2;
|
||||
}
|
||||
else
|
||||
{
|
||||
yin = clip_box.y2;
|
||||
yout = clip_box.y1;
|
||||
}
|
||||
|
||||
tinx = (xin - x1) / deltax;
|
||||
tiny = (yin - y1) / deltay;
|
||||
|
||||
if (tinx < tiny)
|
||||
{
|
||||
// hits x first
|
||||
tin1 = tinx;
|
||||
tin2 = tiny;
|
||||
}
|
||||
else
|
||||
{
|
||||
// hits y first
|
||||
tin1 = tiny;
|
||||
tin2 = tinx;
|
||||
}
|
||||
|
||||
if(tin1 <= 1.0)
|
||||
{
|
||||
if(0.0 < tin1)
|
||||
{
|
||||
*x++ = (T)xin;
|
||||
*y++ = (T)yin;
|
||||
++np;
|
||||
}
|
||||
|
||||
if(tin2 <= 1.0)
|
||||
{
|
||||
toutx = (xout - x1) / deltax;
|
||||
touty = (yout - y1) / deltay;
|
||||
|
||||
tout1 = (toutx < touty) ? toutx : touty;
|
||||
|
||||
if(tin2 > 0.0 || tout1 > 0.0)
|
||||
{
|
||||
if(tin2 <= tout1)
|
||||
{
|
||||
if(tin2 > 0.0)
|
||||
{
|
||||
if(tinx > tiny)
|
||||
{
|
||||
*x++ = (T)xin;
|
||||
*y++ = (T)(y1 + tinx * deltay);
|
||||
}
|
||||
else
|
||||
{
|
||||
*x++ = (T)(x1 + tiny * deltax);
|
||||
*y++ = (T)yin;
|
||||
}
|
||||
++np;
|
||||
}
|
||||
|
||||
if(tout1 < 1.0)
|
||||
{
|
||||
if(toutx < touty)
|
||||
{
|
||||
*x++ = (T)xout;
|
||||
*y++ = (T)(y1 + toutx * deltay);
|
||||
}
|
||||
else
|
||||
{
|
||||
*x++ = (T)(x1 + touty * deltax);
|
||||
*y++ = (T)yout;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*x++ = x2;
|
||||
*y++ = y2;
|
||||
}
|
||||
++np;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(tinx > tiny)
|
||||
{
|
||||
*x++ = (T)xin;
|
||||
*y++ = (T)yout;
|
||||
}
|
||||
else
|
||||
{
|
||||
*x++ = (T)xout;
|
||||
*y++ = (T)yin;
|
||||
}
|
||||
++np;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return np;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<class T>
|
||||
bool clip_move_point(T x1, T y1, T x2, T y2,
|
||||
const rect_base<T>& clip_box,
|
||||
T* x, T* y, unsigned flags)
|
||||
{
|
||||
T bound;
|
||||
|
||||
if(flags & clipping_flags_x_clipped)
|
||||
{
|
||||
if(x1 == x2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bound = (flags & clipping_flags_x1_clipped) ? clip_box.x1 : clip_box.x2;
|
||||
*y = (T)(double(bound - x1) * (y2 - y1) / (x2 - x1) + y1);
|
||||
*x = bound;
|
||||
}
|
||||
|
||||
flags = clipping_flags_y(*y, clip_box);
|
||||
if(flags & clipping_flags_y_clipped)
|
||||
{
|
||||
if(y1 == y2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bound = (flags & clipping_flags_y1_clipped) ? clip_box.y1 : clip_box.y2;
|
||||
*x = (T)(double(bound - y1) * (x2 - x1) / (y2 - y1) + x1);
|
||||
*y = bound;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------clip_line_segment
|
||||
// Returns: ret >= 4 - Fully clipped
|
||||
// (ret & 1) != 0 - First point has been moved
|
||||
// (ret & 2) != 0 - Second point has been moved
|
||||
//
|
||||
template<class T>
|
||||
unsigned clip_line_segment(T* x1, T* y1, T* x2, T* y2,
|
||||
const rect_base<T>& clip_box)
|
||||
{
|
||||
unsigned f1 = clipping_flags(*x1, *y1, clip_box);
|
||||
unsigned f2 = clipping_flags(*x2, *y2, clip_box);
|
||||
unsigned ret = 0;
|
||||
|
||||
if((f2 | f1) == 0)
|
||||
{
|
||||
// Fully visible
|
||||
return 0;
|
||||
}
|
||||
|
||||
if((f1 & clipping_flags_x_clipped) != 0 &&
|
||||
(f1 & clipping_flags_x_clipped) == (f2 & clipping_flags_x_clipped))
|
||||
{
|
||||
// Fully clipped
|
||||
return 4;
|
||||
}
|
||||
|
||||
if((f1 & clipping_flags_y_clipped) != 0 &&
|
||||
(f1 & clipping_flags_y_clipped) == (f2 & clipping_flags_y_clipped))
|
||||
{
|
||||
// Fully clipped
|
||||
return 4;
|
||||
}
|
||||
|
||||
T tx1 = *x1;
|
||||
T ty1 = *y1;
|
||||
T tx2 = *x2;
|
||||
T ty2 = *y2;
|
||||
if(f1)
|
||||
{
|
||||
if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x1, y1, f1))
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
if(*x1 == *x2 && *y1 == *y2)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
ret |= 1;
|
||||
}
|
||||
if(f2)
|
||||
{
|
||||
if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x2, y2, f2))
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
if(*x1 == *x2 && *y1 == *y2)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
ret |= 2;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,423 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for high precision colors has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// color types gray8, gray16
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_COLOR_GRAY_INCLUDED
|
||||
#define AGG_COLOR_GRAY_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_color_rgba.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//===================================================================gray8
|
||||
struct gray8
|
||||
{
|
||||
typedef int8u value_type;
|
||||
typedef int32u calc_type;
|
||||
typedef int32 long_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = 8,
|
||||
base_scale = 1 << base_shift,
|
||||
base_mask = base_scale - 1
|
||||
};
|
||||
typedef gray8 self_type;
|
||||
|
||||
value_type v;
|
||||
value_type a;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray8() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray8(unsigned v_, unsigned a_=base_mask) :
|
||||
v(int8u(v_)), a(int8u(a_)) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray8(const self_type& c, unsigned a_) :
|
||||
v(c.v), a(value_type(a_)) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray8(const rgba& c) :
|
||||
v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))),
|
||||
a((value_type)uround(c.a * double(base_mask))) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray8(const rgba& c, double a_) :
|
||||
v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))),
|
||||
a((value_type)uround(a_ * double(base_mask))) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray8(const rgba8& c) :
|
||||
v((c.r*77 + c.g*150 + c.b*29) >> 8),
|
||||
a(c.a) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray8(const rgba8& c, unsigned a_) :
|
||||
v((c.r*77 + c.g*150 + c.b*29) >> 8),
|
||||
a(a_) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clear()
|
||||
{
|
||||
v = a = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& transparent()
|
||||
{
|
||||
a = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void opacity(double a_)
|
||||
{
|
||||
if(a_ < 0.0) a_ = 0.0;
|
||||
if(a_ > 1.0) a_ = 1.0;
|
||||
a = (value_type)uround(a_ * double(base_mask));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
double opacity() const
|
||||
{
|
||||
return double(a) / double(base_mask);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& premultiply()
|
||||
{
|
||||
if(a == base_mask) return *this;
|
||||
if(a == 0)
|
||||
{
|
||||
v = 0;
|
||||
return *this;
|
||||
}
|
||||
v = value_type((calc_type(v) * a) >> base_shift);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& premultiply(unsigned a_)
|
||||
{
|
||||
if(a == base_mask && a_ >= base_mask) return *this;
|
||||
if(a == 0 || a_ == 0)
|
||||
{
|
||||
v = a = 0;
|
||||
return *this;
|
||||
}
|
||||
calc_type v_ = (calc_type(v) * a_) / a;
|
||||
v = value_type((v_ > a_) ? a_ : v_);
|
||||
a = value_type(a_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& demultiply()
|
||||
{
|
||||
if(a == base_mask) return *this;
|
||||
if(a == 0)
|
||||
{
|
||||
v = 0;
|
||||
return *this;
|
||||
}
|
||||
calc_type v_ = (calc_type(v) * base_mask) / a;
|
||||
v = value_type((v_ > base_mask) ? (value_type)base_mask : v_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
self_type gradient(self_type c, double k) const
|
||||
{
|
||||
self_type ret;
|
||||
calc_type ik = uround(k * base_scale);
|
||||
ret.v = value_type(calc_type(v) + (((calc_type(c.v) - v) * ik) >> base_shift));
|
||||
ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift));
|
||||
return ret;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void add(const self_type& c, unsigned cover)
|
||||
{
|
||||
calc_type cv, ca;
|
||||
if(cover == cover_mask)
|
||||
{
|
||||
if(c.a == base_mask)
|
||||
{
|
||||
*this = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
cv = v + c.v; v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv;
|
||||
ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cv = v + ((c.v * cover + cover_mask/2) >> cover_shift);
|
||||
ca = a + ((c.a * cover + cover_mask/2) >> cover_shift);
|
||||
v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv;
|
||||
a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static self_type no_color() { return self_type(0,0); }
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------------gray8_pre
|
||||
inline gray8 gray8_pre(unsigned v, unsigned a = gray8::base_mask)
|
||||
{
|
||||
return gray8(v,a).premultiply();
|
||||
}
|
||||
inline gray8 gray8_pre(const gray8& c, unsigned a)
|
||||
{
|
||||
return gray8(c,a).premultiply();
|
||||
}
|
||||
inline gray8 gray8_pre(const rgba& c)
|
||||
{
|
||||
return gray8(c).premultiply();
|
||||
}
|
||||
inline gray8 gray8_pre(const rgba& c, double a)
|
||||
{
|
||||
return gray8(c,a).premultiply();
|
||||
}
|
||||
inline gray8 gray8_pre(const rgba8& c)
|
||||
{
|
||||
return gray8(c).premultiply();
|
||||
}
|
||||
inline gray8 gray8_pre(const rgba8& c, unsigned a)
|
||||
{
|
||||
return gray8(c,a).premultiply();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//==================================================================gray16
|
||||
struct gray16
|
||||
{
|
||||
typedef int16u value_type;
|
||||
typedef int32u calc_type;
|
||||
typedef int64 long_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = 16,
|
||||
base_scale = 1 << base_shift,
|
||||
base_mask = base_scale - 1
|
||||
};
|
||||
typedef gray16 self_type;
|
||||
|
||||
value_type v;
|
||||
value_type a;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray16() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray16(unsigned v_, unsigned a_=base_mask) :
|
||||
v(int16u(v_)), a(int16u(a_)) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray16(const self_type& c, unsigned a_) :
|
||||
v(c.v), a(value_type(a_)) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray16(const rgba& c) :
|
||||
v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))),
|
||||
a((value_type)uround(c.a * double(base_mask))) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray16(const rgba& c, double a_) :
|
||||
v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))),
|
||||
a((value_type)uround(a_ * double(base_mask))) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray16(const rgba8& c) :
|
||||
v(c.r*77 + c.g*150 + c.b*29),
|
||||
a((value_type(c.a) << 8) | c.a) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray16(const rgba8& c, unsigned a_) :
|
||||
v(c.r*77 + c.g*150 + c.b*29),
|
||||
a((value_type(a_) << 8) | c.a) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clear()
|
||||
{
|
||||
v = a = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& transparent()
|
||||
{
|
||||
a = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void opacity(double a_)
|
||||
{
|
||||
if(a_ < 0.0) a_ = 0.0;
|
||||
if(a_ > 1.0) a_ = 1.0;
|
||||
a = (value_type)uround(a_ * double(base_mask));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
double opacity() const
|
||||
{
|
||||
return double(a) / double(base_mask);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& premultiply()
|
||||
{
|
||||
if(a == base_mask) return *this;
|
||||
if(a == 0)
|
||||
{
|
||||
v = 0;
|
||||
return *this;
|
||||
}
|
||||
v = value_type((calc_type(v) * a) >> base_shift);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& premultiply(unsigned a_)
|
||||
{
|
||||
if(a == base_mask && a_ >= base_mask) return *this;
|
||||
if(a == 0 || a_ == 0)
|
||||
{
|
||||
v = a = 0;
|
||||
return *this;
|
||||
}
|
||||
calc_type v_ = (calc_type(v) * a_) / a;
|
||||
v = value_type((v_ > a_) ? a_ : v_);
|
||||
a = value_type(a_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& demultiply()
|
||||
{
|
||||
if(a == base_mask) return *this;
|
||||
if(a == 0)
|
||||
{
|
||||
v = 0;
|
||||
return *this;
|
||||
}
|
||||
calc_type v_ = (calc_type(v) * base_mask) / a;
|
||||
v = value_type((v_ > base_mask) ? base_mask : v_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
self_type gradient(self_type c, double k) const
|
||||
{
|
||||
self_type ret;
|
||||
calc_type ik = uround(k * base_scale);
|
||||
ret.v = value_type(calc_type(v) + (((calc_type(c.v) - v) * ik) >> base_shift));
|
||||
ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift));
|
||||
return ret;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void add(const self_type& c, unsigned cover)
|
||||
{
|
||||
calc_type cv, ca;
|
||||
if(cover == cover_mask)
|
||||
{
|
||||
if(c.a == base_mask)
|
||||
{
|
||||
*this = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
cv = v + c.v; v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv;
|
||||
ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cv = v + ((c.v * cover + cover_mask/2) >> cover_shift);
|
||||
ca = a + ((c.a * cover + cover_mask/2) >> cover_shift);
|
||||
v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv;
|
||||
a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static self_type no_color() { return self_type(0,0); }
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------gray16_pre
|
||||
inline gray16 gray16_pre(unsigned v, unsigned a = gray16::base_mask)
|
||||
{
|
||||
return gray16(v,a).premultiply();
|
||||
}
|
||||
inline gray16 gray16_pre(const gray16& c, unsigned a)
|
||||
{
|
||||
return gray16(c,a).premultiply();
|
||||
}
|
||||
inline gray16 gray16_pre(const rgba& c)
|
||||
{
|
||||
return gray16(c).premultiply();
|
||||
}
|
||||
inline gray16 gray16_pre(const rgba& c, double a)
|
||||
{
|
||||
return gray16(c,a).premultiply();
|
||||
}
|
||||
inline gray16 gray16_pre(const rgba8& c)
|
||||
{
|
||||
return gray16(c).premultiply();
|
||||
}
|
||||
inline gray16 gray16_pre(const rgba8& c, unsigned a)
|
||||
{
|
||||
return gray16(c,a).premultiply();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,756 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for high precision colors has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_COLOR_RGBA_INCLUDED
|
||||
#define AGG_COLOR_RGBA_INCLUDED
|
||||
|
||||
#include <math.h>
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
// Supported byte orders for RGB and RGBA pixel formats
|
||||
//=======================================================================
|
||||
struct order_rgb { enum rgb_e { R=0, G=1, B=2, rgb_tag }; }; //----order_rgb
|
||||
struct order_bgr { enum bgr_e { B=0, G=1, R=2, rgb_tag }; }; //----order_bgr
|
||||
struct order_rgba { enum rgba_e { R=0, G=1, B=2, A=3, rgba_tag }; }; //----order_rgba
|
||||
struct order_argb { enum argb_e { A=0, R=1, G=2, B=3, rgba_tag }; }; //----order_argb
|
||||
struct order_abgr { enum abgr_e { A=0, B=1, G=2, R=3, rgba_tag }; }; //----order_abgr
|
||||
struct order_bgra { enum bgra_e { B=0, G=1, R=2, A=3, rgba_tag }; }; //----order_bgra
|
||||
|
||||
//====================================================================rgba
|
||||
struct rgba
|
||||
{
|
||||
typedef double value_type;
|
||||
|
||||
double r;
|
||||
double g;
|
||||
double b;
|
||||
double a;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba(double r_, double g_, double b_, double a_=1.0) :
|
||||
r(r_), g(g_), b(b_), a(a_) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba(const rgba& c, double a_) : r(c.r), g(c.g), b(c.b), a(a_) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clear()
|
||||
{
|
||||
r = g = b = a = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const rgba& transparent()
|
||||
{
|
||||
a = 0.0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const rgba& opacity(double a_)
|
||||
{
|
||||
if(a_ < 0.0) a_ = 0.0;
|
||||
if(a_ > 1.0) a_ = 1.0;
|
||||
a = a_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
double opacity() const
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const rgba& premultiply()
|
||||
{
|
||||
r *= a;
|
||||
g *= a;
|
||||
b *= a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const rgba& premultiply(double a_)
|
||||
{
|
||||
if(a <= 0.0 || a_ <= 0.0)
|
||||
{
|
||||
r = g = b = a = 0.0;
|
||||
return *this;
|
||||
}
|
||||
a_ /= a;
|
||||
r *= a_;
|
||||
g *= a_;
|
||||
b *= a_;
|
||||
a = a_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const rgba& demultiply()
|
||||
{
|
||||
if(a == 0)
|
||||
{
|
||||
r = g = b = 0;
|
||||
return *this;
|
||||
}
|
||||
double a_ = 1.0 / a;
|
||||
r *= a_;
|
||||
g *= a_;
|
||||
b *= a_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba gradient(rgba c, double k) const
|
||||
{
|
||||
rgba ret;
|
||||
ret.r = r + (c.r - r) * k;
|
||||
ret.g = g + (c.g - g) * k;
|
||||
ret.b = b + (c.b - b) * k;
|
||||
ret.a = a + (c.a - a) * k;
|
||||
return ret;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static rgba no_color() { return rgba(0,0,0,0); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static rgba from_wavelength(double wl, double gamma = 1.0);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
explicit rgba(double wavelen, double gamma=1.0)
|
||||
{
|
||||
*this = from_wavelength(wavelen, gamma);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------rgba_pre
|
||||
inline rgba rgba_pre(double r, double g, double b, double a=1.0)
|
||||
{
|
||||
return rgba(r, g, b, a).premultiply();
|
||||
}
|
||||
inline rgba rgba_pre(const rgba& c)
|
||||
{
|
||||
return rgba(c).premultiply();
|
||||
}
|
||||
inline rgba rgba_pre(const rgba& c, double a)
|
||||
{
|
||||
return rgba(c, a).premultiply();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline rgba rgba::from_wavelength(double wl, double gamma)
|
||||
{
|
||||
rgba t(0.0, 0.0, 0.0);
|
||||
|
||||
if(wl >= 380.0 && wl <= 440.0)
|
||||
{
|
||||
t.r = -1.0 * (wl - 440.0) / (440.0 - 380.0);
|
||||
t.b = 1.0;
|
||||
}
|
||||
else
|
||||
if(wl >= 440.0 && wl <= 490.0)
|
||||
{
|
||||
t.g = (wl - 440.0) / (490.0 - 440.0);
|
||||
t.b = 1.0;
|
||||
}
|
||||
else
|
||||
if(wl >= 490.0 && wl <= 510.0)
|
||||
{
|
||||
t.g = 1.0;
|
||||
t.b = -1.0 * (wl - 510.0) / (510.0 - 490.0);
|
||||
}
|
||||
else
|
||||
if(wl >= 510.0 && wl <= 580.0)
|
||||
{
|
||||
t.r = (wl - 510.0) / (580.0 - 510.0);
|
||||
t.g = 1.0;
|
||||
}
|
||||
else
|
||||
if(wl >= 580.0 && wl <= 645.0)
|
||||
{
|
||||
t.r = 1.0;
|
||||
t.g = -1.0 * (wl - 645.0) / (645.0 - 580.0);
|
||||
}
|
||||
else
|
||||
if(wl >= 645.0 && wl <= 780.0)
|
||||
{
|
||||
t.r = 1.0;
|
||||
}
|
||||
|
||||
double s = 1.0;
|
||||
if(wl > 700.0) s = 0.3 + 0.7 * (780.0 - wl) / (780.0 - 700.0);
|
||||
else if(wl < 420.0) s = 0.3 + 0.7 * (wl - 380.0) / (420.0 - 380.0);
|
||||
|
||||
t.r = pow(t.r * s, gamma);
|
||||
t.g = pow(t.g * s, gamma);
|
||||
t.b = pow(t.b * s, gamma);
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//===================================================================rgba8
|
||||
struct rgba8
|
||||
{
|
||||
typedef int8u value_type;
|
||||
typedef int32u calc_type;
|
||||
typedef int32 long_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = 8,
|
||||
base_scale = 1 << base_shift,
|
||||
base_mask = base_scale - 1
|
||||
};
|
||||
typedef rgba8 self_type;
|
||||
|
||||
|
||||
value_type r;
|
||||
value_type g;
|
||||
value_type b;
|
||||
value_type a;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba8() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba8(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) :
|
||||
r(value_type(r_)),
|
||||
g(value_type(g_)),
|
||||
b(value_type(b_)),
|
||||
a(value_type(a_)) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba8(const rgba& c, double a_) :
|
||||
r((value_type)uround(c.r * double(base_mask))),
|
||||
g((value_type)uround(c.g * double(base_mask))),
|
||||
b((value_type)uround(c.b * double(base_mask))),
|
||||
a((value_type)uround(a_ * double(base_mask))) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba8(const self_type& c, unsigned a_) :
|
||||
r(c.r), g(c.g), b(c.b), a(value_type(a_)) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba8(const rgba& c) :
|
||||
r((value_type)uround(c.r * double(base_mask))),
|
||||
g((value_type)uround(c.g * double(base_mask))),
|
||||
b((value_type)uround(c.b * double(base_mask))),
|
||||
a((value_type)uround(c.a * double(base_mask))) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clear()
|
||||
{
|
||||
r = g = b = a = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& transparent()
|
||||
{
|
||||
a = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& opacity(double a_)
|
||||
{
|
||||
if(a_ < 0.0) a_ = 0.0;
|
||||
if(a_ > 1.0) a_ = 1.0;
|
||||
a = (value_type)uround(a_ * double(base_mask));
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
double opacity() const
|
||||
{
|
||||
return double(a) / double(base_mask);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE const self_type& premultiply()
|
||||
{
|
||||
if(a == base_mask) return *this;
|
||||
if(a == 0)
|
||||
{
|
||||
r = g = b = 0;
|
||||
return *this;
|
||||
}
|
||||
r = value_type((calc_type(r) * a) >> base_shift);
|
||||
g = value_type((calc_type(g) * a) >> base_shift);
|
||||
b = value_type((calc_type(b) * a) >> base_shift);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE const self_type& premultiply(unsigned a_)
|
||||
{
|
||||
if(a == base_mask && a_ >= base_mask) return *this;
|
||||
if(a == 0 || a_ == 0)
|
||||
{
|
||||
r = g = b = a = 0;
|
||||
return *this;
|
||||
}
|
||||
calc_type r_ = (calc_type(r) * a_) / a;
|
||||
calc_type g_ = (calc_type(g) * a_) / a;
|
||||
calc_type b_ = (calc_type(b) * a_) / a;
|
||||
r = value_type((r_ > a_) ? a_ : r_);
|
||||
g = value_type((g_ > a_) ? a_ : g_);
|
||||
b = value_type((b_ > a_) ? a_ : b_);
|
||||
a = value_type(a_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE const self_type& demultiply()
|
||||
{
|
||||
if(a == base_mask) return *this;
|
||||
if(a == 0)
|
||||
{
|
||||
r = g = b = 0;
|
||||
return *this;
|
||||
}
|
||||
calc_type r_ = (calc_type(r) * base_mask) / a;
|
||||
calc_type g_ = (calc_type(g) * base_mask) / a;
|
||||
calc_type b_ = (calc_type(b) * base_mask) / a;
|
||||
r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_);
|
||||
g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_);
|
||||
b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE self_type gradient(const self_type& c, double k) const
|
||||
{
|
||||
self_type ret;
|
||||
calc_type ik = uround(k * base_scale);
|
||||
ret.r = value_type(calc_type(r) + (((calc_type(c.r) - r) * ik) >> base_shift));
|
||||
ret.g = value_type(calc_type(g) + (((calc_type(c.g) - g) * ik) >> base_shift));
|
||||
ret.b = value_type(calc_type(b) + (((calc_type(c.b) - b) * ik) >> base_shift));
|
||||
ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift));
|
||||
return ret;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void add(const self_type& c, unsigned cover)
|
||||
{
|
||||
calc_type cr, cg, cb, ca;
|
||||
if(cover == cover_mask)
|
||||
{
|
||||
if(c.a == base_mask)
|
||||
{
|
||||
*this = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
cr = r + c.r; r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr;
|
||||
cg = g + c.g; g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg;
|
||||
cb = b + c.b; b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb;
|
||||
ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cr = r + ((c.r * cover + cover_mask/2) >> cover_shift);
|
||||
cg = g + ((c.g * cover + cover_mask/2) >> cover_shift);
|
||||
cb = b + ((c.b * cover + cover_mask/2) >> cover_shift);
|
||||
ca = a + ((c.a * cover + cover_mask/2) >> cover_shift);
|
||||
r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr;
|
||||
g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg;
|
||||
b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb;
|
||||
a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaLUT>
|
||||
AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma)
|
||||
{
|
||||
r = gamma.dir(r);
|
||||
g = gamma.dir(g);
|
||||
b = gamma.dir(b);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaLUT>
|
||||
AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma)
|
||||
{
|
||||
r = gamma.inv(r);
|
||||
g = gamma.inv(g);
|
||||
b = gamma.inv(b);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static self_type no_color() { return self_type(0,0,0,0); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static self_type from_wavelength(double wl, double gamma = 1.0)
|
||||
{
|
||||
return self_type(rgba::from_wavelength(wl, gamma));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------------rgba8_pre
|
||||
inline rgba8 rgba8_pre(unsigned r, unsigned g, unsigned b,
|
||||
unsigned a = rgba8::base_mask)
|
||||
{
|
||||
return rgba8(r,g,b,a).premultiply();
|
||||
}
|
||||
inline rgba8 rgba8_pre(const rgba8& c)
|
||||
{
|
||||
return rgba8(c).premultiply();
|
||||
}
|
||||
inline rgba8 rgba8_pre(const rgba8& c, unsigned a)
|
||||
{
|
||||
return rgba8(c,a).premultiply();
|
||||
}
|
||||
inline rgba8 rgba8_pre(const rgba& c)
|
||||
{
|
||||
return rgba8(c).premultiply();
|
||||
}
|
||||
inline rgba8 rgba8_pre(const rgba& c, double a)
|
||||
{
|
||||
return rgba8(c,a).premultiply();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------rgb8_packed
|
||||
inline rgba8 rgb8_packed(unsigned v)
|
||||
{
|
||||
return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------bgr8_packed
|
||||
inline rgba8 bgr8_packed(unsigned v)
|
||||
{
|
||||
return rgba8(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------argb8_packed
|
||||
inline rgba8 argb8_packed(unsigned v)
|
||||
{
|
||||
return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF, v >> 24);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------rgba8_gamma_dir
|
||||
template<class GammaLUT>
|
||||
rgba8 rgba8_gamma_dir(rgba8 c, const GammaLUT& gamma)
|
||||
{
|
||||
return rgba8(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------rgba8_gamma_inv
|
||||
template<class GammaLUT>
|
||||
rgba8 rgba8_gamma_inv(rgba8 c, const GammaLUT& gamma)
|
||||
{
|
||||
return rgba8(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//==================================================================rgba16
|
||||
struct rgba16
|
||||
{
|
||||
typedef int16u value_type;
|
||||
typedef int32u calc_type;
|
||||
typedef int64 long_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = 16,
|
||||
base_scale = 1 << base_shift,
|
||||
base_mask = base_scale - 1
|
||||
};
|
||||
typedef rgba16 self_type;
|
||||
|
||||
value_type r;
|
||||
value_type g;
|
||||
value_type b;
|
||||
value_type a;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba16() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba16(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) :
|
||||
r(value_type(r_)),
|
||||
g(value_type(g_)),
|
||||
b(value_type(b_)),
|
||||
a(value_type(a_)) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba16(const self_type& c, unsigned a_) :
|
||||
r(c.r), g(c.g), b(c.b), a(value_type(a_)) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba16(const rgba& c) :
|
||||
r((value_type)uround(c.r * double(base_mask))),
|
||||
g((value_type)uround(c.g * double(base_mask))),
|
||||
b((value_type)uround(c.b * double(base_mask))),
|
||||
a((value_type)uround(c.a * double(base_mask))) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba16(const rgba& c, double a_) :
|
||||
r((value_type)uround(c.r * double(base_mask))),
|
||||
g((value_type)uround(c.g * double(base_mask))),
|
||||
b((value_type)uround(c.b * double(base_mask))),
|
||||
a((value_type)uround(a_ * double(base_mask))) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba16(const rgba8& c) :
|
||||
r(value_type((value_type(c.r) << 8) | c.r)),
|
||||
g(value_type((value_type(c.g) << 8) | c.g)),
|
||||
b(value_type((value_type(c.b) << 8) | c.b)),
|
||||
a(value_type((value_type(c.a) << 8) | c.a)) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rgba16(const rgba8& c, unsigned a_) :
|
||||
r(value_type((value_type(c.r) << 8) | c.r)),
|
||||
g(value_type((value_type(c.g) << 8) | c.g)),
|
||||
b(value_type((value_type(c.b) << 8) | c.b)),
|
||||
a(value_type(( a_ << 8) | c.a)) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clear()
|
||||
{
|
||||
r = g = b = a = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& transparent()
|
||||
{
|
||||
a = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE const self_type& opacity(double a_)
|
||||
{
|
||||
if(a_ < 0.0) a_ = 0.0;
|
||||
if(a_ > 1.0) a_ = 1.0;
|
||||
a = (value_type)uround(a_ * double(base_mask));
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
double opacity() const
|
||||
{
|
||||
return double(a) / double(base_mask);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE const self_type& premultiply()
|
||||
{
|
||||
if(a == base_mask) return *this;
|
||||
if(a == 0)
|
||||
{
|
||||
r = g = b = 0;
|
||||
return *this;
|
||||
}
|
||||
r = value_type((calc_type(r) * a) >> base_shift);
|
||||
g = value_type((calc_type(g) * a) >> base_shift);
|
||||
b = value_type((calc_type(b) * a) >> base_shift);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE const self_type& premultiply(unsigned a_)
|
||||
{
|
||||
if(a == base_mask && a_ >= base_mask) return *this;
|
||||
if(a == 0 || a_ == 0)
|
||||
{
|
||||
r = g = b = a = 0;
|
||||
return *this;
|
||||
}
|
||||
calc_type r_ = (calc_type(r) * a_) / a;
|
||||
calc_type g_ = (calc_type(g) * a_) / a;
|
||||
calc_type b_ = (calc_type(b) * a_) / a;
|
||||
r = value_type((r_ > a_) ? a_ : r_);
|
||||
g = value_type((g_ > a_) ? a_ : g_);
|
||||
b = value_type((b_ > a_) ? a_ : b_);
|
||||
a = value_type(a_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE const self_type& demultiply()
|
||||
{
|
||||
if(a == base_mask) return *this;
|
||||
if(a == 0)
|
||||
{
|
||||
r = g = b = 0;
|
||||
return *this;
|
||||
}
|
||||
calc_type r_ = (calc_type(r) * base_mask) / a;
|
||||
calc_type g_ = (calc_type(g) * base_mask) / a;
|
||||
calc_type b_ = (calc_type(b) * base_mask) / a;
|
||||
r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_);
|
||||
g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_);
|
||||
b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE self_type gradient(const self_type& c, double k) const
|
||||
{
|
||||
self_type ret;
|
||||
calc_type ik = uround(k * base_scale);
|
||||
ret.r = value_type(calc_type(r) + (((calc_type(c.r) - r) * ik) >> base_shift));
|
||||
ret.g = value_type(calc_type(g) + (((calc_type(c.g) - g) * ik) >> base_shift));
|
||||
ret.b = value_type(calc_type(b) + (((calc_type(c.b) - b) * ik) >> base_shift));
|
||||
ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift));
|
||||
return ret;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void add(const self_type& c, unsigned cover)
|
||||
{
|
||||
calc_type cr, cg, cb, ca;
|
||||
if(cover == cover_mask)
|
||||
{
|
||||
if(c.a == base_mask)
|
||||
{
|
||||
*this = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
cr = r + c.r; r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr;
|
||||
cg = g + c.g; g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg;
|
||||
cb = b + c.b; b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb;
|
||||
ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cr = r + ((c.r * cover + cover_mask) >> cover_shift);
|
||||
cg = g + ((c.g * cover + cover_mask) >> cover_shift);
|
||||
cb = b + ((c.b * cover + cover_mask) >> cover_shift);
|
||||
ca = a + ((c.a * cover + cover_mask) >> cover_shift);
|
||||
r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr;
|
||||
g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg;
|
||||
b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb;
|
||||
a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaLUT>
|
||||
AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma)
|
||||
{
|
||||
r = gamma.dir(r);
|
||||
g = gamma.dir(g);
|
||||
b = gamma.dir(b);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaLUT>
|
||||
AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma)
|
||||
{
|
||||
r = gamma.inv(r);
|
||||
g = gamma.inv(g);
|
||||
b = gamma.inv(b);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static self_type no_color() { return self_type(0,0,0,0); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static self_type from_wavelength(double wl, double gamma = 1.0)
|
||||
{
|
||||
return self_type(rgba::from_wavelength(wl, gamma));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------rgba16_pre
|
||||
inline rgba16 rgba16_pre(unsigned r, unsigned g, unsigned b,
|
||||
unsigned a = rgba16::base_mask)
|
||||
{
|
||||
return rgba16(r,g,b,a).premultiply();
|
||||
}
|
||||
inline rgba16 rgba16_pre(const rgba16& c, unsigned a)
|
||||
{
|
||||
return rgba16(c,a).premultiply();
|
||||
}
|
||||
inline rgba16 rgba16_pre(const rgba& c)
|
||||
{
|
||||
return rgba16(c).premultiply();
|
||||
}
|
||||
inline rgba16 rgba16_pre(const rgba& c, double a)
|
||||
{
|
||||
return rgba16(c,a).premultiply();
|
||||
}
|
||||
inline rgba16 rgba16_pre(const rgba8& c)
|
||||
{
|
||||
return rgba16(c).premultiply();
|
||||
}
|
||||
inline rgba16 rgba16_pre(const rgba8& c, unsigned a)
|
||||
{
|
||||
return rgba16(c,a).premultiply();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------rgba16_gamma_dir
|
||||
template<class GammaLUT>
|
||||
rgba16 rgba16_gamma_dir(rgba16 c, const GammaLUT& gamma)
|
||||
{
|
||||
return rgba16(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a);
|
||||
}
|
||||
|
||||
//------------------------------------------------------rgba16_gamma_inv
|
||||
template<class GammaLUT>
|
||||
rgba16 rgba16_gamma_inv(rgba16 c, const GammaLUT& gamma)
|
||||
{
|
||||
return rgba16(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,44 @@
|
|||
#ifndef AGG_CONFIG_INCLUDED
|
||||
#define AGG_CONFIG_INCLUDED
|
||||
|
||||
// This file can be used to redefine certain data types.
|
||||
|
||||
//---------------------------------------
|
||||
// 1. Default basic types such as:
|
||||
//
|
||||
// AGG_INT8
|
||||
// AGG_INT8U
|
||||
// AGG_INT16
|
||||
// AGG_INT16U
|
||||
// AGG_INT32
|
||||
// AGG_INT32U
|
||||
// AGG_INT64
|
||||
// AGG_INT64U
|
||||
//
|
||||
// Just replace this file with new defines if necessary.
|
||||
// For example, if your compiler doesn't have a 64 bit integer type
|
||||
// you can still use AGG if you define the follows:
|
||||
//
|
||||
// #define AGG_INT64 int
|
||||
// #define AGG_INT64U unsigned
|
||||
//
|
||||
// It will result in overflow in 16 bit-per-component image/pattern resampling
|
||||
// but it won't result any crash and the rest of the library will remain
|
||||
// fully functional.
|
||||
|
||||
|
||||
//---------------------------------------
|
||||
// 2. Default rendering_buffer type. Can be:
|
||||
//
|
||||
// Provides faster access for massive pixel operations,
|
||||
// such as blur, image filtering:
|
||||
// #define AGG_RENDERING_BUFFER row_ptr_cache<int8u>
|
||||
//
|
||||
// Provides cheaper creation and destruction (no mem allocs):
|
||||
// #define AGG_RENDERING_BUFFER row_accessor<int8u>
|
||||
//
|
||||
// You can still use both of them simultaneouslyin your applications
|
||||
// This #define is used only for default rendering_buffer type,
|
||||
// in short hand typedefs like pixfmt_rgba32.
|
||||
|
||||
#endif
|
|
@ -0,0 +1,166 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_ADAPTOR_VCGEN_INCLUDED
|
||||
#define AGG_CONV_ADAPTOR_VCGEN_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//------------------------------------------------------------null_markers
|
||||
struct null_markers
|
||||
{
|
||||
void remove_all() {}
|
||||
void add_vertex(double, double, unsigned) {}
|
||||
void prepare_src() {}
|
||||
|
||||
void rewind(unsigned) {}
|
||||
unsigned vertex(double*, double*) { return path_cmd_stop; }
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------conv_adaptor_vcgen
|
||||
template<class VertexSource,
|
||||
class Generator,
|
||||
class Markers=null_markers> class conv_adaptor_vcgen
|
||||
{
|
||||
enum status
|
||||
{
|
||||
initial,
|
||||
accumulate,
|
||||
generate
|
||||
};
|
||||
|
||||
public:
|
||||
explicit conv_adaptor_vcgen(VertexSource& source) :
|
||||
m_source(&source),
|
||||
m_status(initial)
|
||||
{}
|
||||
void attach(VertexSource& source) { m_source = &source; }
|
||||
|
||||
Generator& generator() { return m_generator; }
|
||||
const Generator& generator() const { return m_generator; }
|
||||
|
||||
Markers& markers() { return m_markers; }
|
||||
const Markers& markers() const { return m_markers; }
|
||||
|
||||
void rewind(unsigned path_id)
|
||||
{
|
||||
m_source->rewind(path_id);
|
||||
m_status = initial;
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
// Prohibit copying
|
||||
conv_adaptor_vcgen(const conv_adaptor_vcgen<VertexSource, Generator, Markers>&);
|
||||
const conv_adaptor_vcgen<VertexSource, Generator, Markers>&
|
||||
operator = (const conv_adaptor_vcgen<VertexSource, Generator, Markers>&);
|
||||
|
||||
VertexSource* m_source;
|
||||
Generator m_generator;
|
||||
Markers m_markers;
|
||||
status m_status;
|
||||
unsigned m_last_cmd;
|
||||
double m_start_x;
|
||||
double m_start_y;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource, class Generator, class Markers>
|
||||
unsigned conv_adaptor_vcgen<VertexSource, Generator, Markers>::vertex(double* x, double* y)
|
||||
{
|
||||
unsigned cmd = path_cmd_stop;
|
||||
bool done = false;
|
||||
while(!done)
|
||||
{
|
||||
switch(m_status)
|
||||
{
|
||||
case initial:
|
||||
m_markers.remove_all();
|
||||
m_last_cmd = m_source->vertex(&m_start_x, &m_start_y);
|
||||
m_status = accumulate;
|
||||
|
||||
case accumulate:
|
||||
if(is_stop(m_last_cmd)) return path_cmd_stop;
|
||||
|
||||
m_generator.remove_all();
|
||||
m_generator.add_vertex(m_start_x, m_start_y, path_cmd_move_to);
|
||||
m_markers.add_vertex(m_start_x, m_start_y, path_cmd_move_to);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
cmd = m_source->vertex(x, y);
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
m_last_cmd = cmd;
|
||||
if(is_move_to(cmd))
|
||||
{
|
||||
m_start_x = *x;
|
||||
m_start_y = *y;
|
||||
break;
|
||||
}
|
||||
m_generator.add_vertex(*x, *y, cmd);
|
||||
m_markers.add_vertex(*x, *y, path_cmd_line_to);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_stop(cmd))
|
||||
{
|
||||
m_last_cmd = path_cmd_stop;
|
||||
break;
|
||||
}
|
||||
if(is_end_poly(cmd))
|
||||
{
|
||||
m_generator.add_vertex(*x, *y, cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_generator.rewind(0);
|
||||
m_status = generate;
|
||||
|
||||
case generate:
|
||||
cmd = m_generator.vertex(x, y);
|
||||
if(is_stop(cmd))
|
||||
{
|
||||
m_status = accumulate;
|
||||
break;
|
||||
}
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,168 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_ADAPTOR_VPGEN_INCLUDED
|
||||
#define AGG_CONV_ADAPTOR_VPGEN_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//======================================================conv_adaptor_vpgen
|
||||
template<class VertexSource, class VPGen> class conv_adaptor_vpgen
|
||||
{
|
||||
public:
|
||||
explicit conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {}
|
||||
void attach(VertexSource& source) { m_source = &source; }
|
||||
|
||||
VPGen& vpgen() { return m_vpgen; }
|
||||
const VPGen& vpgen() const { return m_vpgen; }
|
||||
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
conv_adaptor_vpgen(const conv_adaptor_vpgen<VertexSource, VPGen>&);
|
||||
const conv_adaptor_vpgen<VertexSource, VPGen>&
|
||||
operator = (const conv_adaptor_vpgen<VertexSource, VPGen>&);
|
||||
|
||||
VertexSource* m_source;
|
||||
VPGen m_vpgen;
|
||||
double m_start_x;
|
||||
double m_start_y;
|
||||
unsigned m_poly_flags;
|
||||
int m_vertices;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource, class VPGen>
|
||||
void conv_adaptor_vpgen<VertexSource, VPGen>::rewind(unsigned path_id)
|
||||
{
|
||||
m_source->rewind(path_id);
|
||||
m_vpgen.reset();
|
||||
m_start_x = 0;
|
||||
m_start_y = 0;
|
||||
m_poly_flags = 0;
|
||||
m_vertices = 0;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource, class VPGen>
|
||||
unsigned conv_adaptor_vpgen<VertexSource, VPGen>::vertex(double* x, double* y)
|
||||
{
|
||||
unsigned cmd = path_cmd_stop;
|
||||
for(;;)
|
||||
{
|
||||
cmd = m_vpgen.vertex(x, y);
|
||||
if(!is_stop(cmd)) break;
|
||||
|
||||
if(m_poly_flags && !m_vpgen.auto_unclose())
|
||||
{
|
||||
*x = 0.0;
|
||||
*y = 0.0;
|
||||
cmd = m_poly_flags;
|
||||
m_poly_flags = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if(m_vertices < 0)
|
||||
{
|
||||
if(m_vertices < -1)
|
||||
{
|
||||
m_vertices = 0;
|
||||
return path_cmd_stop;
|
||||
}
|
||||
m_vpgen.move_to(m_start_x, m_start_y);
|
||||
m_vertices = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
double tx, ty;
|
||||
cmd = m_source->vertex(&tx, &ty);
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
if(is_move_to(cmd))
|
||||
{
|
||||
if(m_vpgen.auto_close() && m_vertices > 2)
|
||||
{
|
||||
m_vpgen.line_to(m_start_x, m_start_y);
|
||||
m_poly_flags = path_cmd_end_poly | path_flags_close;
|
||||
m_start_x = tx;
|
||||
m_start_y = ty;
|
||||
m_vertices = -1;
|
||||
continue;
|
||||
}
|
||||
m_vpgen.move_to(tx, ty);
|
||||
m_start_x = tx;
|
||||
m_start_y = ty;
|
||||
m_vertices = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vpgen.line_to(tx, ty);
|
||||
++m_vertices;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_end_poly(cmd))
|
||||
{
|
||||
m_poly_flags = cmd;
|
||||
if(is_closed(cmd) || m_vpgen.auto_close())
|
||||
{
|
||||
if(m_vpgen.auto_close()) m_poly_flags |= path_flags_close;
|
||||
if(m_vertices > 2)
|
||||
{
|
||||
m_vpgen.line_to(m_start_x, m_start_y);
|
||||
}
|
||||
m_vertices = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// path_cmd_stop
|
||||
if(m_vpgen.auto_close() && m_vertices > 2)
|
||||
{
|
||||
m_vpgen.line_to(m_start_x, m_start_y);
|
||||
m_poly_flags = path_cmd_end_poly | path_flags_close;
|
||||
m_vertices = -2;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_BSPLINE_INCLUDED
|
||||
#define AGG_CONV_BSPLINE_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_vcgen_bspline.h"
|
||||
#include "agg_conv_adaptor_vcgen.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//---------------------------------------------------------conv_bspline
|
||||
template<class VertexSource>
|
||||
struct conv_bspline : public conv_adaptor_vcgen<VertexSource, vcgen_bspline>
|
||||
{
|
||||
typedef conv_adaptor_vcgen<VertexSource, vcgen_bspline> base_type;
|
||||
|
||||
conv_bspline(VertexSource& vs) :
|
||||
conv_adaptor_vcgen<VertexSource, vcgen_bspline>(vs) {}
|
||||
|
||||
void interpolation_step(double v) { base_type::generator().interpolation_step(v); }
|
||||
double interpolation_step() const { return base_type::generator().interpolation_step(); }
|
||||
|
||||
private:
|
||||
conv_bspline(const conv_bspline<VertexSource>&);
|
||||
const conv_bspline<VertexSource>&
|
||||
operator = (const conv_bspline<VertexSource>&);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Polygon clipping converter
|
||||
// There an optimized Liang-Basky algorithm is used.
|
||||
// The algorithm doesn't optimize the degenerate edges, i.e. it will never
|
||||
// break a closed polygon into two or more ones, instead, there will be
|
||||
// degenerate edges coinciding with the respective clipping boundaries.
|
||||
// This is a sub-optimal solution, because that optimization would require
|
||||
// extra, rather expensive math while the rasterizer tolerates it quite well,
|
||||
// without any considerable overhead.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_CONV_CLIP_POLYGON_INCLUDED
|
||||
#define AGG_CONV_CLIP_POLYGON_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_conv_adaptor_vpgen.h"
|
||||
#include "agg_vpgen_clip_polygon.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=======================================================conv_clip_polygon
|
||||
template<class VertexSource>
|
||||
struct conv_clip_polygon : public conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon>
|
||||
{
|
||||
typedef conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon> base_type;
|
||||
|
||||
conv_clip_polygon(VertexSource& vs) :
|
||||
conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon>(vs) {}
|
||||
|
||||
void clip_box(double x1, double y1, double x2, double y2)
|
||||
{
|
||||
base_type::vpgen().clip_box(x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
double x1() const { return base_type::vpgen().x1(); }
|
||||
double y1() const { return base_type::vpgen().y1(); }
|
||||
double x2() const { return base_type::vpgen().x2(); }
|
||||
double y2() const { return base_type::vpgen().y2(); }
|
||||
|
||||
private:
|
||||
conv_clip_polygon(const conv_clip_polygon<VertexSource>&);
|
||||
const conv_clip_polygon<VertexSource>&
|
||||
operator = (const conv_clip_polygon<VertexSource>&);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,72 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// polyline clipping converter
|
||||
// There an optimized Liang-Basky algorithm is used.
|
||||
// The algorithm doesn't optimize the degenerate edges, i.e. it will never
|
||||
// break a closed polyline into two or more ones, instead, there will be
|
||||
// degenerate edges coinciding with the respective clipping boundaries.
|
||||
// This is a sub-optimal solution, because that optimization would require
|
||||
// extra, rather expensive math while the rasterizer tolerates it quite well,
|
||||
// without any considerable overhead.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_CONV_CLIP_polyline_INCLUDED
|
||||
#define AGG_CONV_CLIP_polyline_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_conv_adaptor_vpgen.h"
|
||||
#include "agg_vpgen_clip_polyline.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=======================================================conv_clip_polyline
|
||||
template<class VertexSource>
|
||||
struct conv_clip_polyline : public conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline>
|
||||
{
|
||||
typedef conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline> base_type;
|
||||
|
||||
conv_clip_polyline(VertexSource& vs) :
|
||||
conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline>(vs) {}
|
||||
|
||||
void clip_box(double x1, double y1, double x2, double y2)
|
||||
{
|
||||
base_type::vpgen().clip_box(x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
double x1() const { return base_type::vpgen().x1(); }
|
||||
double y1() const { return base_type::vpgen().y1(); }
|
||||
double x2() const { return base_type::vpgen().x2(); }
|
||||
double y2() const { return base_type::vpgen().y2(); }
|
||||
|
||||
private:
|
||||
conv_clip_polyline(const conv_clip_polyline<VertexSource>&);
|
||||
const conv_clip_polyline<VertexSource>&
|
||||
operator = (const conv_clip_polyline<VertexSource>&);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,134 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_CLOSE_POLYGON_INCLUDED
|
||||
#define AGG_CONV_CLOSE_POLYGON_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//======================================================conv_close_polygon
|
||||
template<class VertexSource> class conv_close_polygon
|
||||
{
|
||||
public:
|
||||
explicit conv_close_polygon(VertexSource& vs) : m_source(&vs) {}
|
||||
void attach(VertexSource& source) { m_source = &source; }
|
||||
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
conv_close_polygon(const conv_close_polygon<VertexSource>&);
|
||||
const conv_close_polygon<VertexSource>&
|
||||
operator = (const conv_close_polygon<VertexSource>&);
|
||||
|
||||
VertexSource* m_source;
|
||||
unsigned m_cmd[2];
|
||||
double m_x[2];
|
||||
double m_y[2];
|
||||
unsigned m_vertex;
|
||||
bool m_line_to;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource>
|
||||
void conv_close_polygon<VertexSource>::rewind(unsigned path_id)
|
||||
{
|
||||
m_source->rewind(path_id);
|
||||
m_vertex = 2;
|
||||
m_line_to = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource>
|
||||
unsigned conv_close_polygon<VertexSource>::vertex(double* x, double* y)
|
||||
{
|
||||
unsigned cmd = path_cmd_stop;
|
||||
for(;;)
|
||||
{
|
||||
if(m_vertex < 2)
|
||||
{
|
||||
*x = m_x[m_vertex];
|
||||
*y = m_y[m_vertex];
|
||||
cmd = m_cmd[m_vertex];
|
||||
++m_vertex;
|
||||
break;
|
||||
}
|
||||
|
||||
cmd = m_source->vertex(x, y);
|
||||
|
||||
if(is_end_poly(cmd))
|
||||
{
|
||||
cmd |= path_flags_close;
|
||||
break;
|
||||
}
|
||||
|
||||
if(is_stop(cmd))
|
||||
{
|
||||
if(m_line_to)
|
||||
{
|
||||
m_cmd[0] = path_cmd_end_poly | path_flags_close;
|
||||
m_cmd[1] = path_cmd_stop;
|
||||
m_vertex = 0;
|
||||
m_line_to = false;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(is_move_to(cmd))
|
||||
{
|
||||
if(m_line_to)
|
||||
{
|
||||
m_x[0] = 0.0;
|
||||
m_y[0] = 0.0;
|
||||
m_cmd[0] = path_cmd_end_poly | path_flags_close;
|
||||
m_x[1] = *x;
|
||||
m_y[1] = *y;
|
||||
m_cmd[1] = cmd;
|
||||
m_vertex = 0;
|
||||
m_line_to = false;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
m_line_to = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,82 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_CONCAT_INCLUDED
|
||||
#define AGG_CONV_CONCAT_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//=============================================================conv_concat
|
||||
// Concatenation of two paths. Usually used to combine lines or curves
|
||||
// with markers such as arrowheads
|
||||
template<class VS1, class VS2> class conv_concat
|
||||
{
|
||||
public:
|
||||
conv_concat(VS1& source1, VS2& source2) :
|
||||
m_source1(&source1), m_source2(&source2), m_status(2) {}
|
||||
void attach1(VS1& source) { m_source1 = &source; }
|
||||
void attach2(VS2& source) { m_source2 = &source; }
|
||||
|
||||
|
||||
void rewind(unsigned path_id)
|
||||
{
|
||||
m_source1->rewind(path_id);
|
||||
m_source2->rewind(0);
|
||||
m_status = 0;
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
unsigned cmd;
|
||||
if(m_status == 0)
|
||||
{
|
||||
cmd = m_source1->vertex(x, y);
|
||||
if(!is_stop(cmd)) return cmd;
|
||||
m_status = 1;
|
||||
}
|
||||
if(m_status == 1)
|
||||
{
|
||||
cmd = m_source2->vertex(x, y);
|
||||
if(!is_stop(cmd)) return cmd;
|
||||
m_status = 2;
|
||||
}
|
||||
return path_cmd_stop;
|
||||
}
|
||||
|
||||
private:
|
||||
conv_concat(const conv_concat<VS1, VS2>&);
|
||||
const conv_concat<VS1, VS2>&
|
||||
operator = (const conv_concat<VS1, VS2>&);
|
||||
|
||||
VS1* m_source1;
|
||||
VS2* m_source2;
|
||||
int m_status;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,71 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_CONTOUR_INCLUDED
|
||||
#define AGG_CONV_CONTOUR_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_vcgen_contour.h"
|
||||
#include "agg_conv_adaptor_vcgen.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-----------------------------------------------------------conv_contour
|
||||
template<class VertexSource>
|
||||
struct conv_contour : public conv_adaptor_vcgen<VertexSource, vcgen_contour>
|
||||
{
|
||||
typedef conv_adaptor_vcgen<VertexSource, vcgen_contour> base_type;
|
||||
|
||||
conv_contour(VertexSource& vs) :
|
||||
conv_adaptor_vcgen<VertexSource, vcgen_contour>(vs)
|
||||
{
|
||||
}
|
||||
|
||||
void line_join(line_join_e lj) { base_type::generator().line_join(lj); }
|
||||
void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); }
|
||||
void width(double w) { base_type::generator().width(w); }
|
||||
void miter_limit(double ml) { base_type::generator().miter_limit(ml); }
|
||||
void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); }
|
||||
void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); }
|
||||
void approximation_scale(double as) { base_type::generator().approximation_scale(as); }
|
||||
void auto_detect_orientation(bool v) { base_type::generator().auto_detect_orientation(v); }
|
||||
|
||||
line_join_e line_join() const { return base_type::generator().line_join(); }
|
||||
inner_join_e inner_join() const { return base_type::generator().inner_join(); }
|
||||
double width() const { return base_type::generator().width(); }
|
||||
double miter_limit() const { return base_type::generator().miter_limit(); }
|
||||
double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); }
|
||||
double approximation_scale() const { return base_type::generator().approximation_scale(); }
|
||||
bool auto_detect_orientation() const { return base_type::generator().auto_detect_orientation(); }
|
||||
|
||||
private:
|
||||
conv_contour(const conv_contour<VertexSource>&);
|
||||
const conv_contour<VertexSource>&
|
||||
operator = (const conv_contour<VertexSource>&);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,206 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_CURVE_INCLUDED
|
||||
#define AGG_CONV_CURVE_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_curves.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
|
||||
//---------------------------------------------------------------conv_curve
|
||||
// Curve converter class. Any path storage can have Bezier curves defined
|
||||
// by their control points. There're two types of curves supported: curve3
|
||||
// and curve4. Curve3 is a conic Bezier curve with 2 endpoints and 1 control
|
||||
// point. Curve4 has 2 control points (4 points in total) and can be used
|
||||
// to interpolate more complicated curves. Curve4, unlike curve3 can be used
|
||||
// to approximate arcs, both circular and elliptical. Curves are approximated
|
||||
// with straight lines and one of the approaches is just to store the whole
|
||||
// sequence of vertices that approximate our curve. It takes additional
|
||||
// memory, and at the same time the consecutive vertices can be calculated
|
||||
// on demand.
|
||||
//
|
||||
// Initially, path storages are not suppose to keep all the vertices of the
|
||||
// curves (although, nothing prevents us from doing so). Instead, path_storage
|
||||
// keeps only vertices, needed to calculate a curve on demand. Those vertices
|
||||
// are marked with special commands. So, if the path_storage contains curves
|
||||
// (which are not real curves yet), and we render this storage directly,
|
||||
// all we will see is only 2 or 3 straight line segments (for curve3 and
|
||||
// curve4 respectively). If we need to see real curves drawn we need to
|
||||
// include this class into the conversion pipeline.
|
||||
//
|
||||
// Class conv_curve recognizes commands path_cmd_curve3 and path_cmd_curve4
|
||||
// and converts these vertices into a move_to/line_to sequence.
|
||||
//-----------------------------------------------------------------------
|
||||
template<class VertexSource,
|
||||
class Curve3=curve3,
|
||||
class Curve4=curve4> class conv_curve
|
||||
{
|
||||
public:
|
||||
typedef Curve3 curve3_type;
|
||||
typedef Curve4 curve4_type;
|
||||
typedef conv_curve<VertexSource, Curve3, Curve4> self_type;
|
||||
|
||||
explicit conv_curve(VertexSource& source) :
|
||||
m_source(&source), m_last_x(0.0), m_last_y(0.0) {}
|
||||
void attach(VertexSource& source) { m_source = &source; }
|
||||
|
||||
void approximation_method(curve_approximation_method_e v)
|
||||
{
|
||||
m_curve3.approximation_method(v);
|
||||
m_curve4.approximation_method(v);
|
||||
}
|
||||
|
||||
curve_approximation_method_e approximation_method() const
|
||||
{
|
||||
return m_curve4.approximation_method();
|
||||
}
|
||||
|
||||
void approximation_scale(double s)
|
||||
{
|
||||
m_curve3.approximation_scale(s);
|
||||
m_curve4.approximation_scale(s);
|
||||
}
|
||||
|
||||
double approximation_scale() const
|
||||
{
|
||||
return m_curve4.approximation_scale();
|
||||
}
|
||||
|
||||
void angle_tolerance(double v)
|
||||
{
|
||||
m_curve3.angle_tolerance(v);
|
||||
m_curve4.angle_tolerance(v);
|
||||
}
|
||||
|
||||
double angle_tolerance() const
|
||||
{
|
||||
return m_curve4.angle_tolerance();
|
||||
}
|
||||
|
||||
void cusp_limit(double v)
|
||||
{
|
||||
m_curve3.cusp_limit(v);
|
||||
m_curve4.cusp_limit(v);
|
||||
}
|
||||
|
||||
double cusp_limit() const
|
||||
{
|
||||
return m_curve4.cusp_limit();
|
||||
}
|
||||
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
conv_curve(const self_type&);
|
||||
const self_type& operator = (const self_type&);
|
||||
|
||||
VertexSource* m_source;
|
||||
double m_last_x;
|
||||
double m_last_y;
|
||||
curve3_type m_curve3;
|
||||
curve4_type m_curve4;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource, class Curve3, class Curve4>
|
||||
void conv_curve<VertexSource, Curve3, Curve4>::rewind(unsigned path_id)
|
||||
{
|
||||
m_source->rewind(path_id);
|
||||
m_last_x = 0.0;
|
||||
m_last_y = 0.0;
|
||||
m_curve3.reset();
|
||||
m_curve4.reset();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource, class Curve3, class Curve4>
|
||||
unsigned conv_curve<VertexSource, Curve3, Curve4>::vertex(double* x, double* y)
|
||||
{
|
||||
if(!is_stop(m_curve3.vertex(x, y)))
|
||||
{
|
||||
m_last_x = *x;
|
||||
m_last_y = *y;
|
||||
return path_cmd_line_to;
|
||||
}
|
||||
|
||||
if(!is_stop(m_curve4.vertex(x, y)))
|
||||
{
|
||||
m_last_x = *x;
|
||||
m_last_y = *y;
|
||||
return path_cmd_line_to;
|
||||
}
|
||||
|
||||
double ct2_x;
|
||||
double ct2_y;
|
||||
double end_x;
|
||||
double end_y;
|
||||
|
||||
unsigned cmd = m_source->vertex(x, y);
|
||||
switch(cmd)
|
||||
{
|
||||
case path_cmd_curve3:
|
||||
m_source->vertex(&end_x, &end_y);
|
||||
|
||||
m_curve3.init(m_last_x, m_last_y,
|
||||
*x, *y,
|
||||
end_x, end_y);
|
||||
|
||||
m_curve3.vertex(x, y); // First call returns path_cmd_move_to
|
||||
m_curve3.vertex(x, y); // This is the first vertex of the curve
|
||||
cmd = path_cmd_line_to;
|
||||
break;
|
||||
|
||||
case path_cmd_curve4:
|
||||
m_source->vertex(&ct2_x, &ct2_y);
|
||||
m_source->vertex(&end_x, &end_y);
|
||||
|
||||
m_curve4.init(m_last_x, m_last_y,
|
||||
*x, *y,
|
||||
ct2_x, ct2_y,
|
||||
end_x, end_y);
|
||||
|
||||
m_curve4.vertex(x, y); // First call returns path_cmd_move_to
|
||||
m_curve4.vertex(x, y); // This is the first vertex of the curve
|
||||
cmd = path_cmd_line_to;
|
||||
break;
|
||||
}
|
||||
m_last_x = *x;
|
||||
m_last_y = *y;
|
||||
return cmd;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,74 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_DASH_INCLUDED
|
||||
#define AGG_CONV_DASH_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_vcgen_dash.h"
|
||||
#include "agg_conv_adaptor_vcgen.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//---------------------------------------------------------------conv_dash
|
||||
template<class VertexSource, class Markers=null_markers>
|
||||
struct conv_dash : public conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers>
|
||||
{
|
||||
typedef Markers marker_type;
|
||||
typedef conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers> base_type;
|
||||
|
||||
conv_dash(VertexSource& vs) :
|
||||
conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers>(vs)
|
||||
{
|
||||
}
|
||||
|
||||
void remove_all_dashes()
|
||||
{
|
||||
base_type::generator().remove_all_dashes();
|
||||
}
|
||||
|
||||
void add_dash(double dash_len, double gap_len)
|
||||
{
|
||||
base_type::generator().add_dash(dash_len, gap_len);
|
||||
}
|
||||
|
||||
void dash_start(double ds)
|
||||
{
|
||||
base_type::generator().dash_start(ds);
|
||||
}
|
||||
|
||||
void shorten(double s) { base_type::generator().shorten(s); }
|
||||
double shorten() const { return base_type::generator().shorten(); }
|
||||
|
||||
private:
|
||||
conv_dash(const conv_dash<VertexSource, Markers>&);
|
||||
const conv_dash<VertexSource, Markers>&
|
||||
operator = (const conv_dash<VertexSource, Markers>&);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,441 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// General Polygon Clipper based on the GPC library by Alan Murta
|
||||
// Union, Intersection, XOR, A-B, B-A
|
||||
// Contact the author if you intend to use it in commercial applications!
|
||||
// http://www.cs.man.ac.uk/aig/staff/alan/software/
|
||||
// Alan Murta (email: gpc@cs.man.ac.uk)
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_GPC_INCLUDED
|
||||
#define AGG_CONV_GPC_INCLUDED
|
||||
|
||||
#include <math.h>
|
||||
#include "agg_basics.h"
|
||||
#include "agg_array.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "gpc.h"
|
||||
}
|
||||
|
||||
namespace agg
|
||||
{
|
||||
enum gpc_op_e
|
||||
{
|
||||
gpc_or,
|
||||
gpc_and,
|
||||
gpc_xor,
|
||||
gpc_a_minus_b,
|
||||
gpc_b_minus_a
|
||||
};
|
||||
|
||||
|
||||
//================================================================conv_gpc
|
||||
template<class VSA, class VSB> class conv_gpc
|
||||
{
|
||||
enum status
|
||||
{
|
||||
status_move_to,
|
||||
status_line_to,
|
||||
status_stop
|
||||
};
|
||||
|
||||
struct contour_header_type
|
||||
{
|
||||
int num_vertices;
|
||||
int hole_flag;
|
||||
gpc_vertex* vertices;
|
||||
};
|
||||
|
||||
typedef pod_bvector<gpc_vertex, 8> vertex_array_type;
|
||||
typedef pod_bvector<contour_header_type, 6> contour_header_array_type;
|
||||
|
||||
|
||||
public:
|
||||
typedef VSA source_a_type;
|
||||
typedef VSB source_b_type;
|
||||
typedef conv_gpc<source_a_type, source_b_type> self_type;
|
||||
|
||||
~conv_gpc()
|
||||
{
|
||||
free_gpc_data();
|
||||
}
|
||||
|
||||
conv_gpc(source_a_type& a, source_b_type& b, gpc_op_e op = gpc_or) :
|
||||
m_src_a(&a),
|
||||
m_src_b(&b),
|
||||
m_status(status_move_to),
|
||||
m_vertex(-1),
|
||||
m_contour(-1),
|
||||
m_operation(op)
|
||||
{
|
||||
memset(&m_poly_a, 0, sizeof(m_poly_a));
|
||||
memset(&m_poly_b, 0, sizeof(m_poly_b));
|
||||
memset(&m_result, 0, sizeof(m_result));
|
||||
}
|
||||
|
||||
void attach1(VSA& source) { m_src_a = &source; }
|
||||
void attach2(VSB& source) { m_src_b = &source; }
|
||||
|
||||
void operation(gpc_op_e v) { m_operation = v; }
|
||||
|
||||
// Vertex Source Interface
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
conv_gpc(const conv_gpc<VSA, VSB>&);
|
||||
const conv_gpc<VSA, VSB>& operator = (const conv_gpc<VSA, VSB>&);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void free_polygon(gpc_polygon& p);
|
||||
void free_result();
|
||||
void free_gpc_data();
|
||||
void start_contour();
|
||||
void add_vertex(double x, double y);
|
||||
void end_contour(unsigned orientation);
|
||||
void make_polygon(gpc_polygon& p);
|
||||
void start_extracting();
|
||||
bool next_contour();
|
||||
bool next_vertex(double* x, double* y);
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class VS> void add(VS& src, gpc_polygon& p)
|
||||
{
|
||||
unsigned cmd;
|
||||
double x, y;
|
||||
double start_x = 0.0;
|
||||
double start_y = 0.0;
|
||||
bool line_to = false;
|
||||
unsigned orientation = 0;
|
||||
|
||||
m_contour_accumulator.remove_all();
|
||||
|
||||
while(!is_stop(cmd = src.vertex(&x, &y)))
|
||||
{
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
if(is_move_to(cmd))
|
||||
{
|
||||
if(line_to)
|
||||
{
|
||||
end_contour(orientation);
|
||||
orientation = 0;
|
||||
}
|
||||
start_contour();
|
||||
start_x = x;
|
||||
start_y = y;
|
||||
}
|
||||
add_vertex(x, y);
|
||||
line_to = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_end_poly(cmd))
|
||||
{
|
||||
orientation = get_orientation(cmd);
|
||||
if(line_to && is_closed(cmd))
|
||||
{
|
||||
add_vertex(start_x, start_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(line_to)
|
||||
{
|
||||
end_contour(orientation);
|
||||
}
|
||||
make_polygon(p);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
source_a_type* m_src_a;
|
||||
source_b_type* m_src_b;
|
||||
status m_status;
|
||||
int m_vertex;
|
||||
int m_contour;
|
||||
gpc_op_e m_operation;
|
||||
vertex_array_type m_vertex_accumulator;
|
||||
contour_header_array_type m_contour_accumulator;
|
||||
gpc_polygon m_poly_a;
|
||||
gpc_polygon m_poly_b;
|
||||
gpc_polygon m_result;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VSA, class VSB>
|
||||
void conv_gpc<VSA, VSB>::free_polygon(gpc_polygon& p)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < p.num_contours; i++)
|
||||
{
|
||||
pod_allocator<gpc_vertex>::deallocate(p.contour[i].vertex,
|
||||
p.contour[i].num_vertices);
|
||||
}
|
||||
pod_allocator<gpc_vertex_list>::deallocate(p.contour, p.num_contours);
|
||||
memset(&p, 0, sizeof(gpc_polygon));
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VSA, class VSB>
|
||||
void conv_gpc<VSA, VSB>::free_result()
|
||||
{
|
||||
if(m_result.contour)
|
||||
{
|
||||
gpc_free_polygon(&m_result);
|
||||
}
|
||||
memset(&m_result, 0, sizeof(m_result));
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VSA, class VSB>
|
||||
void conv_gpc<VSA, VSB>::free_gpc_data()
|
||||
{
|
||||
free_polygon(m_poly_a);
|
||||
free_polygon(m_poly_b);
|
||||
free_result();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VSA, class VSB>
|
||||
void conv_gpc<VSA, VSB>::start_contour()
|
||||
{
|
||||
contour_header_type h;
|
||||
memset(&h, 0, sizeof(h));
|
||||
m_contour_accumulator.add(h);
|
||||
m_vertex_accumulator.remove_all();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VSA, class VSB>
|
||||
inline void conv_gpc<VSA, VSB>::add_vertex(double x, double y)
|
||||
{
|
||||
gpc_vertex v;
|
||||
v.x = x;
|
||||
v.y = y;
|
||||
m_vertex_accumulator.add(v);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VSA, class VSB>
|
||||
void conv_gpc<VSA, VSB>::end_contour(unsigned orientation)
|
||||
{
|
||||
if(m_contour_accumulator.size())
|
||||
{
|
||||
if(m_vertex_accumulator.size() > 2)
|
||||
{
|
||||
contour_header_type& h =
|
||||
m_contour_accumulator[m_contour_accumulator.size() - 1];
|
||||
|
||||
h.num_vertices = m_vertex_accumulator.size();
|
||||
h.hole_flag = 0;
|
||||
|
||||
// TO DO: Clarify the "holes"
|
||||
//if(is_cw(orientation)) h.hole_flag = 1;
|
||||
|
||||
h.vertices = pod_allocator<gpc_vertex>::allocate(h.num_vertices);
|
||||
gpc_vertex* d = h.vertices;
|
||||
int i;
|
||||
for(i = 0; i < h.num_vertices; i++)
|
||||
{
|
||||
const gpc_vertex& s = m_vertex_accumulator[i];
|
||||
d->x = s.x;
|
||||
d->y = s.y;
|
||||
++d;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vertex_accumulator.remove_last();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VSA, class VSB>
|
||||
void conv_gpc<VSA, VSB>::make_polygon(gpc_polygon& p)
|
||||
{
|
||||
free_polygon(p);
|
||||
if(m_contour_accumulator.size())
|
||||
{
|
||||
p.num_contours = m_contour_accumulator.size();
|
||||
|
||||
p.hole = 0;
|
||||
p.contour = pod_allocator<gpc_vertex_list>::allocate(p.num_contours);
|
||||
|
||||
int i;
|
||||
gpc_vertex_list* pv = p.contour;
|
||||
for(i = 0; i < p.num_contours; i++)
|
||||
{
|
||||
const contour_header_type& h = m_contour_accumulator[i];
|
||||
pv->num_vertices = h.num_vertices;
|
||||
pv->vertex = h.vertices;
|
||||
++pv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VSA, class VSB>
|
||||
void conv_gpc<VSA, VSB>::start_extracting()
|
||||
{
|
||||
m_status = status_move_to;
|
||||
m_contour = -1;
|
||||
m_vertex = -1;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VSA, class VSB>
|
||||
bool conv_gpc<VSA, VSB>::next_contour()
|
||||
{
|
||||
if(++m_contour < m_result.num_contours)
|
||||
{
|
||||
m_vertex = -1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VSA, class VSB>
|
||||
inline bool conv_gpc<VSA, VSB>::next_vertex(double* x, double* y)
|
||||
{
|
||||
const gpc_vertex_list& vlist = m_result.contour[m_contour];
|
||||
if(++m_vertex < vlist.num_vertices)
|
||||
{
|
||||
const gpc_vertex& v = vlist.vertex[m_vertex];
|
||||
*x = v.x;
|
||||
*y = v.y;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VSA, class VSB>
|
||||
void conv_gpc<VSA, VSB>::rewind(unsigned path_id)
|
||||
{
|
||||
free_result();
|
||||
m_src_a->rewind(path_id);
|
||||
m_src_b->rewind(path_id);
|
||||
add(*m_src_a, m_poly_a);
|
||||
add(*m_src_b, m_poly_b);
|
||||
switch(m_operation)
|
||||
{
|
||||
case gpc_or:
|
||||
gpc_polygon_clip(GPC_UNION,
|
||||
&m_poly_a,
|
||||
&m_poly_b,
|
||||
&m_result);
|
||||
break;
|
||||
|
||||
case gpc_and:
|
||||
gpc_polygon_clip(GPC_INT,
|
||||
&m_poly_a,
|
||||
&m_poly_b,
|
||||
&m_result);
|
||||
break;
|
||||
|
||||
case gpc_xor:
|
||||
gpc_polygon_clip(GPC_XOR,
|
||||
&m_poly_a,
|
||||
&m_poly_b,
|
||||
&m_result);
|
||||
break;
|
||||
|
||||
case gpc_a_minus_b:
|
||||
gpc_polygon_clip(GPC_DIFF,
|
||||
&m_poly_a,
|
||||
&m_poly_b,
|
||||
&m_result);
|
||||
break;
|
||||
|
||||
case gpc_b_minus_a:
|
||||
gpc_polygon_clip(GPC_DIFF,
|
||||
&m_poly_b,
|
||||
&m_poly_a,
|
||||
&m_result);
|
||||
break;
|
||||
}
|
||||
start_extracting();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VSA, class VSB>
|
||||
unsigned conv_gpc<VSA, VSB>::vertex(double* x, double* y)
|
||||
{
|
||||
if(m_status == status_move_to)
|
||||
{
|
||||
if(next_contour())
|
||||
{
|
||||
if(next_vertex(x, y))
|
||||
{
|
||||
m_status = status_line_to;
|
||||
return path_cmd_move_to;
|
||||
}
|
||||
m_status = status_stop;
|
||||
return path_cmd_end_poly | path_flags_close;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(next_vertex(x, y))
|
||||
{
|
||||
return path_cmd_line_to;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_status = status_move_to;
|
||||
}
|
||||
return path_cmd_end_poly | path_flags_close;
|
||||
}
|
||||
return path_cmd_stop;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,154 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_MARKER_INCLUDED
|
||||
#define AGG_CONV_MARKER_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_trans_affine.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//-------------------------------------------------------------conv_marker
|
||||
template<class MarkerLocator, class MarkerShapes>
|
||||
class conv_marker
|
||||
{
|
||||
public:
|
||||
conv_marker(MarkerLocator& ml, MarkerShapes& ms);
|
||||
|
||||
trans_affine& transform() { return m_transform; }
|
||||
const trans_affine& transform() const { return m_transform; }
|
||||
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
conv_marker(const conv_marker<MarkerLocator, MarkerShapes>&);
|
||||
const conv_marker<MarkerLocator, MarkerShapes>&
|
||||
operator = (const conv_marker<MarkerLocator, MarkerShapes>&);
|
||||
|
||||
enum status_e
|
||||
{
|
||||
initial,
|
||||
markers,
|
||||
polygon,
|
||||
stop
|
||||
};
|
||||
|
||||
MarkerLocator* m_marker_locator;
|
||||
MarkerShapes* m_marker_shapes;
|
||||
trans_affine m_transform;
|
||||
trans_affine m_mtx;
|
||||
status_e m_status;
|
||||
unsigned m_marker;
|
||||
unsigned m_num_markers;
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class MarkerLocator, class MarkerShapes>
|
||||
conv_marker<MarkerLocator, MarkerShapes>::conv_marker(MarkerLocator& ml, MarkerShapes& ms) :
|
||||
m_marker_locator(&ml),
|
||||
m_marker_shapes(&ms),
|
||||
m_status(initial),
|
||||
m_marker(0),
|
||||
m_num_markers(1)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class MarkerLocator, class MarkerShapes>
|
||||
void conv_marker<MarkerLocator, MarkerShapes>::rewind(unsigned)
|
||||
{
|
||||
m_status = initial;
|
||||
m_marker = 0;
|
||||
m_num_markers = 1;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class MarkerLocator, class MarkerShapes>
|
||||
unsigned conv_marker<MarkerLocator, MarkerShapes>::vertex(double* x, double* y)
|
||||
{
|
||||
unsigned cmd = path_cmd_move_to;
|
||||
double x1, y1, x2, y2;
|
||||
|
||||
while(!is_stop(cmd))
|
||||
{
|
||||
switch(m_status)
|
||||
{
|
||||
case initial:
|
||||
if(m_num_markers == 0)
|
||||
{
|
||||
cmd = path_cmd_stop;
|
||||
break;
|
||||
}
|
||||
m_marker_locator->rewind(m_marker);
|
||||
++m_marker;
|
||||
m_num_markers = 0;
|
||||
m_status = markers;
|
||||
|
||||
case markers:
|
||||
if(is_stop(m_marker_locator->vertex(&x1, &y1)))
|
||||
{
|
||||
m_status = initial;
|
||||
break;
|
||||
}
|
||||
if(is_stop(m_marker_locator->vertex(&x2, &y2)))
|
||||
{
|
||||
m_status = initial;
|
||||
break;
|
||||
}
|
||||
++m_num_markers;
|
||||
m_mtx = m_transform;
|
||||
m_mtx *= trans_affine_rotation(atan2(y2 - y1, x2 - x1));
|
||||
m_mtx *= trans_affine_translation(x1, y1);
|
||||
m_marker_shapes->rewind(m_marker - 1);
|
||||
m_status = polygon;
|
||||
|
||||
case polygon:
|
||||
cmd = m_marker_shapes->vertex(x, y);
|
||||
if(is_stop(cmd))
|
||||
{
|
||||
cmd = path_cmd_move_to;
|
||||
m_status = markers;
|
||||
break;
|
||||
}
|
||||
m_mtx.transform(x, y);
|
||||
return cmd;
|
||||
|
||||
case stop:
|
||||
cmd = path_cmd_stop;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_MARKER_ADAPTOR_INCLUDED
|
||||
#define AGG_CONV_MARKER_ADAPTOR_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_conv_adaptor_vcgen.h"
|
||||
#include "agg_vcgen_vertex_sequence.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=====================================================conv_marker_adaptor
|
||||
template<class VertexSource, class Markers=null_markers>
|
||||
struct conv_marker_adaptor :
|
||||
public conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers>
|
||||
{
|
||||
typedef Markers marker_type;
|
||||
typedef conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers> base_type;
|
||||
|
||||
conv_marker_adaptor(VertexSource& vs) :
|
||||
conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers>(vs)
|
||||
{
|
||||
}
|
||||
|
||||
void shorten(double s) { base_type::generator().shorten(s); }
|
||||
double shorten() const { return base_type::generator().shorten(); }
|
||||
|
||||
private:
|
||||
conv_marker_adaptor(const conv_marker_adaptor<VertexSource, Markers>&);
|
||||
const conv_marker_adaptor<VertexSource, Markers>&
|
||||
operator = (const conv_marker_adaptor<VertexSource, Markers>&);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,57 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_SEGMENTATOR_INCLUDED
|
||||
#define AGG_CONV_SEGMENTATOR_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_conv_adaptor_vpgen.h"
|
||||
#include "agg_vpgen_segmentator.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//========================================================conv_segmentator
|
||||
template<class VertexSource>
|
||||
struct conv_segmentator : public conv_adaptor_vpgen<VertexSource, vpgen_segmentator>
|
||||
{
|
||||
typedef conv_adaptor_vpgen<VertexSource, vpgen_segmentator> base_type;
|
||||
|
||||
conv_segmentator(VertexSource& vs) :
|
||||
conv_adaptor_vpgen<VertexSource, vpgen_segmentator>(vs) {}
|
||||
|
||||
void approximation_scale(double s) { base_type::vpgen().approximation_scale(s); }
|
||||
double approximation_scale() const { return base_type::vpgen().approximation_scale(); }
|
||||
|
||||
private:
|
||||
conv_segmentator(const conv_segmentator<VertexSource>&);
|
||||
const conv_segmentator<VertexSource>&
|
||||
operator = (const conv_segmentator<VertexSource>&);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_SHORTEN_PATH_INCLUDED
|
||||
#define AGG_CONV_SHORTEN_PATH_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_conv_adaptor_vcgen.h"
|
||||
#include "agg_vcgen_vertex_sequence.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=======================================================conv_shorten_path
|
||||
template<class VertexSource> class conv_shorten_path :
|
||||
public conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence>
|
||||
{
|
||||
public:
|
||||
typedef conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence> base_type;
|
||||
|
||||
conv_shorten_path(VertexSource& vs) :
|
||||
conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence>(vs)
|
||||
{
|
||||
}
|
||||
|
||||
void shorten(double s) { base_type::generator().shorten(s); }
|
||||
double shorten() const { return base_type::generator().shorten(); }
|
||||
|
||||
private:
|
||||
conv_shorten_path(const conv_shorten_path<VertexSource>&);
|
||||
const conv_shorten_path<VertexSource>&
|
||||
operator = (const conv_shorten_path<VertexSource>&);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,86 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_SMOOTH_POLY1_INCLUDED
|
||||
#define AGG_CONV_SMOOTH_POLY1_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_vcgen_smooth_poly1.h"
|
||||
#include "agg_conv_adaptor_vcgen.h"
|
||||
#include "agg_conv_curve.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-------------------------------------------------------conv_smooth_poly1
|
||||
template<class VertexSource>
|
||||
struct conv_smooth_poly1 :
|
||||
public conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1>
|
||||
{
|
||||
typedef conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1> base_type;
|
||||
|
||||
conv_smooth_poly1(VertexSource& vs) :
|
||||
conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1>(vs)
|
||||
{
|
||||
}
|
||||
|
||||
void smooth_value(double v) { base_type::generator().smooth_value(v); }
|
||||
double smooth_value() const { return base_type::generator().smooth_value(); }
|
||||
|
||||
private:
|
||||
conv_smooth_poly1(const conv_smooth_poly1<VertexSource>&);
|
||||
const conv_smooth_poly1<VertexSource>&
|
||||
operator = (const conv_smooth_poly1<VertexSource>&);
|
||||
};
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------conv_smooth_poly1_curve
|
||||
template<class VertexSource>
|
||||
struct conv_smooth_poly1_curve :
|
||||
public conv_curve<conv_smooth_poly1<VertexSource> >
|
||||
{
|
||||
conv_smooth_poly1_curve(VertexSource& vs) :
|
||||
conv_curve<conv_smooth_poly1<VertexSource> >(m_smooth),
|
||||
m_smooth(vs)
|
||||
{
|
||||
}
|
||||
|
||||
void smooth_value(double v) { m_smooth.generator().smooth_value(v); }
|
||||
double smooth_value() const { return m_smooth.generator().smooth_value(); }
|
||||
|
||||
private:
|
||||
conv_smooth_poly1_curve(const conv_smooth_poly1_curve<VertexSource>&);
|
||||
const conv_smooth_poly1_curve<VertexSource>&
|
||||
operator = (const conv_smooth_poly1_curve<VertexSource>&);
|
||||
|
||||
conv_smooth_poly1<VertexSource> m_smooth;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_STROKE_INCLUDED
|
||||
#define AGG_CONV_STROKE_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_vcgen_stroke.h"
|
||||
#include "agg_conv_adaptor_vcgen.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-------------------------------------------------------------conv_stroke
|
||||
template<class VertexSource, class Markers=null_markers>
|
||||
struct conv_stroke :
|
||||
public conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers>
|
||||
{
|
||||
typedef Markers marker_type;
|
||||
typedef conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers> base_type;
|
||||
|
||||
conv_stroke(VertexSource& vs) :
|
||||
conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers>(vs)
|
||||
{
|
||||
}
|
||||
|
||||
void line_cap(line_cap_e lc) { base_type::generator().line_cap(lc); }
|
||||
void line_join(line_join_e lj) { base_type::generator().line_join(lj); }
|
||||
void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); }
|
||||
|
||||
line_cap_e line_cap() const { return base_type::generator().line_cap(); }
|
||||
line_join_e line_join() const { return base_type::generator().line_join(); }
|
||||
inner_join_e inner_join() const { return base_type::generator().inner_join(); }
|
||||
|
||||
void width(double w) { base_type::generator().width(w); }
|
||||
void miter_limit(double ml) { base_type::generator().miter_limit(ml); }
|
||||
void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); }
|
||||
void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); }
|
||||
void approximation_scale(double as) { base_type::generator().approximation_scale(as); }
|
||||
|
||||
double width() const { return base_type::generator().width(); }
|
||||
double miter_limit() const { return base_type::generator().miter_limit(); }
|
||||
double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); }
|
||||
double approximation_scale() const { return base_type::generator().approximation_scale(); }
|
||||
|
||||
void shorten(double s) { base_type::generator().shorten(s); }
|
||||
double shorten() const { return base_type::generator().shorten(); }
|
||||
|
||||
private:
|
||||
conv_stroke(const conv_stroke<VertexSource, Markers>&);
|
||||
const conv_stroke<VertexSource, Markers>&
|
||||
operator = (const conv_stroke<VertexSource, Markers>&);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,74 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_TRANSFORM_INCLUDED
|
||||
#define AGG_CONV_TRANSFORM_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_trans_affine.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//----------------------------------------------------------conv_transform
|
||||
template<class VertexSource, class Transformer=trans_affine> class conv_transform
|
||||
{
|
||||
public:
|
||||
conv_transform(VertexSource& source, const Transformer& tr) :
|
||||
m_source(&source), m_trans(&tr) {}
|
||||
void attach(VertexSource& source) { m_source = &source; }
|
||||
|
||||
void rewind(unsigned path_id)
|
||||
{
|
||||
m_source->rewind(path_id);
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
unsigned cmd = m_source->vertex(x, y);
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
m_trans->transform(x, y);
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
void transformer(const Transformer& tr)
|
||||
{
|
||||
m_trans = &tr;
|
||||
}
|
||||
|
||||
private:
|
||||
conv_transform(const conv_transform<VertexSource>&);
|
||||
const conv_transform<VertexSource>&
|
||||
operator = (const conv_transform<VertexSource>&);
|
||||
|
||||
VertexSource* m_source;
|
||||
const Transformer* m_trans;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,61 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_UNCLOSE_POLYGON_INCLUDED
|
||||
#define AGG_CONV_UNCLOSE_POLYGON_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//====================================================conv_unclose_polygon
|
||||
template<class VertexSource> class conv_unclose_polygon
|
||||
{
|
||||
public:
|
||||
explicit conv_unclose_polygon(VertexSource& vs) : m_source(&vs) {}
|
||||
void attach(VertexSource& source) { m_source = &source; }
|
||||
|
||||
void rewind(unsigned path_id)
|
||||
{
|
||||
m_source->rewind(path_id);
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
unsigned cmd = m_source->vertex(x, y);
|
||||
if(is_end_poly(cmd)) cmd &= ~path_flags_close;
|
||||
return cmd;
|
||||
}
|
||||
|
||||
private:
|
||||
conv_unclose_polygon(const conv_unclose_polygon<VertexSource>&);
|
||||
const conv_unclose_polygon<VertexSource>&
|
||||
operator = (const conv_unclose_polygon<VertexSource>&);
|
||||
|
||||
VertexSource* m_source;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,701 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CURVES_INCLUDED
|
||||
#define AGG_CURVES_INCLUDED
|
||||
|
||||
#include "agg_array.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
// See Implementation agg_curves.cpp
|
||||
|
||||
//--------------------------------------------curve_approximation_method_e
|
||||
enum curve_approximation_method_e
|
||||
{
|
||||
curve_inc,
|
||||
curve_div
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------curve3_inc
|
||||
class curve3_inc
|
||||
{
|
||||
public:
|
||||
curve3_inc() :
|
||||
m_num_steps(0), m_step(0), m_scale(1.0) { }
|
||||
|
||||
curve3_inc(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3) :
|
||||
m_num_steps(0), m_step(0), m_scale(1.0)
|
||||
{
|
||||
init(x1, y1, x2, y2, x3, y3);
|
||||
}
|
||||
|
||||
void reset() { m_num_steps = 0; m_step = -1; }
|
||||
void init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3);
|
||||
|
||||
void approximation_method(curve_approximation_method_e) {}
|
||||
curve_approximation_method_e approximation_method() const { return curve_inc; }
|
||||
|
||||
void approximation_scale(double s);
|
||||
double approximation_scale() const;
|
||||
|
||||
void angle_tolerance(double) {}
|
||||
double angle_tolerance() const { return 0.0; }
|
||||
|
||||
void cusp_limit(double) {}
|
||||
double cusp_limit() const { return 0.0; }
|
||||
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
int m_num_steps;
|
||||
int m_step;
|
||||
double m_scale;
|
||||
double m_start_x;
|
||||
double m_start_y;
|
||||
double m_end_x;
|
||||
double m_end_y;
|
||||
double m_fx;
|
||||
double m_fy;
|
||||
double m_dfx;
|
||||
double m_dfy;
|
||||
double m_ddfx;
|
||||
double m_ddfy;
|
||||
double m_saved_fx;
|
||||
double m_saved_fy;
|
||||
double m_saved_dfx;
|
||||
double m_saved_dfy;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------curve3_div
|
||||
class curve3_div
|
||||
{
|
||||
public:
|
||||
curve3_div() :
|
||||
m_approximation_scale(1.0),
|
||||
m_angle_tolerance(0.0),
|
||||
m_count(0)
|
||||
{}
|
||||
|
||||
curve3_div(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3) :
|
||||
m_approximation_scale(1.0),
|
||||
m_angle_tolerance(0.0),
|
||||
m_count(0)
|
||||
{
|
||||
init(x1, y1, x2, y2, x3, y3);
|
||||
}
|
||||
|
||||
void reset() { m_points.remove_all(); m_count = 0; }
|
||||
void init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3);
|
||||
|
||||
void approximation_method(curve_approximation_method_e) {}
|
||||
curve_approximation_method_e approximation_method() const { return curve_div; }
|
||||
|
||||
void approximation_scale(double s) { m_approximation_scale = s; }
|
||||
double approximation_scale() const { return m_approximation_scale; }
|
||||
|
||||
void angle_tolerance(double a) { m_angle_tolerance = a; }
|
||||
double angle_tolerance() const { return m_angle_tolerance; }
|
||||
|
||||
void cusp_limit(double) {}
|
||||
double cusp_limit() const { return 0.0; }
|
||||
|
||||
void rewind(unsigned)
|
||||
{
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
if(m_count >= m_points.size()) return path_cmd_stop;
|
||||
const point_d& p = m_points[m_count++];
|
||||
*x = p.x;
|
||||
*y = p.y;
|
||||
return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to;
|
||||
}
|
||||
|
||||
private:
|
||||
void bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3);
|
||||
void recursive_bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
unsigned level);
|
||||
|
||||
double m_approximation_scale;
|
||||
double m_distance_tolerance_square;
|
||||
double m_angle_tolerance;
|
||||
unsigned m_count;
|
||||
pod_bvector<point_d> m_points;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------curve4_points
|
||||
struct curve4_points
|
||||
{
|
||||
double cp[8];
|
||||
curve4_points() {}
|
||||
curve4_points(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4)
|
||||
{
|
||||
cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2;
|
||||
cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4;
|
||||
}
|
||||
void init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4)
|
||||
{
|
||||
cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2;
|
||||
cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4;
|
||||
}
|
||||
double operator [] (unsigned i) const { return cp[i]; }
|
||||
double& operator [] (unsigned i) { return cp[i]; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------curve4_inc
|
||||
class curve4_inc
|
||||
{
|
||||
public:
|
||||
curve4_inc() :
|
||||
m_num_steps(0), m_step(0), m_scale(1.0) { }
|
||||
|
||||
curve4_inc(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4) :
|
||||
m_num_steps(0), m_step(0), m_scale(1.0)
|
||||
{
|
||||
init(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
}
|
||||
|
||||
curve4_inc(const curve4_points& cp) :
|
||||
m_num_steps(0), m_step(0), m_scale(1.0)
|
||||
{
|
||||
init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
void reset() { m_num_steps = 0; m_step = -1; }
|
||||
void init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4);
|
||||
|
||||
void init(const curve4_points& cp)
|
||||
{
|
||||
init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
void approximation_method(curve_approximation_method_e) {}
|
||||
curve_approximation_method_e approximation_method() const { return curve_inc; }
|
||||
|
||||
void approximation_scale(double s);
|
||||
double approximation_scale() const;
|
||||
|
||||
void angle_tolerance(double) {}
|
||||
double angle_tolerance() const { return 0.0; }
|
||||
|
||||
void cusp_limit(double) {}
|
||||
double cusp_limit() const { return 0.0; }
|
||||
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
int m_num_steps;
|
||||
int m_step;
|
||||
double m_scale;
|
||||
double m_start_x;
|
||||
double m_start_y;
|
||||
double m_end_x;
|
||||
double m_end_y;
|
||||
double m_fx;
|
||||
double m_fy;
|
||||
double m_dfx;
|
||||
double m_dfy;
|
||||
double m_ddfx;
|
||||
double m_ddfy;
|
||||
double m_dddfx;
|
||||
double m_dddfy;
|
||||
double m_saved_fx;
|
||||
double m_saved_fy;
|
||||
double m_saved_dfx;
|
||||
double m_saved_dfy;
|
||||
double m_saved_ddfx;
|
||||
double m_saved_ddfy;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------catrom_to_bezier
|
||||
inline curve4_points catrom_to_bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4)
|
||||
{
|
||||
// Trans. matrix Catmull-Rom to Bezier
|
||||
//
|
||||
// 0 1 0 0
|
||||
// -1/6 1 1/6 0
|
||||
// 0 1/6 1 -1/6
|
||||
// 0 0 1 0
|
||||
//
|
||||
return curve4_points(
|
||||
x2,
|
||||
y2,
|
||||
(-x1 + 6*x2 + x3) / 6,
|
||||
(-y1 + 6*y2 + y3) / 6,
|
||||
( x2 + 6*x3 - x4) / 6,
|
||||
( y2 + 6*y3 - y4) / 6,
|
||||
x3,
|
||||
y3);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
inline curve4_points
|
||||
catrom_to_bezier(const curve4_points& cp)
|
||||
{
|
||||
return catrom_to_bezier(cp[0], cp[1], cp[2], cp[3],
|
||||
cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------ubspline_to_bezier
|
||||
inline curve4_points ubspline_to_bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4)
|
||||
{
|
||||
// Trans. matrix Uniform BSpline to Bezier
|
||||
//
|
||||
// 1/6 4/6 1/6 0
|
||||
// 0 4/6 2/6 0
|
||||
// 0 2/6 4/6 0
|
||||
// 0 1/6 4/6 1/6
|
||||
//
|
||||
return curve4_points(
|
||||
(x1 + 4*x2 + x3) / 6,
|
||||
(y1 + 4*y2 + y3) / 6,
|
||||
(4*x2 + 2*x3) / 6,
|
||||
(4*y2 + 2*y3) / 6,
|
||||
(2*x2 + 4*x3) / 6,
|
||||
(2*y2 + 4*y3) / 6,
|
||||
(x2 + 4*x3 + x4) / 6,
|
||||
(y2 + 4*y3 + y4) / 6);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
inline curve4_points
|
||||
ubspline_to_bezier(const curve4_points& cp)
|
||||
{
|
||||
return ubspline_to_bezier(cp[0], cp[1], cp[2], cp[3],
|
||||
cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------hermite_to_bezier
|
||||
inline curve4_points hermite_to_bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4)
|
||||
{
|
||||
// Trans. matrix Hermite to Bezier
|
||||
//
|
||||
// 1 0 0 0
|
||||
// 1 0 1/3 0
|
||||
// 0 1 0 -1/3
|
||||
// 0 1 0 0
|
||||
//
|
||||
return curve4_points(
|
||||
x1,
|
||||
y1,
|
||||
(3*x1 + x3) / 3,
|
||||
(3*y1 + y3) / 3,
|
||||
(3*x2 - x4) / 3,
|
||||
(3*y2 - y4) / 3,
|
||||
x2,
|
||||
y2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
inline curve4_points
|
||||
hermite_to_bezier(const curve4_points& cp)
|
||||
{
|
||||
return hermite_to_bezier(cp[0], cp[1], cp[2], cp[3],
|
||||
cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------curve4_div
|
||||
class curve4_div
|
||||
{
|
||||
public:
|
||||
curve4_div() :
|
||||
m_approximation_scale(1.0),
|
||||
m_angle_tolerance(0.0),
|
||||
m_cusp_limit(0.0),
|
||||
m_count(0)
|
||||
{}
|
||||
|
||||
curve4_div(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4) :
|
||||
m_approximation_scale(1.0),
|
||||
m_angle_tolerance(0.0),
|
||||
m_cusp_limit(0.0),
|
||||
m_count(0)
|
||||
{
|
||||
init(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
}
|
||||
|
||||
curve4_div(const curve4_points& cp) :
|
||||
m_approximation_scale(1.0),
|
||||
m_angle_tolerance(0.0),
|
||||
m_count(0)
|
||||
{
|
||||
init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
void reset() { m_points.remove_all(); m_count = 0; }
|
||||
void init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4);
|
||||
|
||||
void init(const curve4_points& cp)
|
||||
{
|
||||
init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
void approximation_method(curve_approximation_method_e) {}
|
||||
|
||||
curve_approximation_method_e approximation_method() const
|
||||
{
|
||||
return curve_div;
|
||||
}
|
||||
|
||||
void approximation_scale(double s) { m_approximation_scale = s; }
|
||||
double approximation_scale() const { return m_approximation_scale; }
|
||||
|
||||
void angle_tolerance(double a) { m_angle_tolerance = a; }
|
||||
double angle_tolerance() const { return m_angle_tolerance; }
|
||||
|
||||
void cusp_limit(double v)
|
||||
{
|
||||
m_cusp_limit = (v == 0.0) ? 0.0 : pi - v;
|
||||
}
|
||||
|
||||
double cusp_limit() const
|
||||
{
|
||||
return (m_cusp_limit == 0.0) ? 0.0 : pi - m_cusp_limit;
|
||||
}
|
||||
|
||||
void rewind(unsigned)
|
||||
{
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
if(m_count >= m_points.size()) return path_cmd_stop;
|
||||
const point_d& p = m_points[m_count++];
|
||||
*x = p.x;
|
||||
*y = p.y;
|
||||
return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to;
|
||||
}
|
||||
|
||||
private:
|
||||
void bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4);
|
||||
|
||||
void recursive_bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4,
|
||||
unsigned level);
|
||||
|
||||
double m_approximation_scale;
|
||||
double m_distance_tolerance_square;
|
||||
double m_angle_tolerance;
|
||||
double m_cusp_limit;
|
||||
unsigned m_count;
|
||||
pod_bvector<point_d> m_points;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------curve3
|
||||
class curve3
|
||||
{
|
||||
public:
|
||||
curve3() : m_approximation_method(curve_div) {}
|
||||
curve3(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3) :
|
||||
m_approximation_method(curve_div)
|
||||
{
|
||||
init(x1, y1, x2, y2, x3, y3);
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
m_curve_inc.reset();
|
||||
m_curve_div.reset();
|
||||
}
|
||||
|
||||
void init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3)
|
||||
{
|
||||
if(m_approximation_method == curve_inc)
|
||||
{
|
||||
m_curve_inc.init(x1, y1, x2, y2, x3, y3);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_curve_div.init(x1, y1, x2, y2, x3, y3);
|
||||
}
|
||||
}
|
||||
|
||||
void approximation_method(curve_approximation_method_e v)
|
||||
{
|
||||
m_approximation_method = v;
|
||||
}
|
||||
|
||||
curve_approximation_method_e approximation_method() const
|
||||
{
|
||||
return m_approximation_method;
|
||||
}
|
||||
|
||||
void approximation_scale(double s)
|
||||
{
|
||||
m_curve_inc.approximation_scale(s);
|
||||
m_curve_div.approximation_scale(s);
|
||||
}
|
||||
|
||||
double approximation_scale() const
|
||||
{
|
||||
return m_curve_inc.approximation_scale();
|
||||
}
|
||||
|
||||
void angle_tolerance(double a)
|
||||
{
|
||||
m_curve_div.angle_tolerance(a);
|
||||
}
|
||||
|
||||
double angle_tolerance() const
|
||||
{
|
||||
return m_curve_div.angle_tolerance();
|
||||
}
|
||||
|
||||
void cusp_limit(double v)
|
||||
{
|
||||
m_curve_div.cusp_limit(v);
|
||||
}
|
||||
|
||||
double cusp_limit() const
|
||||
{
|
||||
return m_curve_div.cusp_limit();
|
||||
}
|
||||
|
||||
void rewind(unsigned path_id)
|
||||
{
|
||||
if(m_approximation_method == curve_inc)
|
||||
{
|
||||
m_curve_inc.rewind(path_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_curve_div.rewind(path_id);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
if(m_approximation_method == curve_inc)
|
||||
{
|
||||
return m_curve_inc.vertex(x, y);
|
||||
}
|
||||
return m_curve_div.vertex(x, y);
|
||||
}
|
||||
|
||||
private:
|
||||
curve3_inc m_curve_inc;
|
||||
curve3_div m_curve_div;
|
||||
curve_approximation_method_e m_approximation_method;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------curve4
|
||||
class curve4
|
||||
{
|
||||
public:
|
||||
curve4() : m_approximation_method(curve_div) {}
|
||||
curve4(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4) :
|
||||
m_approximation_method(curve_div)
|
||||
{
|
||||
init(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
}
|
||||
|
||||
curve4(const curve4_points& cp) :
|
||||
m_approximation_method(curve_div)
|
||||
{
|
||||
init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
m_curve_inc.reset();
|
||||
m_curve_div.reset();
|
||||
}
|
||||
|
||||
void init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4)
|
||||
{
|
||||
if(m_approximation_method == curve_inc)
|
||||
{
|
||||
m_curve_inc.init(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_curve_div.init(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
}
|
||||
}
|
||||
|
||||
void init(const curve4_points& cp)
|
||||
{
|
||||
init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
void approximation_method(curve_approximation_method_e v)
|
||||
{
|
||||
m_approximation_method = v;
|
||||
}
|
||||
|
||||
curve_approximation_method_e approximation_method() const
|
||||
{
|
||||
return m_approximation_method;
|
||||
}
|
||||
|
||||
void approximation_scale(double s)
|
||||
{
|
||||
m_curve_inc.approximation_scale(s);
|
||||
m_curve_div.approximation_scale(s);
|
||||
}
|
||||
double approximation_scale() const { return m_curve_inc.approximation_scale(); }
|
||||
|
||||
void angle_tolerance(double v)
|
||||
{
|
||||
m_curve_div.angle_tolerance(v);
|
||||
}
|
||||
|
||||
double angle_tolerance() const
|
||||
{
|
||||
return m_curve_div.angle_tolerance();
|
||||
}
|
||||
|
||||
void cusp_limit(double v)
|
||||
{
|
||||
m_curve_div.cusp_limit(v);
|
||||
}
|
||||
|
||||
double cusp_limit() const
|
||||
{
|
||||
return m_curve_div.cusp_limit();
|
||||
}
|
||||
|
||||
void rewind(unsigned path_id)
|
||||
{
|
||||
if(m_approximation_method == curve_inc)
|
||||
{
|
||||
m_curve_inc.rewind(path_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_curve_div.rewind(path_id);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
if(m_approximation_method == curve_inc)
|
||||
{
|
||||
return m_curve_inc.vertex(x, y);
|
||||
}
|
||||
return m_curve_div.vertex(x, y);
|
||||
}
|
||||
|
||||
private:
|
||||
curve4_inc m_curve_inc;
|
||||
curve4_div m_curve_div;
|
||||
curve_approximation_method_e m_approximation_method;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,295 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_DDA_LINE_INCLUDED
|
||||
#define AGG_DDA_LINE_INCLUDED
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//===================================================dda_line_interpolator
|
||||
template<int FractionShift, int YShift=0> class dda_line_interpolator
|
||||
{
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
dda_line_interpolator() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
dda_line_interpolator(int y1, int y2, unsigned count) :
|
||||
m_y(y1),
|
||||
m_inc(((y2 - y1) << FractionShift) / int(count)),
|
||||
m_dy(0)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void operator ++ ()
|
||||
{
|
||||
m_dy += m_inc;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void operator -- ()
|
||||
{
|
||||
m_dy -= m_inc;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void operator += (unsigned n)
|
||||
{
|
||||
m_dy += m_inc * n;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void operator -= (unsigned n)
|
||||
{
|
||||
m_dy -= m_inc * n;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int y() const { return m_y + (m_dy >> (FractionShift-YShift)); }
|
||||
int dy() const { return m_dy; }
|
||||
|
||||
|
||||
private:
|
||||
int m_y;
|
||||
int m_inc;
|
||||
int m_dy;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=================================================dda2_line_interpolator
|
||||
class dda2_line_interpolator
|
||||
{
|
||||
public:
|
||||
typedef int save_data_type;
|
||||
enum save_size_e { save_size = 2 };
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
dda2_line_interpolator() {}
|
||||
|
||||
//-------------------------------------------- Forward-adjusted line
|
||||
dda2_line_interpolator(int y1, int y2, int count) :
|
||||
m_cnt(count <= 0 ? 1 : count),
|
||||
m_lft((y2 - y1) / m_cnt),
|
||||
m_rem((y2 - y1) % m_cnt),
|
||||
m_mod(m_rem),
|
||||
m_y(y1)
|
||||
{
|
||||
if(m_mod <= 0)
|
||||
{
|
||||
m_mod += count;
|
||||
m_rem += count;
|
||||
m_lft--;
|
||||
}
|
||||
m_mod -= count;
|
||||
}
|
||||
|
||||
//-------------------------------------------- Backward-adjusted line
|
||||
dda2_line_interpolator(int y1, int y2, int count, int) :
|
||||
m_cnt(count <= 0 ? 1 : count),
|
||||
m_lft((y2 - y1) / m_cnt),
|
||||
m_rem((y2 - y1) % m_cnt),
|
||||
m_mod(m_rem),
|
||||
m_y(y1)
|
||||
{
|
||||
if(m_mod <= 0)
|
||||
{
|
||||
m_mod += count;
|
||||
m_rem += count;
|
||||
m_lft--;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------- Backward-adjusted line
|
||||
dda2_line_interpolator(int y, int count) :
|
||||
m_cnt(count <= 0 ? 1 : count),
|
||||
m_lft(y / m_cnt),
|
||||
m_rem(y % m_cnt),
|
||||
m_mod(m_rem),
|
||||
m_y(0)
|
||||
{
|
||||
if(m_mod <= 0)
|
||||
{
|
||||
m_mod += count;
|
||||
m_rem += count;
|
||||
m_lft--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void save(save_data_type* data) const
|
||||
{
|
||||
data[0] = m_mod;
|
||||
data[1] = m_y;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void load(const save_data_type* data)
|
||||
{
|
||||
m_mod = data[0];
|
||||
m_y = data[1];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void operator++()
|
||||
{
|
||||
m_mod += m_rem;
|
||||
m_y += m_lft;
|
||||
if(m_mod > 0)
|
||||
{
|
||||
m_mod -= m_cnt;
|
||||
m_y++;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void operator--()
|
||||
{
|
||||
if(m_mod <= m_rem)
|
||||
{
|
||||
m_mod += m_cnt;
|
||||
m_y--;
|
||||
}
|
||||
m_mod -= m_rem;
|
||||
m_y -= m_lft;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void adjust_forward()
|
||||
{
|
||||
m_mod -= m_cnt;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void adjust_backward()
|
||||
{
|
||||
m_mod += m_cnt;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int mod() const { return m_mod; }
|
||||
int rem() const { return m_rem; }
|
||||
int lft() const { return m_lft; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int y() const { return m_y; }
|
||||
|
||||
private:
|
||||
int m_cnt;
|
||||
int m_lft;
|
||||
int m_rem;
|
||||
int m_mod;
|
||||
int m_y;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------line_bresenham_interpolator
|
||||
class line_bresenham_interpolator
|
||||
{
|
||||
public:
|
||||
enum subpixel_scale_e
|
||||
{
|
||||
subpixel_shift = 8,
|
||||
subpixel_scale = 1 << subpixel_shift,
|
||||
subpixel_mask = subpixel_scale - 1
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static int line_lr(int v) { return v >> subpixel_shift; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
line_bresenham_interpolator(int x1, int y1, int x2, int y2) :
|
||||
m_x1_lr(line_lr(x1)),
|
||||
m_y1_lr(line_lr(y1)),
|
||||
m_x2_lr(line_lr(x2)),
|
||||
m_y2_lr(line_lr(y2)),
|
||||
m_ver(abs(m_x2_lr - m_x1_lr) < abs(m_y2_lr - m_y1_lr)),
|
||||
m_len(m_ver ? abs(m_y2_lr - m_y1_lr) :
|
||||
abs(m_x2_lr - m_x1_lr)),
|
||||
m_inc(m_ver ? ((y2 > y1) ? 1 : -1) : ((x2 > x1) ? 1 : -1)),
|
||||
m_interpolator(m_ver ? x1 : y1,
|
||||
m_ver ? x2 : y2,
|
||||
m_len)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
bool is_ver() const { return m_ver; }
|
||||
unsigned len() const { return m_len; }
|
||||
int inc() const { return m_inc; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void hstep()
|
||||
{
|
||||
++m_interpolator;
|
||||
m_x1_lr += m_inc;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void vstep()
|
||||
{
|
||||
++m_interpolator;
|
||||
m_y1_lr += m_inc;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int x1() const { return m_x1_lr; }
|
||||
int y1() const { return m_y1_lr; }
|
||||
int x2() const { return line_lr(m_interpolator.y()); }
|
||||
int y2() const { return line_lr(m_interpolator.y()); }
|
||||
int x2_hr() const { return m_interpolator.y(); }
|
||||
int y2_hr() const { return m_interpolator.y(); }
|
||||
|
||||
private:
|
||||
int m_x1_lr;
|
||||
int m_y1_lr;
|
||||
int m_x2_lr;
|
||||
int m_y2_lr;
|
||||
bool m_ver;
|
||||
unsigned m_len;
|
||||
int m_inc;
|
||||
dda2_line_interpolator m_interpolator;
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,128 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_ELLIPSE_INCLUDED
|
||||
#define AGG_ELLIPSE_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include <math.h>
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//----------------------------------------------------------------ellipse
|
||||
class ellipse
|
||||
{
|
||||
public:
|
||||
ellipse() :
|
||||
m_x(0.0), m_y(0.0), m_rx(1.0), m_ry(1.0), m_scale(1.0),
|
||||
m_num(4), m_step(0), m_cw(false) {}
|
||||
|
||||
ellipse(double x, double y, double rx, double ry,
|
||||
unsigned num_steps=0, bool cw=false) :
|
||||
m_x(x), m_y(y), m_rx(rx), m_ry(ry), m_scale(1.0),
|
||||
m_num(num_steps), m_step(0), m_cw(cw)
|
||||
{
|
||||
if(m_num == 0) calc_num_steps();
|
||||
}
|
||||
|
||||
void init(double x, double y, double rx, double ry,
|
||||
unsigned num_steps=0, bool cw=false);
|
||||
|
||||
void approximation_scale(double scale);
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
void calc_num_steps();
|
||||
|
||||
double m_x;
|
||||
double m_y;
|
||||
double m_rx;
|
||||
double m_ry;
|
||||
double m_scale;
|
||||
unsigned m_num;
|
||||
unsigned m_step;
|
||||
bool m_cw;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void ellipse::init(double x, double y, double rx, double ry,
|
||||
unsigned num_steps, bool cw)
|
||||
{
|
||||
m_x = x;
|
||||
m_y = y;
|
||||
m_rx = rx;
|
||||
m_ry = ry;
|
||||
m_num = num_steps;
|
||||
m_step = 0;
|
||||
m_cw = cw;
|
||||
if(m_num == 0) calc_num_steps();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void ellipse::approximation_scale(double scale)
|
||||
{
|
||||
m_scale = scale;
|
||||
calc_num_steps();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void ellipse::calc_num_steps()
|
||||
{
|
||||
double ra = (fabs(m_rx) + fabs(m_ry)) / 2;
|
||||
double da = acos(ra / (ra + 0.125 / m_scale)) * 2;
|
||||
m_num = uround(2*pi / da);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void ellipse::rewind(unsigned)
|
||||
{
|
||||
m_step = 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline unsigned ellipse::vertex(double* x, double* y)
|
||||
{
|
||||
if(m_step == m_num)
|
||||
{
|
||||
++m_step;
|
||||
return path_cmd_end_poly | path_flags_close | path_flags_ccw;
|
||||
}
|
||||
if(m_step > m_num) return path_cmd_stop;
|
||||
double angle = double(m_step) / double(m_num) * 2.0 * pi;
|
||||
if(m_cw) angle = 2.0 * pi - angle;
|
||||
*x = m_x + cos(angle) * m_rx;
|
||||
*y = m_y + sin(angle) * m_ry;
|
||||
m_step++;
|
||||
return ((m_step == 1) ? path_cmd_move_to : path_cmd_line_to);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_ELLIPSE_BRESENHAM_INCLUDED
|
||||
#define AGG_ELLIPSE_BRESENHAM_INCLUDED
|
||||
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//------------------------------------------ellipse_bresenham_interpolator
|
||||
class ellipse_bresenham_interpolator
|
||||
{
|
||||
public:
|
||||
ellipse_bresenham_interpolator(int rx, int ry) :
|
||||
m_rx2(rx * rx),
|
||||
m_ry2(ry * ry),
|
||||
m_two_rx2(m_rx2 << 1),
|
||||
m_two_ry2(m_ry2 << 1),
|
||||
m_dx(0),
|
||||
m_dy(0),
|
||||
m_inc_x(0),
|
||||
m_inc_y(-ry * m_two_rx2),
|
||||
m_cur_f(0)
|
||||
{}
|
||||
|
||||
int dx() const { return m_dx; }
|
||||
int dy() const { return m_dy; }
|
||||
|
||||
void operator++ ()
|
||||
{
|
||||
int mx, my, mxy, min_m;
|
||||
int fx, fy, fxy;
|
||||
|
||||
mx = fx = m_cur_f + m_inc_x + m_ry2;
|
||||
if(mx < 0) mx = -mx;
|
||||
|
||||
my = fy = m_cur_f + m_inc_y + m_rx2;
|
||||
if(my < 0) my = -my;
|
||||
|
||||
mxy = fxy = m_cur_f + m_inc_x + m_ry2 + m_inc_y + m_rx2;
|
||||
if(mxy < 0) mxy = -mxy;
|
||||
|
||||
min_m = mx;
|
||||
bool flag = true;
|
||||
|
||||
if(min_m > my)
|
||||
{
|
||||
min_m = my;
|
||||
flag = false;
|
||||
}
|
||||
|
||||
m_dx = m_dy = 0;
|
||||
|
||||
if(min_m > mxy)
|
||||
{
|
||||
m_inc_x += m_two_ry2;
|
||||
m_inc_y += m_two_rx2;
|
||||
m_cur_f = fxy;
|
||||
m_dx = 1;
|
||||
m_dy = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if(flag)
|
||||
{
|
||||
m_inc_x += m_two_ry2;
|
||||
m_cur_f = fx;
|
||||
m_dx = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
m_inc_y += m_two_rx2;
|
||||
m_cur_f = fy;
|
||||
m_dy = 1;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_rx2;
|
||||
int m_ry2;
|
||||
int m_two_rx2;
|
||||
int m_two_ry2;
|
||||
int m_dx;
|
||||
int m_dy;
|
||||
int m_inc_x;
|
||||
int m_inc_y;
|
||||
int m_cur_f;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_EMBEDDED_RASTER_FONTS_INCLUDED
|
||||
#define AGG_EMBEDDED_RASTER_FONTS_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
extern const int8u gse4x6[];
|
||||
extern const int8u gse4x8[];
|
||||
extern const int8u gse5x7[];
|
||||
extern const int8u gse5x9[];
|
||||
extern const int8u gse6x12[];
|
||||
extern const int8u gse6x9[];
|
||||
extern const int8u gse7x11[];
|
||||
extern const int8u gse7x11_bold[];
|
||||
extern const int8u gse7x15[];
|
||||
extern const int8u gse7x15_bold[];
|
||||
extern const int8u gse8x16[];
|
||||
extern const int8u gse8x16_bold[];
|
||||
extern const int8u mcs11_prop[];
|
||||
extern const int8u mcs11_prop_condensed[];
|
||||
extern const int8u mcs12_prop[];
|
||||
extern const int8u mcs13_prop[];
|
||||
extern const int8u mcs5x10_mono[];
|
||||
extern const int8u mcs5x11_mono[];
|
||||
extern const int8u mcs6x10_mono[];
|
||||
extern const int8u mcs6x11_mono[];
|
||||
extern const int8u mcs7x12_mono_high[];
|
||||
extern const int8u mcs7x12_mono_low[];
|
||||
extern const int8u verdana12[];
|
||||
extern const int8u verdana12_bold[];
|
||||
extern const int8u verdana13[];
|
||||
extern const int8u verdana13_bold[];
|
||||
extern const int8u verdana14[];
|
||||
extern const int8u verdana14_bold[];
|
||||
extern const int8u verdana16[];
|
||||
extern const int8u verdana16_bold[];
|
||||
extern const int8u verdana17[];
|
||||
extern const int8u verdana17_bold[];
|
||||
extern const int8u verdana18[];
|
||||
extern const int8u verdana18_bold[];
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,418 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_FONT_CACHE_MANAGER_INCLUDED
|
||||
#define AGG_FONT_CACHE_MANAGER_INCLUDED
|
||||
|
||||
#include <string.h>
|
||||
#include "agg_array.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//---------------------------------------------------------glyph_data_type
|
||||
enum glyph_data_type
|
||||
{
|
||||
glyph_data_invalid = 0,
|
||||
glyph_data_mono = 1,
|
||||
glyph_data_gray8 = 2,
|
||||
glyph_data_outline = 3
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------------glyph_cache
|
||||
struct glyph_cache
|
||||
{
|
||||
unsigned glyph_index;
|
||||
int8u* data;
|
||||
unsigned data_size;
|
||||
glyph_data_type data_type;
|
||||
rect_i bounds;
|
||||
double advance_x;
|
||||
double advance_y;
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------font_cache
|
||||
class font_cache
|
||||
{
|
||||
public:
|
||||
enum block_size_e { block_size = 16384-16 };
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
font_cache() :
|
||||
m_allocator(block_size),
|
||||
m_font_signature(0)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void signature(const char* font_signature)
|
||||
{
|
||||
m_font_signature = (char*)m_allocator.allocate(strlen(font_signature) + 1);
|
||||
strcpy(m_font_signature, font_signature);
|
||||
memset(m_glyphs, 0, sizeof(m_glyphs));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
bool font_is(const char* font_signature) const
|
||||
{
|
||||
return strcmp(font_signature, m_font_signature) == 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const glyph_cache* find_glyph(unsigned glyph_code) const
|
||||
{
|
||||
unsigned msb = (glyph_code >> 8) & 0xFF;
|
||||
if(m_glyphs[msb])
|
||||
{
|
||||
return m_glyphs[msb][glyph_code & 0xFF];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
glyph_cache* cache_glyph(unsigned glyph_code,
|
||||
unsigned glyph_index,
|
||||
unsigned data_size,
|
||||
glyph_data_type data_type,
|
||||
const rect_i& bounds,
|
||||
double advance_x,
|
||||
double advance_y)
|
||||
{
|
||||
unsigned msb = (glyph_code >> 8) & 0xFF;
|
||||
if(m_glyphs[msb] == 0)
|
||||
{
|
||||
m_glyphs[msb] =
|
||||
(glyph_cache**)m_allocator.allocate(sizeof(glyph_cache*) * 256,
|
||||
sizeof(glyph_cache*));
|
||||
memset(m_glyphs[msb], 0, sizeof(glyph_cache*) * 256);
|
||||
}
|
||||
|
||||
unsigned lsb = glyph_code & 0xFF;
|
||||
if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite
|
||||
|
||||
glyph_cache* glyph =
|
||||
(glyph_cache*)m_allocator.allocate(sizeof(glyph_cache),
|
||||
sizeof(double));
|
||||
|
||||
glyph->glyph_index = glyph_index;
|
||||
glyph->data = m_allocator.allocate(data_size);
|
||||
glyph->data_size = data_size;
|
||||
glyph->data_type = data_type;
|
||||
glyph->bounds = bounds;
|
||||
glyph->advance_x = advance_x;
|
||||
glyph->advance_y = advance_y;
|
||||
return m_glyphs[msb][lsb] = glyph;
|
||||
}
|
||||
|
||||
private:
|
||||
block_allocator m_allocator;
|
||||
glyph_cache** m_glyphs[256];
|
||||
char* m_font_signature;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------font_cache_pool
|
||||
class font_cache_pool
|
||||
{
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
~font_cache_pool()
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < m_num_fonts; ++i)
|
||||
{
|
||||
obj_allocator<font_cache>::deallocate(m_fonts[i]);
|
||||
}
|
||||
pod_allocator<font_cache*>::deallocate(m_fonts, m_max_fonts);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
font_cache_pool(unsigned max_fonts=32) :
|
||||
m_fonts(pod_allocator<font_cache*>::allocate(max_fonts)),
|
||||
m_max_fonts(max_fonts),
|
||||
m_num_fonts(0),
|
||||
m_cur_font(0)
|
||||
{}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void font(const char* font_signature, bool reset_cache = false)
|
||||
{
|
||||
int idx = find_font(font_signature);
|
||||
if(idx >= 0)
|
||||
{
|
||||
if(reset_cache)
|
||||
{
|
||||
obj_allocator<font_cache>::deallocate(m_fonts[idx]);
|
||||
m_fonts[idx] = obj_allocator<font_cache>::allocate();
|
||||
m_fonts[idx]->signature(font_signature);
|
||||
}
|
||||
m_cur_font = m_fonts[idx];
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_num_fonts >= m_max_fonts)
|
||||
{
|
||||
obj_allocator<font_cache>::deallocate(m_fonts[0]);
|
||||
memcpy(m_fonts,
|
||||
m_fonts + 1,
|
||||
(m_max_fonts - 1) * sizeof(font_cache*));
|
||||
m_num_fonts = m_max_fonts - 1;
|
||||
}
|
||||
m_fonts[m_num_fonts] = obj_allocator<font_cache>::allocate();
|
||||
m_fonts[m_num_fonts]->signature(font_signature);
|
||||
m_cur_font = m_fonts[m_num_fonts];
|
||||
++m_num_fonts;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const font_cache* font() const
|
||||
{
|
||||
return m_cur_font;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const glyph_cache* find_glyph(unsigned glyph_code) const
|
||||
{
|
||||
if(m_cur_font) return m_cur_font->find_glyph(glyph_code);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
glyph_cache* cache_glyph(unsigned glyph_code,
|
||||
unsigned glyph_index,
|
||||
unsigned data_size,
|
||||
glyph_data_type data_type,
|
||||
const rect_i& bounds,
|
||||
double advance_x,
|
||||
double advance_y)
|
||||
{
|
||||
if(m_cur_font)
|
||||
{
|
||||
return m_cur_font->cache_glyph(glyph_code,
|
||||
glyph_index,
|
||||
data_size,
|
||||
data_type,
|
||||
bounds,
|
||||
advance_x,
|
||||
advance_y);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int find_font(const char* font_signature)
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < m_num_fonts; i++)
|
||||
{
|
||||
if(m_fonts[i]->font_is(font_signature)) return int(i);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private:
|
||||
font_cache** m_fonts;
|
||||
unsigned m_max_fonts;
|
||||
unsigned m_num_fonts;
|
||||
font_cache* m_cur_font;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
enum glyph_rendering
|
||||
{
|
||||
glyph_ren_native_mono,
|
||||
glyph_ren_native_gray8,
|
||||
glyph_ren_outline,
|
||||
glyph_ren_agg_mono,
|
||||
glyph_ren_agg_gray8
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------font_cache_manager
|
||||
template<class FontEngine> class font_cache_manager
|
||||
{
|
||||
public:
|
||||
typedef FontEngine font_engine_type;
|
||||
typedef font_cache_manager<FontEngine> self_type;
|
||||
typedef typename font_engine_type::path_adaptor_type path_adaptor_type;
|
||||
typedef typename font_engine_type::gray8_adaptor_type gray8_adaptor_type;
|
||||
typedef typename gray8_adaptor_type::embedded_scanline gray8_scanline_type;
|
||||
typedef typename font_engine_type::mono_adaptor_type mono_adaptor_type;
|
||||
typedef typename mono_adaptor_type::embedded_scanline mono_scanline_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
font_cache_manager(font_engine_type& engine, unsigned max_fonts=32) :
|
||||
m_fonts(max_fonts),
|
||||
m_engine(engine),
|
||||
m_change_stamp(-1),
|
||||
m_prev_glyph(0),
|
||||
m_last_glyph(0)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset_last_glyph()
|
||||
{
|
||||
m_prev_glyph = m_last_glyph = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const glyph_cache* glyph(unsigned glyph_code)
|
||||
{
|
||||
synchronize();
|
||||
const glyph_cache* gl = m_fonts.find_glyph(glyph_code);
|
||||
if(gl)
|
||||
{
|
||||
m_prev_glyph = m_last_glyph;
|
||||
return m_last_glyph = gl;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_engine.prepare_glyph(glyph_code))
|
||||
{
|
||||
m_prev_glyph = m_last_glyph;
|
||||
m_last_glyph = m_fonts.cache_glyph(glyph_code,
|
||||
m_engine.glyph_index(),
|
||||
m_engine.data_size(),
|
||||
m_engine.data_type(),
|
||||
m_engine.bounds(),
|
||||
m_engine.advance_x(),
|
||||
m_engine.advance_y());
|
||||
m_engine.write_glyph_to(m_last_glyph->data);
|
||||
return m_last_glyph;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void init_embedded_adaptors(const glyph_cache* gl,
|
||||
double x, double y,
|
||||
double scale=1.0)
|
||||
{
|
||||
if(gl)
|
||||
{
|
||||
switch(gl->data_type)
|
||||
{
|
||||
default: return;
|
||||
case glyph_data_mono:
|
||||
m_mono_adaptor.init(gl->data, gl->data_size, x, y);
|
||||
break;
|
||||
|
||||
case glyph_data_gray8:
|
||||
m_gray8_adaptor.init(gl->data, gl->data_size, x, y);
|
||||
break;
|
||||
|
||||
case glyph_data_outline:
|
||||
m_path_adaptor.init(gl->data, gl->data_size, x, y, scale);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
path_adaptor_type& path_adaptor() { return m_path_adaptor; }
|
||||
gray8_adaptor_type& gray8_adaptor() { return m_gray8_adaptor; }
|
||||
gray8_scanline_type& gray8_scanline() { return m_gray8_scanline; }
|
||||
mono_adaptor_type& mono_adaptor() { return m_mono_adaptor; }
|
||||
mono_scanline_type& mono_scanline() { return m_mono_scanline; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const glyph_cache* perv_glyph() const { return m_prev_glyph; }
|
||||
const glyph_cache* last_glyph() const { return m_last_glyph; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
bool add_kerning(double* x, double* y)
|
||||
{
|
||||
if(m_prev_glyph && m_last_glyph)
|
||||
{
|
||||
return m_engine.add_kerning(m_prev_glyph->glyph_index,
|
||||
m_last_glyph->glyph_index,
|
||||
x, y);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void precache(unsigned from, unsigned to)
|
||||
{
|
||||
for(; from <= to; ++from) glyph(from);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset_cache()
|
||||
{
|
||||
m_fonts.font(m_engine.font_signature(), true);
|
||||
m_change_stamp = m_engine.change_stamp();
|
||||
m_prev_glyph = m_last_glyph = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
font_cache_manager(const self_type&);
|
||||
const self_type& operator = (const self_type&);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void synchronize()
|
||||
{
|
||||
if(m_change_stamp != m_engine.change_stamp())
|
||||
{
|
||||
m_fonts.font(m_engine.font_signature());
|
||||
m_change_stamp = m_engine.change_stamp();
|
||||
m_prev_glyph = m_last_glyph = 0;
|
||||
}
|
||||
}
|
||||
|
||||
font_cache_pool m_fonts;
|
||||
font_engine_type& m_engine;
|
||||
int m_change_stamp;
|
||||
double m_dx;
|
||||
double m_dy;
|
||||
const glyph_cache* m_prev_glyph;
|
||||
const glyph_cache* m_last_glyph;
|
||||
path_adaptor_type m_path_adaptor;
|
||||
gray8_adaptor_type m_gray8_adaptor;
|
||||
gray8_scanline_type m_gray8_scanline;
|
||||
mono_adaptor_type m_mono_adaptor;
|
||||
mono_scanline_type m_mono_scanline;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_GAMMA_FUNCTIONS_INCLUDED
|
||||
#define AGG_GAMMA_FUNCTIONS_INCLUDED
|
||||
|
||||
#include <math.h>
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//===============================================================gamma_none
|
||||
struct gamma_none
|
||||
{
|
||||
double operator()(double x) const { return x; }
|
||||
};
|
||||
|
||||
|
||||
//==============================================================gamma_power
|
||||
class gamma_power
|
||||
{
|
||||
public:
|
||||
gamma_power() : m_gamma(1.0) {}
|
||||
gamma_power(double g) : m_gamma(g) {}
|
||||
|
||||
void gamma(double g) { m_gamma = g; }
|
||||
double gamma() const { return m_gamma; }
|
||||
|
||||
double operator() (double x) const
|
||||
{
|
||||
return pow(x, m_gamma);
|
||||
}
|
||||
|
||||
private:
|
||||
double m_gamma;
|
||||
};
|
||||
|
||||
|
||||
//==========================================================gamma_threshold
|
||||
class gamma_threshold
|
||||
{
|
||||
public:
|
||||
gamma_threshold() : m_threshold(0.5) {}
|
||||
gamma_threshold(double t) : m_threshold(t) {}
|
||||
|
||||
void threshold(double t) { m_threshold = t; }
|
||||
double threshold() const { return m_threshold; }
|
||||
|
||||
double operator() (double x) const
|
||||
{
|
||||
return (x < m_threshold) ? 0.0 : 1.0;
|
||||
}
|
||||
|
||||
private:
|
||||
double m_threshold;
|
||||
};
|
||||
|
||||
|
||||
//============================================================gamma_linear
|
||||
class gamma_linear
|
||||
{
|
||||
public:
|
||||
gamma_linear() : m_start(0.0), m_end(1.0) {}
|
||||
gamma_linear(double s, double e) : m_start(s), m_end(e) {}
|
||||
|
||||
void set(double s, double e) { m_start = s; m_end = e; }
|
||||
void start(double s) { m_start = s; }
|
||||
void end(double e) { m_end = e; }
|
||||
double start() const { return m_start; }
|
||||
double end() const { return m_end; }
|
||||
|
||||
double operator() (double x) const
|
||||
{
|
||||
if(x < m_start) return 0.0;
|
||||
if(x > m_end) return 1.0;
|
||||
return (x - m_start) / (m_end - m_start);
|
||||
}
|
||||
|
||||
private:
|
||||
double m_start;
|
||||
double m_end;
|
||||
};
|
||||
|
||||
|
||||
//==========================================================gamma_multiply
|
||||
class gamma_multiply
|
||||
{
|
||||
public:
|
||||
gamma_multiply() : m_mul(1.0) {}
|
||||
gamma_multiply(double v) : m_mul(v) {}
|
||||
|
||||
void value(double v) { m_mul = v; }
|
||||
double value() const { return m_mul; }
|
||||
|
||||
double operator() (double x) const
|
||||
{
|
||||
double y = x * m_mul;
|
||||
if(y > 1.0) y = 1.0;
|
||||
return y;
|
||||
}
|
||||
|
||||
private:
|
||||
double m_mul;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_GAMMA_LUT_INCLUDED
|
||||
#define AGG_GAMMA_LUT_INCLUDED
|
||||
|
||||
#include <math.h>
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
template<class LoResT=int8u,
|
||||
class HiResT=int8u,
|
||||
unsigned GammaShift=8,
|
||||
unsigned HiResShift=8> class gamma_lut
|
||||
{
|
||||
public:
|
||||
typedef gamma_lut<LoResT, HiResT, GammaShift, HiResShift> self_type;
|
||||
|
||||
enum gamma_scale_e
|
||||
{
|
||||
gamma_shift = GammaShift,
|
||||
gamma_size = 1 << gamma_shift,
|
||||
gamma_mask = gamma_size - 1
|
||||
};
|
||||
|
||||
enum hi_res_scale_e
|
||||
{
|
||||
hi_res_shift = HiResShift,
|
||||
hi_res_size = 1 << hi_res_shift,
|
||||
hi_res_mask = hi_res_size - 1
|
||||
};
|
||||
|
||||
~gamma_lut()
|
||||
{
|
||||
pod_allocator<LoResT>::deallocate(m_inv_gamma, hi_res_size);
|
||||
pod_allocator<HiResT>::deallocate(m_dir_gamma, gamma_size);
|
||||
}
|
||||
|
||||
gamma_lut() :
|
||||
m_gamma(1.0),
|
||||
m_dir_gamma(pod_allocator<HiResT>::allocate(gamma_size)),
|
||||
m_inv_gamma(pod_allocator<LoResT>::allocate(hi_res_size))
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < gamma_size; i++)
|
||||
{
|
||||
m_dir_gamma[i] = HiResT(i << (hi_res_shift - gamma_shift));
|
||||
}
|
||||
|
||||
for(i = 0; i < hi_res_size; i++)
|
||||
{
|
||||
m_inv_gamma[i] = LoResT(i >> (hi_res_shift - gamma_shift));
|
||||
}
|
||||
}
|
||||
|
||||
gamma_lut(double g) :
|
||||
m_gamma(1.0),
|
||||
m_dir_gamma(pod_allocator<HiResT>::allocate(gamma_size)),
|
||||
m_inv_gamma(pod_allocator<LoResT>::allocate(hi_res_size))
|
||||
{
|
||||
gamma(g);
|
||||
}
|
||||
|
||||
void gamma(double g)
|
||||
{
|
||||
m_gamma = g;
|
||||
|
||||
unsigned i;
|
||||
for(i = 0; i < gamma_size; i++)
|
||||
{
|
||||
m_dir_gamma[i] = (HiResT)
|
||||
uround(pow(i / double(gamma_mask), m_gamma) * double(hi_res_mask));
|
||||
}
|
||||
|
||||
double inv_g = 1.0 / g;
|
||||
for(i = 0; i < hi_res_size; i++)
|
||||
{
|
||||
m_inv_gamma[i] = (LoResT)
|
||||
uround(pow(i / double(hi_res_mask), inv_g) * double(gamma_mask));
|
||||
}
|
||||
}
|
||||
|
||||
double gamma() const
|
||||
{
|
||||
return m_gamma;
|
||||
}
|
||||
|
||||
HiResT dir(LoResT v) const
|
||||
{
|
||||
return m_dir_gamma[unsigned(v)];
|
||||
}
|
||||
|
||||
LoResT inv(HiResT v) const
|
||||
{
|
||||
return m_inv_gamma[unsigned(v)];
|
||||
}
|
||||
|
||||
private:
|
||||
gamma_lut(const self_type&);
|
||||
const self_type& operator = (const self_type&);
|
||||
|
||||
double m_gamma;
|
||||
HiResT* m_dir_gamma;
|
||||
LoResT* m_inv_gamma;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,164 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_GLYPH_RASTER_BIN_INCLUDED
|
||||
#define AGG_GLYPH_RASTER_BIN_INCLUDED
|
||||
|
||||
#include <string.h>
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//========================================================glyph_raster_bin
|
||||
template<class ColorT> class glyph_raster_bin
|
||||
{
|
||||
public:
|
||||
typedef ColorT color_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
struct glyph_rect
|
||||
{
|
||||
int x1,y1,x2,y2;
|
||||
double dx, dy;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
glyph_raster_bin(const int8u* font) :
|
||||
m_font(font),
|
||||
m_big_endian(false)
|
||||
{
|
||||
int t = 1;
|
||||
if(*(char*)&t == 0) m_big_endian = true;
|
||||
memset(m_span, 0, sizeof(m_span));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const int8u* font() const { return m_font; }
|
||||
void font(const int8u* f) { m_font = f; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
double height() const { return m_font[0]; }
|
||||
double base_line() const { return m_font[1]; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class CharT>
|
||||
double width(const CharT* str) const
|
||||
{
|
||||
unsigned start_char = m_font[2];
|
||||
unsigned num_chars = m_font[3];
|
||||
|
||||
unsigned w = 0;
|
||||
while(*str)
|
||||
{
|
||||
unsigned glyph = *str;
|
||||
const int8u* bits = m_font + 4 + num_chars * 2 +
|
||||
value(m_font + 4 + (glyph - start_char) * 2);
|
||||
w += *bits;
|
||||
++str;
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare(glyph_rect* r, double x, double y, unsigned glyph, bool flip)
|
||||
{
|
||||
unsigned start_char = m_font[2];
|
||||
unsigned num_chars = m_font[3];
|
||||
|
||||
m_bits = m_font + 4 + num_chars * 2 +
|
||||
value(m_font + 4 + (glyph - start_char) * 2);
|
||||
|
||||
m_glyph_width = *m_bits++;
|
||||
m_glyph_byte_width = (m_glyph_width + 7) >> 3;
|
||||
|
||||
r->x1 = int(x);
|
||||
r->x2 = r->x1 + m_glyph_width - 1;
|
||||
if(flip)
|
||||
{
|
||||
r->y1 = int(y) - m_font[0] + m_font[1];
|
||||
r->y2 = r->y1 + m_font[0] - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
r->y1 = int(y) - m_font[1] + 1;
|
||||
r->y2 = r->y1 + m_font[0] - 1;
|
||||
}
|
||||
r->dx = m_glyph_width;
|
||||
r->dy = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const cover_type* span(unsigned i)
|
||||
{
|
||||
i = m_font[0] - i - 1;
|
||||
const int8u* bits = m_bits + i * m_glyph_byte_width;
|
||||
unsigned j;
|
||||
unsigned val = *bits;
|
||||
unsigned nb = 0;
|
||||
for(j = 0; j < m_glyph_width; ++j)
|
||||
{
|
||||
m_span[j] = (cover_type)((val & 0x80) ? cover_full : cover_none);
|
||||
val <<= 1;
|
||||
if(++nb >= 8)
|
||||
{
|
||||
val = *++bits;
|
||||
nb = 0;
|
||||
}
|
||||
}
|
||||
return m_span;
|
||||
}
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
int16u value(const int8u* p) const
|
||||
{
|
||||
int16u v;
|
||||
if(m_big_endian)
|
||||
{
|
||||
*(int8u*)&v = p[1];
|
||||
*((int8u*)&v + 1) = p[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
*(int8u*)&v = p[0];
|
||||
*((int8u*)&v + 1) = p[1];
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const int8u* m_font;
|
||||
bool m_big_endian;
|
||||
cover_type m_span[32];
|
||||
const int8u* m_bits;
|
||||
unsigned m_glyph_width;
|
||||
unsigned m_glyph_byte_width;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,253 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_GRADIENT_LUT_INCLUDED
|
||||
#define AGG_GRADIENT_LUT_INCLUDED
|
||||
|
||||
#include "agg_array.h"
|
||||
#include "agg_dda_line.h"
|
||||
#include "agg_color_rgba.h"
|
||||
#include "agg_color_gray.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//======================================================color_interpolator
|
||||
template<class ColorT> struct color_interpolator
|
||||
{
|
||||
public:
|
||||
typedef ColorT color_type;
|
||||
|
||||
color_interpolator(const color_type& c1,
|
||||
const color_type& c2,
|
||||
unsigned len) :
|
||||
m_c1(c1),
|
||||
m_c2(c2),
|
||||
m_len(len),
|
||||
m_count(0)
|
||||
{}
|
||||
|
||||
void operator ++ ()
|
||||
{
|
||||
++m_count;
|
||||
}
|
||||
|
||||
color_type color() const
|
||||
{
|
||||
return m_c1.gradient(m_c2, double(m_count) / m_len);
|
||||
}
|
||||
|
||||
private:
|
||||
color_type m_c1;
|
||||
color_type m_c2;
|
||||
unsigned m_len;
|
||||
unsigned m_count;
|
||||
};
|
||||
|
||||
//========================================================================
|
||||
// Fast specialization for rgba8
|
||||
template<> struct color_interpolator<rgba8>
|
||||
{
|
||||
public:
|
||||
typedef rgba8 color_type;
|
||||
|
||||
color_interpolator(const color_type& c1,
|
||||
const color_type& c2,
|
||||
unsigned len) :
|
||||
r(c1.r, c2.r, len),
|
||||
g(c1.g, c2.g, len),
|
||||
b(c1.b, c2.b, len),
|
||||
a(c1.a, c2.a, len)
|
||||
{}
|
||||
|
||||
void operator ++ ()
|
||||
{
|
||||
++r; ++g; ++b; ++a;
|
||||
}
|
||||
|
||||
color_type color() const
|
||||
{
|
||||
return color_type(r.y(), g.y(), b.y(), a.y());
|
||||
}
|
||||
|
||||
private:
|
||||
agg::dda_line_interpolator<14> r, g, b, a;
|
||||
};
|
||||
|
||||
//========================================================================
|
||||
// Fast specialization for gray8
|
||||
template<> struct color_interpolator<gray8>
|
||||
{
|
||||
public:
|
||||
typedef gray8 color_type;
|
||||
|
||||
color_interpolator(const color_type& c1,
|
||||
const color_type& c2,
|
||||
unsigned len) :
|
||||
v(c1.v, c2.v, len),
|
||||
a(c1.a, c2.a, len)
|
||||
{}
|
||||
|
||||
void operator ++ ()
|
||||
{
|
||||
++v; ++a;
|
||||
}
|
||||
|
||||
color_type color() const
|
||||
{
|
||||
return color_type(v.y(), a.y());
|
||||
}
|
||||
|
||||
private:
|
||||
agg::dda_line_interpolator<14> v,a;
|
||||
};
|
||||
|
||||
//============================================================gradient_lut
|
||||
template<class ColorInterpolator,
|
||||
unsigned ColorLutSize=256> class gradient_lut
|
||||
{
|
||||
public:
|
||||
typedef ColorInterpolator interpolator_type;
|
||||
typedef typename interpolator_type::color_type color_type;
|
||||
enum { color_lut_size = ColorLutSize };
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gradient_lut() : m_color_lut(color_lut_size) {}
|
||||
|
||||
// Build Gradient Lut
|
||||
// First, call remove_all(), then add_color() at least twice,
|
||||
// then build_lut(). Argument "offset" in add_color must be
|
||||
// in range [0...1] and defines a color stop as it is described
|
||||
// in SVG specification, section Gradients and Patterns.
|
||||
// The simplest linear gradient is:
|
||||
// gradient_lut.add_color(0.0, start_color);
|
||||
// gradient_lut.add_color(1.0, end_color);
|
||||
//--------------------------------------------------------------------
|
||||
void remove_all();
|
||||
void add_color(double offset, const color_type& color);
|
||||
void build_lut();
|
||||
|
||||
// Size-index Interface. This class can be used directly as the
|
||||
// ColorF in span_gradient. All it needs is two access methods
|
||||
// size() and operator [].
|
||||
//--------------------------------------------------------------------
|
||||
static unsigned size()
|
||||
{
|
||||
return color_lut_size;
|
||||
}
|
||||
const color_type& operator [] (unsigned i) const
|
||||
{
|
||||
return m_color_lut[i];
|
||||
}
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
struct color_point
|
||||
{
|
||||
double offset;
|
||||
color_type color;
|
||||
|
||||
color_point() {}
|
||||
color_point(double off, const color_type& c) :
|
||||
offset(off), color(c)
|
||||
{
|
||||
if(offset < 0.0) offset = 0.0;
|
||||
if(offset > 1.0) offset = 1.0;
|
||||
}
|
||||
};
|
||||
typedef agg::pod_bvector<color_point, 4> color_profile_type;
|
||||
typedef agg::pod_array<color_type> color_lut_type;
|
||||
|
||||
static bool offset_less(const color_point& a, const color_point& b)
|
||||
{
|
||||
return a.offset < b.offset;
|
||||
}
|
||||
static bool offset_equal(const color_point& a, const color_point& b)
|
||||
{
|
||||
return a.offset == b.offset;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
color_profile_type m_color_profile;
|
||||
color_lut_type m_color_lut;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class T, unsigned S>
|
||||
void gradient_lut<T,S>::remove_all()
|
||||
{
|
||||
m_color_profile.remove_all();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class T, unsigned S>
|
||||
void gradient_lut<T,S>::add_color(double offset, const color_type& color)
|
||||
{
|
||||
m_color_profile.add(color_point(offset, color));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class T, unsigned S>
|
||||
void gradient_lut<T,S>::build_lut()
|
||||
{
|
||||
quick_sort(m_color_profile, offset_less);
|
||||
m_color_profile.cut_at(remove_duplicates(m_color_profile, offset_equal));
|
||||
if(m_color_profile.size() >= 2)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned start = uround(m_color_profile[0].offset * color_lut_size);
|
||||
unsigned end;
|
||||
color_type c = m_color_profile[0].color;
|
||||
for(i = 0; i < start; i++)
|
||||
{
|
||||
m_color_lut[i] = c;
|
||||
}
|
||||
for(i = 1; i < m_color_profile.size(); i++)
|
||||
{
|
||||
end = uround(m_color_profile[i].offset * color_lut_size);
|
||||
interpolator_type ci(m_color_profile[i-1].color,
|
||||
m_color_profile[i ].color,
|
||||
end - start + 1);
|
||||
while(start < end)
|
||||
{
|
||||
m_color_lut[start] = ci.color();
|
||||
++ci;
|
||||
++start;
|
||||
}
|
||||
}
|
||||
c = m_color_profile.last().color;
|
||||
for(; end < m_color_lut.size(); end++)
|
||||
{
|
||||
m_color_lut[end] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,158 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_GSV_TEXT_INCLUDED
|
||||
#define AGG_GSV_TEXT_INCLUDED
|
||||
|
||||
#include "agg_array.h"
|
||||
#include "agg_conv_stroke.h"
|
||||
#include "agg_conv_transform.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
|
||||
//---------------------------------------------------------------gsv_text
|
||||
//
|
||||
// See Implementation agg_gsv_text.cpp
|
||||
//
|
||||
class gsv_text
|
||||
{
|
||||
enum status
|
||||
{
|
||||
initial,
|
||||
next_char,
|
||||
start_glyph,
|
||||
glyph
|
||||
};
|
||||
|
||||
public:
|
||||
gsv_text();
|
||||
|
||||
void font(const void* font);
|
||||
void flip(bool flip_y) { m_flip = flip_y; }
|
||||
void load_font(const char* file);
|
||||
void size(double height, double width=0.0);
|
||||
void space(double space);
|
||||
void line_space(double line_space);
|
||||
void start_point(double x, double y);
|
||||
void text(const char* text);
|
||||
|
||||
double text_width();
|
||||
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
// not supposed to be copied
|
||||
gsv_text(const gsv_text&);
|
||||
const gsv_text& operator = (const gsv_text&);
|
||||
|
||||
int16u value(const int8u* p) const
|
||||
{
|
||||
int16u v;
|
||||
if(m_big_endian)
|
||||
{
|
||||
*(int8u*)&v = p[1];
|
||||
*((int8u*)&v + 1) = p[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
*(int8u*)&v = p[0];
|
||||
*((int8u*)&v + 1) = p[1];
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
private:
|
||||
double m_x;
|
||||
double m_y;
|
||||
double m_start_x;
|
||||
double m_width;
|
||||
double m_height;
|
||||
double m_space;
|
||||
double m_line_space;
|
||||
char m_chr[2];
|
||||
char* m_text;
|
||||
pod_array<char> m_text_buf;
|
||||
char* m_cur_chr;
|
||||
const void* m_font;
|
||||
pod_array<char> m_loaded_font;
|
||||
status m_status;
|
||||
bool m_big_endian;
|
||||
bool m_flip;
|
||||
int8u* m_indices;
|
||||
int8* m_glyphs;
|
||||
int8* m_bglyph;
|
||||
int8* m_eglyph;
|
||||
double m_w;
|
||||
double m_h;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------gsv_text_outline
|
||||
template<class Transformer = trans_affine> class gsv_text_outline
|
||||
{
|
||||
public:
|
||||
gsv_text_outline(gsv_text& text, const Transformer& trans) :
|
||||
m_polyline(text),
|
||||
m_trans(m_polyline, trans)
|
||||
{
|
||||
}
|
||||
|
||||
void width(double w)
|
||||
{
|
||||
m_polyline.width(w);
|
||||
}
|
||||
|
||||
void transformer(const Transformer* trans)
|
||||
{
|
||||
m_trans->transformer(trans);
|
||||
}
|
||||
|
||||
void rewind(unsigned path_id)
|
||||
{
|
||||
m_trans.rewind(path_id);
|
||||
m_polyline.line_join(round_join);
|
||||
m_polyline.line_cap(round_cap);
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
return m_trans.vertex(x, y);
|
||||
}
|
||||
|
||||
private:
|
||||
conv_stroke<gsv_text> m_polyline;
|
||||
conv_transform<conv_stroke<gsv_text>, Transformer> m_trans;
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,490 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_IMAGE_ACCESSORS_INCLUDED
|
||||
#define AGG_IMAGE_ACCESSORS_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-----------------------------------------------------image_accessor_clip
|
||||
template<class PixFmt> class image_accessor_clip
|
||||
{
|
||||
public:
|
||||
typedef PixFmt pixfmt_type;
|
||||
typedef typename pixfmt_type::color_type color_type;
|
||||
typedef typename pixfmt_type::order_type order_type;
|
||||
typedef typename pixfmt_type::value_type value_type;
|
||||
enum pix_width_e { pix_width = pixfmt_type::pix_width };
|
||||
|
||||
image_accessor_clip() {}
|
||||
explicit image_accessor_clip(const pixfmt_type& pixf,
|
||||
const color_type& bk) :
|
||||
m_pixf(&pixf)
|
||||
{
|
||||
pixfmt_type::make_pix(m_bk_buf, bk);
|
||||
}
|
||||
|
||||
void attach(const pixfmt_type& pixf)
|
||||
{
|
||||
m_pixf = &pixf;
|
||||
}
|
||||
|
||||
void background_color(const color_type& bk)
|
||||
{
|
||||
pixfmt_type::make_pix(m_bk_buf, bk);
|
||||
}
|
||||
|
||||
private:
|
||||
AGG_INLINE const int8u* pixel() const
|
||||
{
|
||||
if(m_y >= 0 && m_y < (int)m_pixf->height() &&
|
||||
m_x >= 0 && m_x < (int)m_pixf->width())
|
||||
{
|
||||
return m_pixf->pix_ptr(m_x, m_y);
|
||||
}
|
||||
return m_bk_buf;
|
||||
}
|
||||
|
||||
public:
|
||||
AGG_INLINE const int8u* span(int x, int y, unsigned len)
|
||||
{
|
||||
m_x = m_x0 = x;
|
||||
m_y = y;
|
||||
if(y >= 0 && y < (int)m_pixf->height() &&
|
||||
x >= 0 && x+(int)len <= (int)m_pixf->width())
|
||||
{
|
||||
return m_pix_ptr = m_pixf->pix_ptr(x, y);
|
||||
}
|
||||
m_pix_ptr = 0;
|
||||
return pixel();
|
||||
}
|
||||
|
||||
AGG_INLINE const int8u* next_x()
|
||||
{
|
||||
if(m_pix_ptr) return m_pix_ptr += pix_width;
|
||||
++m_x;
|
||||
return pixel();
|
||||
}
|
||||
|
||||
AGG_INLINE const int8u* next_y()
|
||||
{
|
||||
++m_y;
|
||||
m_x = m_x0;
|
||||
if(m_pix_ptr &&
|
||||
m_y >= 0 && m_y < (int)m_pixf->height())
|
||||
{
|
||||
return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y);
|
||||
}
|
||||
m_pix_ptr = 0;
|
||||
return pixel();
|
||||
}
|
||||
|
||||
private:
|
||||
const pixfmt_type* m_pixf;
|
||||
int8u m_bk_buf[4];
|
||||
int m_x, m_x0, m_y;
|
||||
const int8u* m_pix_ptr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------image_accessor_no_clip
|
||||
template<class PixFmt> class image_accessor_no_clip
|
||||
{
|
||||
public:
|
||||
typedef PixFmt pixfmt_type;
|
||||
typedef typename pixfmt_type::color_type color_type;
|
||||
typedef typename pixfmt_type::order_type order_type;
|
||||
typedef typename pixfmt_type::value_type value_type;
|
||||
enum pix_width_e { pix_width = pixfmt_type::pix_width };
|
||||
|
||||
image_accessor_no_clip() {}
|
||||
explicit image_accessor_no_clip(const pixfmt_type& pixf) :
|
||||
m_pixf(&pixf)
|
||||
{}
|
||||
|
||||
void attach(const pixfmt_type& pixf)
|
||||
{
|
||||
m_pixf = &pixf;
|
||||
}
|
||||
|
||||
AGG_INLINE const int8u* span(int x, int y, unsigned)
|
||||
{
|
||||
m_x = x;
|
||||
m_y = y;
|
||||
return m_pix_ptr = m_pixf->pix_ptr(x, y);
|
||||
}
|
||||
|
||||
AGG_INLINE const int8u* next_x()
|
||||
{
|
||||
return m_pix_ptr += pix_width;
|
||||
}
|
||||
|
||||
AGG_INLINE const int8u* next_y()
|
||||
{
|
||||
++m_y;
|
||||
return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y);
|
||||
}
|
||||
|
||||
private:
|
||||
const pixfmt_type* m_pixf;
|
||||
int m_x, m_y;
|
||||
const int8u* m_pix_ptr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------image_accessor_clone
|
||||
template<class PixFmt> class image_accessor_clone
|
||||
{
|
||||
public:
|
||||
typedef PixFmt pixfmt_type;
|
||||
typedef typename pixfmt_type::color_type color_type;
|
||||
typedef typename pixfmt_type::order_type order_type;
|
||||
typedef typename pixfmt_type::value_type value_type;
|
||||
enum pix_width_e { pix_width = pixfmt_type::pix_width };
|
||||
|
||||
image_accessor_clone() {}
|
||||
explicit image_accessor_clone(const pixfmt_type& pixf) :
|
||||
m_pixf(&pixf)
|
||||
{}
|
||||
|
||||
void attach(const pixfmt_type& pixf)
|
||||
{
|
||||
m_pixf = &pixf;
|
||||
}
|
||||
|
||||
private:
|
||||
AGG_INLINE const int8u* pixel() const
|
||||
{
|
||||
register int x = m_x;
|
||||
register int y = m_y;
|
||||
if(x < 0) x = 0;
|
||||
if(y < 0) y = 0;
|
||||
if(x >= (int)m_pixf->width()) x = m_pixf->width() - 1;
|
||||
if(y >= (int)m_pixf->height()) y = m_pixf->height() - 1;
|
||||
return m_pixf->pix_ptr(x, y);
|
||||
}
|
||||
|
||||
public:
|
||||
AGG_INLINE const int8u* span(int x, int y, unsigned len)
|
||||
{
|
||||
m_x = m_x0 = x;
|
||||
m_y = y;
|
||||
if(y >= 0 && y < (int)m_pixf->height() &&
|
||||
x >= 0 && x+len <= (int)m_pixf->width())
|
||||
{
|
||||
return m_pix_ptr = m_pixf->pix_ptr(x, y);
|
||||
}
|
||||
m_pix_ptr = 0;
|
||||
return pixel();
|
||||
}
|
||||
|
||||
AGG_INLINE const int8u* next_x()
|
||||
{
|
||||
if(m_pix_ptr) return m_pix_ptr += pix_width;
|
||||
++m_x;
|
||||
return pixel();
|
||||
}
|
||||
|
||||
AGG_INLINE const int8u* next_y()
|
||||
{
|
||||
++m_y;
|
||||
m_x = m_x0;
|
||||
if(m_pix_ptr &&
|
||||
m_y >= 0 && m_y < (int)m_pixf->height())
|
||||
{
|
||||
return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y);
|
||||
}
|
||||
m_pix_ptr = 0;
|
||||
return pixel();
|
||||
}
|
||||
|
||||
private:
|
||||
const pixfmt_type* m_pixf;
|
||||
int m_x, m_x0, m_y;
|
||||
const int8u* m_pix_ptr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------image_accessor_wrap
|
||||
template<class PixFmt, class WrapX, class WrapY> class image_accessor_wrap
|
||||
{
|
||||
public:
|
||||
typedef PixFmt pixfmt_type;
|
||||
typedef typename pixfmt_type::color_type color_type;
|
||||
typedef typename pixfmt_type::order_type order_type;
|
||||
typedef typename pixfmt_type::value_type value_type;
|
||||
enum pix_width_e { pix_width = pixfmt_type::pix_width };
|
||||
|
||||
image_accessor_wrap() {}
|
||||
explicit image_accessor_wrap(const pixfmt_type& pixf) :
|
||||
m_pixf(&pixf),
|
||||
m_wrap_x(pixf.width()),
|
||||
m_wrap_y(pixf.height())
|
||||
{}
|
||||
|
||||
void attach(const pixfmt_type& pixf)
|
||||
{
|
||||
m_pixf = &pixf;
|
||||
}
|
||||
|
||||
AGG_INLINE const int8u* span(int x, int y, unsigned)
|
||||
{
|
||||
m_x = x;
|
||||
m_row_ptr = m_pixf->row_ptr(m_wrap_y(y));
|
||||
return m_row_ptr + m_wrap_x(x) * pix_width;
|
||||
}
|
||||
|
||||
AGG_INLINE const int8u* next_x()
|
||||
{
|
||||
int x = ++m_wrap_x;
|
||||
return m_row_ptr + x * pix_width;
|
||||
}
|
||||
|
||||
AGG_INLINE const int8u* next_y()
|
||||
{
|
||||
m_row_ptr = m_pixf->row_ptr(++m_wrap_y);
|
||||
return m_row_ptr + m_wrap_x(m_x) * pix_width;
|
||||
}
|
||||
|
||||
private:
|
||||
const pixfmt_type* m_pixf;
|
||||
const int8u* m_row_ptr;
|
||||
int m_x;
|
||||
WrapX m_wrap_x;
|
||||
WrapY m_wrap_y;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------wrap_mode_repeat
|
||||
class wrap_mode_repeat
|
||||
{
|
||||
public:
|
||||
wrap_mode_repeat() {}
|
||||
wrap_mode_repeat(unsigned size) :
|
||||
m_size(size),
|
||||
m_add(size * (0x3FFFFFFF / size)),
|
||||
m_value(0)
|
||||
{}
|
||||
|
||||
AGG_INLINE unsigned operator() (int v)
|
||||
{
|
||||
return m_value = (unsigned(v) + m_add) % m_size;
|
||||
}
|
||||
|
||||
AGG_INLINE unsigned operator++ ()
|
||||
{
|
||||
++m_value;
|
||||
if(m_value >= m_size) m_value = 0;
|
||||
return m_value;
|
||||
}
|
||||
private:
|
||||
unsigned m_size;
|
||||
unsigned m_add;
|
||||
unsigned m_value;
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------wrap_mode_repeat_pow2
|
||||
class wrap_mode_repeat_pow2
|
||||
{
|
||||
public:
|
||||
wrap_mode_repeat_pow2() {}
|
||||
wrap_mode_repeat_pow2(unsigned size) : m_value(0)
|
||||
{
|
||||
m_mask = 1;
|
||||
while(m_mask < size) m_mask = (m_mask << 1) | 1;
|
||||
m_mask >>= 1;
|
||||
}
|
||||
AGG_INLINE unsigned operator() (int v)
|
||||
{
|
||||
return m_value = unsigned(v) & m_mask;
|
||||
}
|
||||
AGG_INLINE unsigned operator++ ()
|
||||
{
|
||||
++m_value;
|
||||
if(m_value > m_mask) m_value = 0;
|
||||
return m_value;
|
||||
}
|
||||
private:
|
||||
unsigned m_mask;
|
||||
unsigned m_value;
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------wrap_mode_repeat_auto_pow2
|
||||
class wrap_mode_repeat_auto_pow2
|
||||
{
|
||||
public:
|
||||
wrap_mode_repeat_auto_pow2() {}
|
||||
wrap_mode_repeat_auto_pow2(unsigned size) :
|
||||
m_size(size),
|
||||
m_add(size * (0x3FFFFFFF / size)),
|
||||
m_mask((m_size & (m_size-1)) ? 0 : m_size-1),
|
||||
m_value(0)
|
||||
{}
|
||||
|
||||
AGG_INLINE unsigned operator() (int v)
|
||||
{
|
||||
if(m_mask) return m_value = unsigned(v) & m_mask;
|
||||
return m_value = (unsigned(v) + m_add) % m_size;
|
||||
}
|
||||
AGG_INLINE unsigned operator++ ()
|
||||
{
|
||||
++m_value;
|
||||
if(m_value >= m_size) m_value = 0;
|
||||
return m_value;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned m_size;
|
||||
unsigned m_add;
|
||||
unsigned m_mask;
|
||||
unsigned m_value;
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------wrap_mode_reflect
|
||||
class wrap_mode_reflect
|
||||
{
|
||||
public:
|
||||
wrap_mode_reflect() {}
|
||||
wrap_mode_reflect(unsigned size) :
|
||||
m_size(size),
|
||||
m_size2(size * 2),
|
||||
m_add(m_size2 * (0x3FFFFFFF / m_size2)),
|
||||
m_value(0)
|
||||
{}
|
||||
|
||||
AGG_INLINE unsigned operator() (int v)
|
||||
{
|
||||
m_value = (unsigned(v) + m_add) % m_size2;
|
||||
if(m_value >= m_size) return m_size2 - m_value - 1;
|
||||
return m_value;
|
||||
}
|
||||
|
||||
AGG_INLINE unsigned operator++ ()
|
||||
{
|
||||
++m_value;
|
||||
if(m_value >= m_size2) m_value = 0;
|
||||
if(m_value >= m_size) return m_size2 - m_value - 1;
|
||||
return m_value;
|
||||
}
|
||||
private:
|
||||
unsigned m_size;
|
||||
unsigned m_size2;
|
||||
unsigned m_add;
|
||||
unsigned m_value;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------wrap_mode_reflect_pow2
|
||||
class wrap_mode_reflect_pow2
|
||||
{
|
||||
public:
|
||||
wrap_mode_reflect_pow2() {}
|
||||
wrap_mode_reflect_pow2(unsigned size) : m_value(0)
|
||||
{
|
||||
m_mask = 1;
|
||||
m_size = 1;
|
||||
while(m_mask < size)
|
||||
{
|
||||
m_mask = (m_mask << 1) | 1;
|
||||
m_size <<= 1;
|
||||
}
|
||||
}
|
||||
AGG_INLINE unsigned operator() (int v)
|
||||
{
|
||||
m_value = unsigned(v) & m_mask;
|
||||
if(m_value >= m_size) return m_mask - m_value;
|
||||
return m_value;
|
||||
}
|
||||
AGG_INLINE unsigned operator++ ()
|
||||
{
|
||||
++m_value;
|
||||
m_value &= m_mask;
|
||||
if(m_value >= m_size) return m_mask - m_value;
|
||||
return m_value;
|
||||
}
|
||||
private:
|
||||
unsigned m_size;
|
||||
unsigned m_mask;
|
||||
unsigned m_value;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------wrap_mode_reflect_auto_pow2
|
||||
class wrap_mode_reflect_auto_pow2
|
||||
{
|
||||
public:
|
||||
wrap_mode_reflect_auto_pow2() {}
|
||||
wrap_mode_reflect_auto_pow2(unsigned size) :
|
||||
m_size(size),
|
||||
m_size2(size * 2),
|
||||
m_add(m_size2 * (0x3FFFFFFF / m_size2)),
|
||||
m_mask((m_size2 & (m_size2-1)) ? 0 : m_size2-1),
|
||||
m_value(0)
|
||||
{}
|
||||
|
||||
AGG_INLINE unsigned operator() (int v)
|
||||
{
|
||||
m_value = m_mask ? unsigned(v) & m_mask :
|
||||
(unsigned(v) + m_add) % m_size2;
|
||||
if(m_value >= m_size) return m_size2 - m_value - 1;
|
||||
return m_value;
|
||||
}
|
||||
AGG_INLINE unsigned operator++ ()
|
||||
{
|
||||
++m_value;
|
||||
if(m_value >= m_size2) m_value = 0;
|
||||
if(m_value >= m_size) return m_size2 - m_value - 1;
|
||||
return m_value;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned m_size;
|
||||
unsigned m_size2;
|
||||
unsigned m_add;
|
||||
unsigned m_mask;
|
||||
unsigned m_value;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,453 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_IMAGE_FILTERS_INCLUDED
|
||||
#define AGG_IMAGE_FILTERS_INCLUDED
|
||||
|
||||
#include "agg_array.h"
|
||||
#include "agg_math.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
// See Implementation agg_image_filters.cpp
|
||||
|
||||
enum image_filter_scale_e
|
||||
{
|
||||
image_filter_shift = 14, //----image_filter_shift
|
||||
image_filter_scale = 1 << image_filter_shift, //----image_filter_scale
|
||||
image_filter_mask = image_filter_scale - 1 //----image_filter_mask
|
||||
};
|
||||
|
||||
enum image_subpixel_scale_e
|
||||
{
|
||||
image_subpixel_shift = 8, //----image_subpixel_shift
|
||||
image_subpixel_scale = 1 << image_subpixel_shift, //----image_subpixel_scale
|
||||
image_subpixel_mask = image_subpixel_scale - 1 //----image_subpixel_mask
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------image_filter_lut
|
||||
class image_filter_lut
|
||||
{
|
||||
public:
|
||||
template<class FilterF> void calculate(const FilterF& filter,
|
||||
bool normalization=true)
|
||||
{
|
||||
double r = filter.radius();
|
||||
realloc_lut(r);
|
||||
unsigned i;
|
||||
unsigned pivot = diameter() << (image_subpixel_shift - 1);
|
||||
for(i = 0; i < pivot; i++)
|
||||
{
|
||||
double x = double(i) / double(image_subpixel_scale);
|
||||
double y = filter.calc_weight(x);
|
||||
m_weight_array[pivot + i] =
|
||||
m_weight_array[pivot - i] = (int16)iround(y * image_filter_scale);
|
||||
}
|
||||
unsigned end = (diameter() << image_subpixel_shift) - 1;
|
||||
m_weight_array[0] = m_weight_array[end];
|
||||
if(normalization)
|
||||
{
|
||||
normalize();
|
||||
}
|
||||
}
|
||||
|
||||
image_filter_lut() : m_radius(0), m_diameter(0), m_start(0) {}
|
||||
|
||||
template<class FilterF> image_filter_lut(const FilterF& filter,
|
||||
bool normalization=true)
|
||||
{
|
||||
calculate(filter, normalization);
|
||||
}
|
||||
|
||||
double radius() const { return m_radius; }
|
||||
unsigned diameter() const { return m_diameter; }
|
||||
int start() const { return m_start; }
|
||||
const int16* weight_array() const { return &m_weight_array[0]; }
|
||||
void normalize();
|
||||
|
||||
private:
|
||||
void realloc_lut(double radius);
|
||||
image_filter_lut(const image_filter_lut&);
|
||||
const image_filter_lut& operator = (const image_filter_lut&);
|
||||
|
||||
double m_radius;
|
||||
unsigned m_diameter;
|
||||
int m_start;
|
||||
pod_array<int16> m_weight_array;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------image_filter
|
||||
template<class FilterF> class image_filter : public image_filter_lut
|
||||
{
|
||||
public:
|
||||
image_filter()
|
||||
{
|
||||
calculate(m_filter_function);
|
||||
}
|
||||
private:
|
||||
FilterF m_filter_function;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------image_filter_bilinear
|
||||
struct image_filter_bilinear
|
||||
{
|
||||
static double radius() { return 1.0; }
|
||||
static double calc_weight(double x)
|
||||
{
|
||||
return 1.0 - x;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------image_filter_hanning
|
||||
struct image_filter_hanning
|
||||
{
|
||||
static double radius() { return 1.0; }
|
||||
static double calc_weight(double x)
|
||||
{
|
||||
return 0.5 + 0.5 * cos(pi * x);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------image_filter_hamming
|
||||
struct image_filter_hamming
|
||||
{
|
||||
static double radius() { return 1.0; }
|
||||
static double calc_weight(double x)
|
||||
{
|
||||
return 0.54 + 0.46 * cos(pi * x);
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------image_filter_hermite
|
||||
struct image_filter_hermite
|
||||
{
|
||||
static double radius() { return 1.0; }
|
||||
static double calc_weight(double x)
|
||||
{
|
||||
return (2.0 * x - 3.0) * x * x + 1.0;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------image_filter_quadric
|
||||
struct image_filter_quadric
|
||||
{
|
||||
static double radius() { return 1.5; }
|
||||
static double calc_weight(double x)
|
||||
{
|
||||
double t;
|
||||
if(x < 0.5) return 0.75 - x * x;
|
||||
if(x < 1.5) {t = x - 1.5; return 0.5 * t * t;}
|
||||
return 0.0;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------image_filter_bicubic
|
||||
class image_filter_bicubic
|
||||
{
|
||||
static double pow3(double x)
|
||||
{
|
||||
return (x <= 0.0) ? 0.0 : x * x * x;
|
||||
}
|
||||
|
||||
public:
|
||||
static double radius() { return 2.0; }
|
||||
static double calc_weight(double x)
|
||||
{
|
||||
return
|
||||
(1.0/6.0) *
|
||||
(pow3(x + 2) - 4 * pow3(x + 1) + 6 * pow3(x) - 4 * pow3(x - 1));
|
||||
}
|
||||
};
|
||||
|
||||
//-------------------------------------------------image_filter_kaiser
|
||||
class image_filter_kaiser
|
||||
{
|
||||
double a;
|
||||
double i0a;
|
||||
double epsilon;
|
||||
|
||||
public:
|
||||
image_filter_kaiser(double b = 6.33) :
|
||||
a(b), epsilon(1e-12)
|
||||
{
|
||||
i0a = 1.0 / bessel_i0(b);
|
||||
}
|
||||
|
||||
static double radius() { return 1.0; }
|
||||
double calc_weight(double x) const
|
||||
{
|
||||
return bessel_i0(a * sqrt(1. - x * x)) * i0a;
|
||||
}
|
||||
|
||||
private:
|
||||
double bessel_i0(double x) const
|
||||
{
|
||||
int i;
|
||||
double sum, y, t;
|
||||
|
||||
sum = 1.;
|
||||
y = x * x / 4.;
|
||||
t = y;
|
||||
|
||||
for(i = 2; t > epsilon; i++)
|
||||
{
|
||||
sum += t;
|
||||
t *= (double)y / (i * i);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------image_filter_catrom
|
||||
struct image_filter_catrom
|
||||
{
|
||||
static double radius() { return 2.0; }
|
||||
static double calc_weight(double x)
|
||||
{
|
||||
if(x < 1.0) return 0.5 * (2.0 + x * x * (-5.0 + x * 3.0));
|
||||
if(x < 2.0) return 0.5 * (4.0 + x * (-8.0 + x * (5.0 - x)));
|
||||
return 0.;
|
||||
}
|
||||
};
|
||||
|
||||
//---------------------------------------------image_filter_mitchell
|
||||
class image_filter_mitchell
|
||||
{
|
||||
double p0, p2, p3;
|
||||
double q0, q1, q2, q3;
|
||||
|
||||
public:
|
||||
image_filter_mitchell(double b = 1.0/3.0, double c = 1.0/3.0) :
|
||||
p0((6.0 - 2.0 * b) / 6.0),
|
||||
p2((-18.0 + 12.0 * b + 6.0 * c) / 6.0),
|
||||
p3((12.0 - 9.0 * b - 6.0 * c) / 6.0),
|
||||
q0((8.0 * b + 24.0 * c) / 6.0),
|
||||
q1((-12.0 * b - 48.0 * c) / 6.0),
|
||||
q2((6.0 * b + 30.0 * c) / 6.0),
|
||||
q3((-b - 6.0 * c) / 6.0)
|
||||
{}
|
||||
|
||||
static double radius() { return 2.0; }
|
||||
double calc_weight(double x) const
|
||||
{
|
||||
if(x < 1.0) return p0 + x * x * (p2 + x * p3);
|
||||
if(x < 2.0) return q0 + x * (q1 + x * (q2 + x * q3));
|
||||
return 0.0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------image_filter_spline16
|
||||
struct image_filter_spline16
|
||||
{
|
||||
static double radius() { return 2.0; }
|
||||
static double calc_weight(double x)
|
||||
{
|
||||
if(x < 1.0)
|
||||
{
|
||||
return ((x - 9.0/5.0 ) * x - 1.0/5.0 ) * x + 1.0;
|
||||
}
|
||||
return ((-1.0/3.0 * (x-1) + 4.0/5.0) * (x-1) - 7.0/15.0 ) * (x-1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------image_filter_spline36
|
||||
struct image_filter_spline36
|
||||
{
|
||||
static double radius() { return 3.0; }
|
||||
static double calc_weight(double x)
|
||||
{
|
||||
if(x < 1.0)
|
||||
{
|
||||
return ((13.0/11.0 * x - 453.0/209.0) * x - 3.0/209.0) * x + 1.0;
|
||||
}
|
||||
if(x < 2.0)
|
||||
{
|
||||
return ((-6.0/11.0 * (x-1) + 270.0/209.0) * (x-1) - 156.0/ 209.0) * (x-1);
|
||||
}
|
||||
return ((1.0/11.0 * (x-2) - 45.0/209.0) * (x-2) + 26.0/209.0) * (x-2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------image_filter_gaussian
|
||||
struct image_filter_gaussian
|
||||
{
|
||||
static double radius() { return 2.0; }
|
||||
static double calc_weight(double x)
|
||||
{
|
||||
return exp(-2.0 * x * x) * sqrt(2.0 / pi);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------image_filter_bessel
|
||||
struct image_filter_bessel
|
||||
{
|
||||
static double radius() { return 3.2383; }
|
||||
static double calc_weight(double x)
|
||||
{
|
||||
return (x == 0.0) ? pi / 4.0 : besj(pi * x, 1) / (2.0 * x);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------image_filter_sinc
|
||||
class image_filter_sinc
|
||||
{
|
||||
public:
|
||||
image_filter_sinc(double r) : m_radius(r < 2.0 ? 2.0 : r) {}
|
||||
double radius() const { return m_radius; }
|
||||
double calc_weight(double x) const
|
||||
{
|
||||
if(x == 0.0) return 1.0;
|
||||
x *= pi;
|
||||
return sin(x) / x;
|
||||
}
|
||||
private:
|
||||
double m_radius;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------image_filter_lanczos
|
||||
class image_filter_lanczos
|
||||
{
|
||||
public:
|
||||
image_filter_lanczos(double r) : m_radius(r < 2.0 ? 2.0 : r) {}
|
||||
double radius() const { return m_radius; }
|
||||
double calc_weight(double x) const
|
||||
{
|
||||
if(x == 0.0) return 1.0;
|
||||
if(x > m_radius) return 0.0;
|
||||
x *= pi;
|
||||
double xr = x / m_radius;
|
||||
return (sin(x) / x) * (sin(xr) / xr);
|
||||
}
|
||||
private:
|
||||
double m_radius;
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------image_filter_blackman
|
||||
class image_filter_blackman
|
||||
{
|
||||
public:
|
||||
image_filter_blackman(double r) : m_radius(r < 2.0 ? 2.0 : r) {}
|
||||
double radius() const { return m_radius; }
|
||||
double calc_weight(double x) const
|
||||
{
|
||||
if(x == 0.0) return 1.0;
|
||||
if(x > m_radius) return 0.0;
|
||||
x *= pi;
|
||||
double xr = x / m_radius;
|
||||
return (sin(x) / x) * (0.42 + 0.5*cos(xr) + 0.08*cos(2*xr));
|
||||
}
|
||||
private:
|
||||
double m_radius;
|
||||
};
|
||||
|
||||
//------------------------------------------------image_filter_sinc36
|
||||
class image_filter_sinc36 : public image_filter_sinc
|
||||
{ public: image_filter_sinc36() : image_filter_sinc(3.0){} };
|
||||
|
||||
//------------------------------------------------image_filter_sinc64
|
||||
class image_filter_sinc64 : public image_filter_sinc
|
||||
{ public: image_filter_sinc64() : image_filter_sinc(4.0){} };
|
||||
|
||||
//-----------------------------------------------image_filter_sinc100
|
||||
class image_filter_sinc100 : public image_filter_sinc
|
||||
{ public: image_filter_sinc100() : image_filter_sinc(5.0){} };
|
||||
|
||||
//-----------------------------------------------image_filter_sinc144
|
||||
class image_filter_sinc144 : public image_filter_sinc
|
||||
{ public: image_filter_sinc144() : image_filter_sinc(6.0){} };
|
||||
|
||||
//-----------------------------------------------image_filter_sinc196
|
||||
class image_filter_sinc196 : public image_filter_sinc
|
||||
{ public: image_filter_sinc196() : image_filter_sinc(7.0){} };
|
||||
|
||||
//-----------------------------------------------image_filter_sinc256
|
||||
class image_filter_sinc256 : public image_filter_sinc
|
||||
{ public: image_filter_sinc256() : image_filter_sinc(8.0){} };
|
||||
|
||||
//---------------------------------------------image_filter_lanczos36
|
||||
class image_filter_lanczos36 : public image_filter_lanczos
|
||||
{ public: image_filter_lanczos36() : image_filter_lanczos(3.0){} };
|
||||
|
||||
//---------------------------------------------image_filter_lanczos64
|
||||
class image_filter_lanczos64 : public image_filter_lanczos
|
||||
{ public: image_filter_lanczos64() : image_filter_lanczos(4.0){} };
|
||||
|
||||
//--------------------------------------------image_filter_lanczos100
|
||||
class image_filter_lanczos100 : public image_filter_lanczos
|
||||
{ public: image_filter_lanczos100() : image_filter_lanczos(5.0){} };
|
||||
|
||||
//--------------------------------------------image_filter_lanczos144
|
||||
class image_filter_lanczos144 : public image_filter_lanczos
|
||||
{ public: image_filter_lanczos144() : image_filter_lanczos(6.0){} };
|
||||
|
||||
//--------------------------------------------image_filter_lanczos196
|
||||
class image_filter_lanczos196 : public image_filter_lanczos
|
||||
{ public: image_filter_lanczos196() : image_filter_lanczos(7.0){} };
|
||||
|
||||
//--------------------------------------------image_filter_lanczos256
|
||||
class image_filter_lanczos256 : public image_filter_lanczos
|
||||
{ public: image_filter_lanczos256() : image_filter_lanczos(8.0){} };
|
||||
|
||||
//--------------------------------------------image_filter_blackman36
|
||||
class image_filter_blackman36 : public image_filter_blackman
|
||||
{ public: image_filter_blackman36() : image_filter_blackman(3.0){} };
|
||||
|
||||
//--------------------------------------------image_filter_blackman64
|
||||
class image_filter_blackman64 : public image_filter_blackman
|
||||
{ public: image_filter_blackman64() : image_filter_blackman(4.0){} };
|
||||
|
||||
//-------------------------------------------image_filter_blackman100
|
||||
class image_filter_blackman100 : public image_filter_blackman
|
||||
{ public: image_filter_blackman100() : image_filter_blackman(5.0){} };
|
||||
|
||||
//-------------------------------------------image_filter_blackman144
|
||||
class image_filter_blackman144 : public image_filter_blackman
|
||||
{ public: image_filter_blackman144() : image_filter_blackman(6.0){} };
|
||||
|
||||
//-------------------------------------------image_filter_blackman196
|
||||
class image_filter_blackman196 : public image_filter_blackman
|
||||
{ public: image_filter_blackman196() : image_filter_blackman(7.0){} };
|
||||
|
||||
//-------------------------------------------image_filter_blackman256
|
||||
class image_filter_blackman256 : public image_filter_blackman
|
||||
{ public: image_filter_blackman256() : image_filter_blackman(8.0){} };
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,199 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_LINE_AA_BASICS_INCLUDED
|
||||
#define AGG_LINE_AA_BASICS_INCLUDED
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
// See Implementation agg_line_aa_basics.cpp
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
enum line_subpixel_scale_e
|
||||
{
|
||||
line_subpixel_shift = 8, //----line_subpixel_shift
|
||||
line_subpixel_scale = 1 << line_subpixel_shift, //----line_subpixel_scale
|
||||
line_subpixel_mask = line_subpixel_scale - 1, //----line_subpixel_mask
|
||||
line_max_coord = (1 << 28) - 1, //----line_max_coord
|
||||
line_max_length = 1 << (line_subpixel_shift + 10) //----line_max_length
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
enum line_mr_subpixel_scale_e
|
||||
{
|
||||
line_mr_subpixel_shift = 4, //----line_mr_subpixel_shift
|
||||
line_mr_subpixel_scale = 1 << line_mr_subpixel_shift, //----line_mr_subpixel_scale
|
||||
line_mr_subpixel_mask = line_mr_subpixel_scale - 1 //----line_mr_subpixel_mask
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------line_mr
|
||||
AGG_INLINE int line_mr(int x)
|
||||
{
|
||||
return x >> (line_subpixel_shift - line_mr_subpixel_shift);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------line_hr
|
||||
AGG_INLINE int line_hr(int x)
|
||||
{
|
||||
return x << (line_subpixel_shift - line_mr_subpixel_shift);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------line_dbl_hr
|
||||
AGG_INLINE int line_dbl_hr(int x)
|
||||
{
|
||||
return x << line_subpixel_shift;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------line_coord
|
||||
struct line_coord
|
||||
{
|
||||
AGG_INLINE static int conv(double x)
|
||||
{
|
||||
return iround(x * line_subpixel_scale);
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------line_coord_sat
|
||||
struct line_coord_sat
|
||||
{
|
||||
AGG_INLINE static int conv(double x)
|
||||
{
|
||||
return saturation<line_max_coord>::iround(x * line_subpixel_scale);
|
||||
}
|
||||
};
|
||||
|
||||
//==========================================================line_parameters
|
||||
struct line_parameters
|
||||
{
|
||||
//---------------------------------------------------------------------
|
||||
line_parameters() {}
|
||||
line_parameters(int x1_, int y1_, int x2_, int y2_, int len_) :
|
||||
x1(x1_), y1(y1_), x2(x2_), y2(y2_),
|
||||
dx(abs(x2_ - x1_)),
|
||||
dy(abs(y2_ - y1_)),
|
||||
sx((x2_ > x1_) ? 1 : -1),
|
||||
sy((y2_ > y1_) ? 1 : -1),
|
||||
vertical(dy >= dx),
|
||||
inc(vertical ? sy : sx),
|
||||
len(len_),
|
||||
octant((sy & 4) | (sx & 2) | int(vertical))
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
unsigned orthogonal_quadrant() const { return s_orthogonal_quadrant[octant]; }
|
||||
unsigned diagonal_quadrant() const { return s_diagonal_quadrant[octant]; }
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
bool same_orthogonal_quadrant(const line_parameters& lp) const
|
||||
{
|
||||
return s_orthogonal_quadrant[octant] == s_orthogonal_quadrant[lp.octant];
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
bool same_diagonal_quadrant(const line_parameters& lp) const
|
||||
{
|
||||
return s_diagonal_quadrant[octant] == s_diagonal_quadrant[lp.octant];
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
void divide(line_parameters& lp1, line_parameters& lp2) const
|
||||
{
|
||||
int xmid = (x1 + x2) >> 1;
|
||||
int ymid = (y1 + y2) >> 1;
|
||||
int len2 = len >> 1;
|
||||
|
||||
lp1 = *this;
|
||||
lp2 = *this;
|
||||
|
||||
lp1.x2 = xmid;
|
||||
lp1.y2 = ymid;
|
||||
lp1.len = len2;
|
||||
lp1.dx = abs(lp1.x2 - lp1.x1);
|
||||
lp1.dy = abs(lp1.y2 - lp1.y1);
|
||||
|
||||
lp2.x1 = xmid;
|
||||
lp2.y1 = ymid;
|
||||
lp2.len = len2;
|
||||
lp2.dx = abs(lp2.x2 - lp2.x1);
|
||||
lp2.dy = abs(lp2.y2 - lp2.y1);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
int x1, y1, x2, y2, dx, dy, sx, sy;
|
||||
bool vertical;
|
||||
int inc;
|
||||
int len;
|
||||
int octant;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
static const int8u s_orthogonal_quadrant[8];
|
||||
static const int8u s_diagonal_quadrant[8];
|
||||
};
|
||||
|
||||
|
||||
|
||||
// See Implementation agg_line_aa_basics.cpp
|
||||
|
||||
//----------------------------------------------------------------bisectrix
|
||||
void bisectrix(const line_parameters& l1,
|
||||
const line_parameters& l2,
|
||||
int* x, int* y);
|
||||
|
||||
|
||||
//-------------------------------------------fix_degenerate_bisectrix_start
|
||||
void inline fix_degenerate_bisectrix_start(const line_parameters& lp,
|
||||
int* x, int* y)
|
||||
{
|
||||
int d = iround((double(*x - lp.x2) * double(lp.y2 - lp.y1) -
|
||||
double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len);
|
||||
if(d < line_subpixel_scale/2)
|
||||
{
|
||||
*x = lp.x1 + (lp.y2 - lp.y1);
|
||||
*y = lp.y1 - (lp.x2 - lp.x1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------fix_degenerate_bisectrix_end
|
||||
void inline fix_degenerate_bisectrix_end(const line_parameters& lp,
|
||||
int* x, int* y)
|
||||
{
|
||||
int d = iround((double(*x - lp.x2) * double(lp.y2 - lp.y1) -
|
||||
double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len);
|
||||
if(d < line_subpixel_scale/2)
|
||||
{
|
||||
*x = lp.x2 + (lp.y2 - lp.y1);
|
||||
*y = lp.y2 - (lp.x2 - lp.x1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,446 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
// Bessel function (besj) was adapted for use in AGG library by Andy Wilk
|
||||
// Contact: castor.vulgaris@gmail.com
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_MATH_INCLUDED
|
||||
#define AGG_MATH_INCLUDED
|
||||
|
||||
#include <math.h>
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//------------------------------------------------------vertex_dist_epsilon
|
||||
// Coinciding points maximal distance (Epsilon)
|
||||
const double vertex_dist_epsilon = 1e-14;
|
||||
|
||||
//-----------------------------------------------------intersection_epsilon
|
||||
// See calc_intersection
|
||||
const double intersection_epsilon = 1.0e-30;
|
||||
|
||||
//------------------------------------------------------------cross_product
|
||||
AGG_INLINE double cross_product(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x, double y)
|
||||
{
|
||||
return (x - x2) * (y2 - y1) - (y - y2) * (x2 - x1);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------point_in_triangle
|
||||
AGG_INLINE bool point_in_triangle(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x, double y)
|
||||
{
|
||||
bool cp1 = cross_product(x1, y1, x2, y2, x, y) < 0.0;
|
||||
bool cp2 = cross_product(x2, y2, x3, y3, x, y) < 0.0;
|
||||
bool cp3 = cross_product(x3, y3, x1, y1, x, y) < 0.0;
|
||||
return cp1 == cp2 && cp2 == cp3 && cp3 == cp1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------calc_distance
|
||||
AGG_INLINE double calc_distance(double x1, double y1, double x2, double y2)
|
||||
{
|
||||
double dx = x2-x1;
|
||||
double dy = y2-y1;
|
||||
return sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------calc_sq_distance
|
||||
AGG_INLINE double calc_sq_distance(double x1, double y1, double x2, double y2)
|
||||
{
|
||||
double dx = x2-x1;
|
||||
double dy = y2-y1;
|
||||
return dx * dx + dy * dy;
|
||||
}
|
||||
|
||||
//------------------------------------------------calc_line_point_distance
|
||||
AGG_INLINE double calc_line_point_distance(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x, double y)
|
||||
{
|
||||
double dx = x2-x1;
|
||||
double dy = y2-y1;
|
||||
double d = sqrt(dx * dx + dy * dy);
|
||||
if(d < vertex_dist_epsilon)
|
||||
{
|
||||
return calc_distance(x1, y1, x, y);
|
||||
}
|
||||
return ((x - x2) * dy - (y - y2) * dx) / d;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------calc_line_point_u
|
||||
AGG_INLINE double calc_segment_point_u(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x, double y)
|
||||
{
|
||||
double dx = x2 - x1;
|
||||
double dy = y2 - y1;
|
||||
|
||||
if(dx == 0 && dy == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
double pdx = x - x1;
|
||||
double pdy = y - y1;
|
||||
|
||||
return (pdx * dx + pdy * dy) / (dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
//---------------------------------------------calc_line_point_sq_distance
|
||||
AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x, double y,
|
||||
double u)
|
||||
{
|
||||
if(u <= 0)
|
||||
{
|
||||
return calc_sq_distance(x, y, x1, y1);
|
||||
}
|
||||
else
|
||||
if(u >= 1)
|
||||
{
|
||||
return calc_sq_distance(x, y, x2, y2);
|
||||
}
|
||||
return calc_sq_distance(x, y, x1 + u * (x2 - x1), y1 + u * (y2 - y1));
|
||||
}
|
||||
|
||||
//---------------------------------------------calc_line_point_sq_distance
|
||||
AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x, double y)
|
||||
{
|
||||
return
|
||||
calc_segment_point_sq_distance(
|
||||
x1, y1, x2, y2, x, y,
|
||||
calc_segment_point_u(x1, y1, x2, y2, x, y));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------calc_intersection
|
||||
AGG_INLINE bool calc_intersection(double ax, double ay, double bx, double by,
|
||||
double cx, double cy, double dx, double dy,
|
||||
double* x, double* y)
|
||||
{
|
||||
double num = (ay-cy) * (dx-cx) - (ax-cx) * (dy-cy);
|
||||
double den = (bx-ax) * (dy-cy) - (by-ay) * (dx-cx);
|
||||
if(fabs(den) < intersection_epsilon) return false;
|
||||
double r = num / den;
|
||||
*x = ax + r * (bx-ax);
|
||||
*y = ay + r * (by-ay);
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------intersection_exists
|
||||
AGG_INLINE bool intersection_exists(double x1, double y1, double x2, double y2,
|
||||
double x3, double y3, double x4, double y4)
|
||||
{
|
||||
// It's less expensive but you can't control the
|
||||
// boundary conditions: Less or LessEqual
|
||||
double dx1 = x2 - x1;
|
||||
double dy1 = y2 - y1;
|
||||
double dx2 = x4 - x3;
|
||||
double dy2 = y4 - y3;
|
||||
return ((x3 - x2) * dy1 - (y3 - y2) * dx1 < 0.0) !=
|
||||
((x4 - x2) * dy1 - (y4 - y2) * dx1 < 0.0) &&
|
||||
((x1 - x4) * dy2 - (y1 - y4) * dx2 < 0.0) !=
|
||||
((x2 - x4) * dy2 - (y2 - y4) * dx2 < 0.0);
|
||||
|
||||
// It's is more expensive but more flexible
|
||||
// in terms of boundary conditions.
|
||||
//--------------------
|
||||
//double den = (x2-x1) * (y4-y3) - (y2-y1) * (x4-x3);
|
||||
//if(fabs(den) < intersection_epsilon) return false;
|
||||
//double nom1 = (x4-x3) * (y1-y3) - (y4-y3) * (x1-x3);
|
||||
//double nom2 = (x2-x1) * (y1-y3) - (y2-y1) * (x1-x3);
|
||||
//double ua = nom1 / den;
|
||||
//double ub = nom2 / den;
|
||||
//return ua >= 0.0 && ua <= 1.0 && ub >= 0.0 && ub <= 1.0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------calc_orthogonal
|
||||
AGG_INLINE void calc_orthogonal(double thickness,
|
||||
double x1, double y1,
|
||||
double x2, double y2,
|
||||
double* x, double* y)
|
||||
{
|
||||
double dx = x2 - x1;
|
||||
double dy = y2 - y1;
|
||||
double d = sqrt(dx*dx + dy*dy);
|
||||
*x = thickness * dy / d;
|
||||
*y = -thickness * dx / d;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------dilate_triangle
|
||||
AGG_INLINE void dilate_triangle(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double *x, double* y,
|
||||
double d)
|
||||
{
|
||||
double dx1=0.0;
|
||||
double dy1=0.0;
|
||||
double dx2=0.0;
|
||||
double dy2=0.0;
|
||||
double dx3=0.0;
|
||||
double dy3=0.0;
|
||||
double loc = cross_product(x1, y1, x2, y2, x3, y3);
|
||||
if(fabs(loc) > intersection_epsilon)
|
||||
{
|
||||
if(cross_product(x1, y1, x2, y2, x3, y3) > 0.0)
|
||||
{
|
||||
d = -d;
|
||||
}
|
||||
calc_orthogonal(d, x1, y1, x2, y2, &dx1, &dy1);
|
||||
calc_orthogonal(d, x2, y2, x3, y3, &dx2, &dy2);
|
||||
calc_orthogonal(d, x3, y3, x1, y1, &dx3, &dy3);
|
||||
}
|
||||
*x++ = x1 + dx1; *y++ = y1 + dy1;
|
||||
*x++ = x2 + dx1; *y++ = y2 + dy1;
|
||||
*x++ = x2 + dx2; *y++ = y2 + dy2;
|
||||
*x++ = x3 + dx2; *y++ = y3 + dy2;
|
||||
*x++ = x3 + dx3; *y++ = y3 + dy3;
|
||||
*x++ = x1 + dx3; *y++ = y1 + dy3;
|
||||
}
|
||||
|
||||
//------------------------------------------------------calc_triangle_area
|
||||
AGG_INLINE double calc_triangle_area(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3)
|
||||
{
|
||||
return (x1*y2 - x2*y1 + x2*y3 - x3*y2 + x3*y1 - x1*y3) * 0.5;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------calc_polygon_area
|
||||
template<class Storage> double calc_polygon_area(const Storage& st)
|
||||
{
|
||||
unsigned i;
|
||||
double sum = 0.0;
|
||||
double x = st[0].x;
|
||||
double y = st[0].y;
|
||||
double xs = x;
|
||||
double ys = y;
|
||||
|
||||
for(i = 1; i < st.size(); i++)
|
||||
{
|
||||
const typename Storage::value_type& v = st[i];
|
||||
sum += x * v.y - y * v.x;
|
||||
x = v.x;
|
||||
y = v.y;
|
||||
}
|
||||
return (sum + x * ys - y * xs) * 0.5;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Tables for fast sqrt
|
||||
extern int16u g_sqrt_table[1024];
|
||||
extern int8 g_elder_bit_table[256];
|
||||
|
||||
|
||||
//---------------------------------------------------------------fast_sqrt
|
||||
//Fast integer Sqrt - really fast: no cycles, divisions or multiplications
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4035) //Disable warning "no return value"
|
||||
#endif
|
||||
AGG_INLINE unsigned fast_sqrt(unsigned val)
|
||||
{
|
||||
#if defined(_M_IX86) && defined(_MSC_VER) && !defined(AGG_NO_ASM)
|
||||
//For Ix86 family processors this assembler code is used.
|
||||
//The key command here is bsr - determination the number of the most
|
||||
//significant bit of the value. For other processors
|
||||
//(and maybe compilers) the pure C "#else" section is used.
|
||||
__asm
|
||||
{
|
||||
mov ebx, val
|
||||
mov edx, 11
|
||||
bsr ecx, ebx
|
||||
sub ecx, 9
|
||||
jle less_than_9_bits
|
||||
shr ecx, 1
|
||||
adc ecx, 0
|
||||
sub edx, ecx
|
||||
shl ecx, 1
|
||||
shr ebx, cl
|
||||
less_than_9_bits:
|
||||
xor eax, eax
|
||||
mov ax, g_sqrt_table[ebx*2]
|
||||
mov ecx, edx
|
||||
shr eax, cl
|
||||
}
|
||||
#else
|
||||
|
||||
//This code is actually pure C and portable to most
|
||||
//arcitectures including 64bit ones.
|
||||
unsigned t = val;
|
||||
int bit=0;
|
||||
unsigned shift = 11;
|
||||
|
||||
//The following piece of code is just an emulation of the
|
||||
//Ix86 assembler command "bsr" (see above). However on old
|
||||
//Intels (like Intel MMX 233MHz) this code is about twice
|
||||
//faster (sic!) then just one "bsr". On PIII and PIV the
|
||||
//bsr is optimized quite well.
|
||||
bit = t >> 24;
|
||||
if(bit)
|
||||
{
|
||||
bit = g_elder_bit_table[bit] + 24;
|
||||
}
|
||||
else
|
||||
{
|
||||
bit = (t >> 16) & 0xFF;
|
||||
if(bit)
|
||||
{
|
||||
bit = g_elder_bit_table[bit] + 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
bit = (t >> 8) & 0xFF;
|
||||
if(bit)
|
||||
{
|
||||
bit = g_elder_bit_table[bit] + 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
bit = g_elder_bit_table[t];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//This code calculates the sqrt.
|
||||
bit -= 9;
|
||||
if(bit > 0)
|
||||
{
|
||||
bit = (bit >> 1) + (bit & 1);
|
||||
shift -= bit;
|
||||
val >>= (bit << 1);
|
||||
}
|
||||
return g_sqrt_table[val] >> shift;
|
||||
#endif
|
||||
}
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------besj
|
||||
// Function BESJ calculates Bessel function of first kind of order n
|
||||
// Arguments:
|
||||
// n - an integer (>=0), the order
|
||||
// x - value at which the Bessel function is required
|
||||
//--------------------
|
||||
// C++ Mathematical Library
|
||||
// Convereted from equivalent FORTRAN library
|
||||
// Converetd by Gareth Walker for use by course 392 computational project
|
||||
// All functions tested and yield the same results as the corresponding
|
||||
// FORTRAN versions.
|
||||
//
|
||||
// If you have any problems using these functions please report them to
|
||||
// M.Muldoon@UMIST.ac.uk
|
||||
//
|
||||
// Documentation available on the web
|
||||
// http://www.ma.umist.ac.uk/mrm/Teaching/392/libs/392.html
|
||||
// Version 1.0 8/98
|
||||
// 29 October, 1999
|
||||
//--------------------
|
||||
// Adapted for use in AGG library by Andy Wilk (castor.vulgaris@gmail.com)
|
||||
//------------------------------------------------------------------------
|
||||
inline double besj(double x, int n)
|
||||
{
|
||||
if(n < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
double d = 1E-6;
|
||||
double b = 0;
|
||||
if(fabs(x) <= d)
|
||||
{
|
||||
if(n != 0) return 0;
|
||||
return 1;
|
||||
}
|
||||
double b1 = 0; // b1 is the value from the previous iteration
|
||||
// Set up a starting order for recurrence
|
||||
int m1 = (int)fabs(x) + 6;
|
||||
if(fabs(x) > 5)
|
||||
{
|
||||
m1 = (int)(fabs(1.4 * x + 60 / x));
|
||||
}
|
||||
int m2 = (int)(n + 2 + fabs(x) / 4);
|
||||
if (m1 > m2)
|
||||
{
|
||||
m2 = m1;
|
||||
}
|
||||
|
||||
// Apply recurrence down from curent max order
|
||||
for(;;)
|
||||
{
|
||||
double c3 = 0;
|
||||
double c2 = 1E-30;
|
||||
double c4 = 0;
|
||||
int m8 = 1;
|
||||
if (m2 / 2 * 2 == m2)
|
||||
{
|
||||
m8 = -1;
|
||||
}
|
||||
int imax = m2 - 2;
|
||||
for (int i = 1; i <= imax; i++)
|
||||
{
|
||||
double c6 = 2 * (m2 - i) * c2 / x - c3;
|
||||
c3 = c2;
|
||||
c2 = c6;
|
||||
if(m2 - i - 1 == n)
|
||||
{
|
||||
b = c6;
|
||||
}
|
||||
m8 = -1 * m8;
|
||||
if (m8 > 0)
|
||||
{
|
||||
c4 = c4 + 2 * c6;
|
||||
}
|
||||
}
|
||||
double c6 = 2 * c2 / x - c3;
|
||||
if(n == 0)
|
||||
{
|
||||
b = c6;
|
||||
}
|
||||
c4 += c6;
|
||||
b /= c4;
|
||||
if(fabs(b - b1) < d)
|
||||
{
|
||||
return b;
|
||||
}
|
||||
b1 = b;
|
||||
m2 += 3;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,531 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_STROKE_MATH_INCLUDED
|
||||
#define AGG_STROKE_MATH_INCLUDED
|
||||
|
||||
#include "agg_math.h"
|
||||
#include "agg_vertex_sequence.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//-------------------------------------------------------------line_cap_e
|
||||
enum line_cap_e
|
||||
{
|
||||
butt_cap,
|
||||
square_cap,
|
||||
round_cap
|
||||
};
|
||||
|
||||
//------------------------------------------------------------line_join_e
|
||||
enum line_join_e
|
||||
{
|
||||
miter_join = 0,
|
||||
miter_join_revert = 1,
|
||||
round_join = 2,
|
||||
bevel_join = 3,
|
||||
miter_join_round = 4
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------inner_join_e
|
||||
enum inner_join_e
|
||||
{
|
||||
inner_bevel,
|
||||
inner_miter,
|
||||
inner_jag,
|
||||
inner_round
|
||||
};
|
||||
|
||||
//------------------------------------------------------------math_stroke
|
||||
template<class VertexConsumer> class math_stroke
|
||||
{
|
||||
public:
|
||||
typedef typename VertexConsumer::value_type coord_type;
|
||||
|
||||
math_stroke();
|
||||
|
||||
void line_cap(line_cap_e lc) { m_line_cap = lc; }
|
||||
void line_join(line_join_e lj) { m_line_join = lj; }
|
||||
void inner_join(inner_join_e ij) { m_inner_join = ij; }
|
||||
|
||||
line_cap_e line_cap() const { return m_line_cap; }
|
||||
line_join_e line_join() const { return m_line_join; }
|
||||
inner_join_e inner_join() const { return m_inner_join; }
|
||||
|
||||
void width(double w);
|
||||
void miter_limit(double ml) { m_miter_limit = ml; }
|
||||
void miter_limit_theta(double t);
|
||||
void inner_miter_limit(double ml) { m_inner_miter_limit = ml; }
|
||||
void approximation_scale(double as) { m_approx_scale = as; }
|
||||
|
||||
double width() const { return m_width * 2.0; }
|
||||
double miter_limit() const { return m_miter_limit; }
|
||||
double inner_miter_limit() const { return m_inner_miter_limit; }
|
||||
double approximation_scale() const { return m_approx_scale; }
|
||||
|
||||
void calc_cap(VertexConsumer& vc,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
double len);
|
||||
|
||||
void calc_join(VertexConsumer& vc,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
const vertex_dist& v2,
|
||||
double len1,
|
||||
double len2);
|
||||
|
||||
private:
|
||||
AGG_INLINE void add_vertex(VertexConsumer& vc, double x, double y)
|
||||
{
|
||||
vc.add(coord_type(x, y));
|
||||
}
|
||||
|
||||
void calc_arc(VertexConsumer& vc,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2);
|
||||
|
||||
void calc_miter(VertexConsumer& vc,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
const vertex_dist& v2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
line_join_e lj,
|
||||
double mlimit,
|
||||
double dbevel);
|
||||
|
||||
double m_width;
|
||||
double m_width_abs;
|
||||
double m_width_eps;
|
||||
int m_width_sign;
|
||||
double m_miter_limit;
|
||||
double m_inner_miter_limit;
|
||||
double m_approx_scale;
|
||||
line_cap_e m_line_cap;
|
||||
line_join_e m_line_join;
|
||||
inner_join_e m_inner_join;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
template<class VC> math_stroke<VC>::math_stroke() :
|
||||
m_width(0.5),
|
||||
m_width_abs(0.5),
|
||||
m_width_eps(0.5/1024.0),
|
||||
m_width_sign(1),
|
||||
m_miter_limit(4.0),
|
||||
m_inner_miter_limit(1.01),
|
||||
m_approx_scale(1.0),
|
||||
m_line_cap(butt_cap),
|
||||
m_line_join(miter_join),
|
||||
m_inner_join(inner_miter)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
template<class VC> void math_stroke<VC>::width(double w)
|
||||
{
|
||||
m_width = w * 0.5;
|
||||
if(m_width < 0)
|
||||
{
|
||||
m_width_abs = -m_width;
|
||||
m_width_sign = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_width_abs = m_width;
|
||||
m_width_sign = 1;
|
||||
}
|
||||
m_width_eps = m_width / 1024.0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
template<class VC> void math_stroke<VC>::miter_limit_theta(double t)
|
||||
{
|
||||
m_miter_limit = 1.0 / sin(t * 0.5) ;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
template<class VC>
|
||||
void math_stroke<VC>::calc_arc(VC& vc,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
double a1 = atan2(dy1 * m_width_sign, dx1 * m_width_sign);
|
||||
double a2 = atan2(dy2 * m_width_sign, dx2 * m_width_sign);
|
||||
double da = a1 - a2;
|
||||
int i, n;
|
||||
|
||||
da = acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2;
|
||||
|
||||
add_vertex(vc, x + dx1, y + dy1);
|
||||
if(m_width_sign > 0)
|
||||
{
|
||||
if(a1 > a2) a2 += 2 * pi;
|
||||
n = int((a2 - a1) / da);
|
||||
da = (a2 - a1) / (n + 1);
|
||||
a1 += da;
|
||||
for(i = 0; i < n; i++)
|
||||
{
|
||||
add_vertex(vc, x + cos(a1) * m_width, y + sin(a1) * m_width);
|
||||
a1 += da;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(a1 < a2) a2 -= 2 * pi;
|
||||
n = int((a1 - a2) / da);
|
||||
da = (a1 - a2) / (n + 1);
|
||||
a1 -= da;
|
||||
for(i = 0; i < n; i++)
|
||||
{
|
||||
add_vertex(vc, x + cos(a1) * m_width, y + sin(a1) * m_width);
|
||||
a1 -= da;
|
||||
}
|
||||
}
|
||||
add_vertex(vc, x + dx2, y + dy2);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
template<class VC>
|
||||
void math_stroke<VC>::calc_miter(VC& vc,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
const vertex_dist& v2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
line_join_e lj,
|
||||
double mlimit,
|
||||
double dbevel)
|
||||
{
|
||||
double xi = v1.x;
|
||||
double yi = v1.y;
|
||||
double di = 1;
|
||||
double lim = m_width_abs * mlimit;
|
||||
bool miter_limit_exceeded = true; // Assume the worst
|
||||
bool intersection_failed = true; // Assume the worst
|
||||
|
||||
if(calc_intersection(v0.x + dx1, v0.y - dy1,
|
||||
v1.x + dx1, v1.y - dy1,
|
||||
v1.x + dx2, v1.y - dy2,
|
||||
v2.x + dx2, v2.y - dy2,
|
||||
&xi, &yi))
|
||||
{
|
||||
// Calculation of the intersection succeeded
|
||||
//---------------------
|
||||
di = calc_distance(v1.x, v1.y, xi, yi);
|
||||
if(di <= lim)
|
||||
{
|
||||
// Inside the miter limit
|
||||
//---------------------
|
||||
add_vertex(vc, xi, yi);
|
||||
miter_limit_exceeded = false;
|
||||
}
|
||||
intersection_failed = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Calculation of the intersection failed, most probably
|
||||
// the three points lie one straight line.
|
||||
// First check if v0 and v2 lie on the opposite sides of vector:
|
||||
// (v1.x, v1.y) -> (v1.x+dx1, v1.y-dy1), that is, the perpendicular
|
||||
// to the line determined by vertices v0 and v1.
|
||||
// This condition determines whether the next line segments continues
|
||||
// the previous one or goes back.
|
||||
//----------------
|
||||
double x2 = v1.x + dx1;
|
||||
double y2 = v1.y - dy1;
|
||||
if((cross_product(v0.x, v0.y, v1.x, v1.y, x2, y2) < 0.0) ==
|
||||
(cross_product(v1.x, v1.y, v2.x, v2.y, x2, y2) < 0.0))
|
||||
{
|
||||
// This case means that the next segment continues
|
||||
// the previous one (straight line)
|
||||
//-----------------
|
||||
add_vertex(vc, v1.x + dx1, v1.y - dy1);
|
||||
miter_limit_exceeded = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(miter_limit_exceeded)
|
||||
{
|
||||
// Miter limit exceeded
|
||||
//------------------------
|
||||
switch(lj)
|
||||
{
|
||||
case miter_join_revert:
|
||||
// For the compatibility with SVG, PDF, etc,
|
||||
// we use a simple bevel join instead of
|
||||
// "smart" bevel
|
||||
//-------------------
|
||||
add_vertex(vc, v1.x + dx1, v1.y - dy1);
|
||||
add_vertex(vc, v1.x + dx2, v1.y - dy2);
|
||||
break;
|
||||
|
||||
case miter_join_round:
|
||||
calc_arc(vc, v1.x, v1.y, dx1, -dy1, dx2, -dy2);
|
||||
break;
|
||||
|
||||
default:
|
||||
// If no miter-revert, calculate new dx1, dy1, dx2, dy2
|
||||
//----------------
|
||||
if(intersection_failed)
|
||||
{
|
||||
mlimit *= m_width_sign;
|
||||
add_vertex(vc, v1.x + dx1 + dy1 * mlimit,
|
||||
v1.y - dy1 + dx1 * mlimit);
|
||||
add_vertex(vc, v1.x + dx2 - dy2 * mlimit,
|
||||
v1.y - dy2 - dx2 * mlimit);
|
||||
}
|
||||
else
|
||||
{
|
||||
double x1 = v1.x + dx1;
|
||||
double y1 = v1.y - dy1;
|
||||
double x2 = v1.x + dx2;
|
||||
double y2 = v1.y - dy2;
|
||||
di = (lim - dbevel) / (di - dbevel);
|
||||
add_vertex(vc, x1 + (xi - x1) * di,
|
||||
y1 + (yi - y1) * di);
|
||||
add_vertex(vc, x2 + (xi - x2) * di,
|
||||
y2 + (yi - y2) * di);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------stroke_calc_cap
|
||||
template<class VC>
|
||||
void math_stroke<VC>::calc_cap(VC& vc,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
double len)
|
||||
{
|
||||
vc.remove_all();
|
||||
|
||||
double dx1 = (v1.y - v0.y) / len;
|
||||
double dy1 = (v1.x - v0.x) / len;
|
||||
double dx2 = 0;
|
||||
double dy2 = 0;
|
||||
|
||||
dx1 *= m_width;
|
||||
dy1 *= m_width;
|
||||
|
||||
if(m_line_cap != round_cap)
|
||||
{
|
||||
if(m_line_cap == square_cap)
|
||||
{
|
||||
dx2 = dy1 * m_width_sign;
|
||||
dy2 = dx1 * m_width_sign;
|
||||
}
|
||||
add_vertex(vc, v0.x - dx1 - dx2, v0.y + dy1 - dy2);
|
||||
add_vertex(vc, v0.x + dx1 - dx2, v0.y - dy1 - dy2);
|
||||
}
|
||||
else
|
||||
{
|
||||
double da = acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2;
|
||||
double a1;
|
||||
int i;
|
||||
int n = int(pi / da);
|
||||
|
||||
da = pi / (n + 1);
|
||||
add_vertex(vc, v0.x - dx1, v0.y + dy1);
|
||||
if(m_width_sign > 0)
|
||||
{
|
||||
a1 = atan2(dy1, -dx1);
|
||||
a1 += da;
|
||||
for(i = 0; i < n; i++)
|
||||
{
|
||||
add_vertex(vc, v0.x + cos(a1) * m_width,
|
||||
v0.y + sin(a1) * m_width);
|
||||
a1 += da;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
a1 = atan2(-dy1, dx1);
|
||||
a1 -= da;
|
||||
for(i = 0; i < n; i++)
|
||||
{
|
||||
add_vertex(vc, v0.x + cos(a1) * m_width,
|
||||
v0.y + sin(a1) * m_width);
|
||||
a1 -= da;
|
||||
}
|
||||
}
|
||||
add_vertex(vc, v0.x + dx1, v0.y - dy1);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
template<class VC>
|
||||
void math_stroke<VC>::calc_join(VC& vc,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
const vertex_dist& v2,
|
||||
double len1,
|
||||
double len2)
|
||||
{
|
||||
double dx1 = m_width * (v1.y - v0.y) / len1;
|
||||
double dy1 = m_width * (v1.x - v0.x) / len1;
|
||||
double dx2 = m_width * (v2.y - v1.y) / len2;
|
||||
double dy2 = m_width * (v2.x - v1.x) / len2;
|
||||
|
||||
vc.remove_all();
|
||||
|
||||
double cp = cross_product(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y);
|
||||
if(cp != 0 && (cp > 0) == (m_width > 0))
|
||||
{
|
||||
// Inner join
|
||||
//---------------
|
||||
double limit = ((len1 < len2) ? len1 : len2) / m_width_abs;
|
||||
if(limit < m_inner_miter_limit)
|
||||
{
|
||||
limit = m_inner_miter_limit;
|
||||
}
|
||||
|
||||
switch(m_inner_join)
|
||||
{
|
||||
default: // inner_bevel
|
||||
add_vertex(vc, v1.x + dx1, v1.y - dy1);
|
||||
add_vertex(vc, v1.x + dx2, v1.y - dy2);
|
||||
break;
|
||||
|
||||
case inner_miter:
|
||||
calc_miter(vc,
|
||||
v0, v1, v2, dx1, dy1, dx2, dy2,
|
||||
miter_join_revert,
|
||||
limit, 0);
|
||||
break;
|
||||
|
||||
case inner_jag:
|
||||
case inner_round:
|
||||
cp = (dx1-dx2) * (dx1-dx2) + (dy1-dy2) * (dy1-dy2);
|
||||
if(cp < len1 * len1 && cp < len2 * len2)
|
||||
{
|
||||
calc_miter(vc,
|
||||
v0, v1, v2, dx1, dy1, dx2, dy2,
|
||||
miter_join_revert,
|
||||
limit, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_inner_join == inner_jag)
|
||||
{
|
||||
add_vertex(vc, v1.x + dx1, v1.y - dy1);
|
||||
add_vertex(vc, v1.x, v1.y );
|
||||
add_vertex(vc, v1.x + dx2, v1.y - dy2);
|
||||
}
|
||||
else
|
||||
{
|
||||
add_vertex(vc, v1.x + dx1, v1.y - dy1);
|
||||
add_vertex(vc, v1.x, v1.y );
|
||||
calc_arc(vc, v1.x, v1.y, dx2, -dy2, dx1, -dy1);
|
||||
add_vertex(vc, v1.x, v1.y );
|
||||
add_vertex(vc, v1.x + dx2, v1.y - dy2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Outer join
|
||||
//---------------
|
||||
|
||||
// Calculate the distance between v1 and
|
||||
// the central point of the bevel line segment
|
||||
//---------------
|
||||
double dx = (dx1 + dx2) / 2;
|
||||
double dy = (dy1 + dy2) / 2;
|
||||
double dbevel = sqrt(dx * dx + dy * dy);
|
||||
|
||||
if(m_line_join == round_join || m_line_join == bevel_join)
|
||||
{
|
||||
// This is an optimization that reduces the number of points
|
||||
// in cases of almost collinear segments. If there's no
|
||||
// visible difference between bevel and miter joins we'd rather
|
||||
// use miter join because it adds only one point instead of two.
|
||||
//
|
||||
// Here we calculate the middle point between the bevel points
|
||||
// and then, the distance between v1 and this middle point.
|
||||
// At outer joins this distance always less than stroke width,
|
||||
// because it's actually the height of an isosceles triangle of
|
||||
// v1 and its two bevel points. If the difference between this
|
||||
// width and this value is small (no visible bevel) we can
|
||||
// add just one point.
|
||||
//
|
||||
// The constant in the expression makes the result approximately
|
||||
// the same as in round joins and caps. You can safely comment
|
||||
// out this entire "if".
|
||||
//-------------------
|
||||
if(m_approx_scale * (m_width_abs - dbevel) < m_width_eps)
|
||||
{
|
||||
if(calc_intersection(v0.x + dx1, v0.y - dy1,
|
||||
v1.x + dx1, v1.y - dy1,
|
||||
v1.x + dx2, v1.y - dy2,
|
||||
v2.x + dx2, v2.y - dy2,
|
||||
&dx, &dy))
|
||||
{
|
||||
add_vertex(vc, dx, dy);
|
||||
}
|
||||
else
|
||||
{
|
||||
add_vertex(vc, v1.x + dx1, v1.y - dy1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch(m_line_join)
|
||||
{
|
||||
case miter_join:
|
||||
case miter_join_revert:
|
||||
case miter_join_round:
|
||||
calc_miter(vc,
|
||||
v0, v1, v2, dx1, dy1, dx2, dy2,
|
||||
m_line_join,
|
||||
m_miter_limit,
|
||||
dbevel);
|
||||
break;
|
||||
|
||||
case round_join:
|
||||
calc_arc(vc, v1.x, v1.y, dx1, -dy1, dx2, -dy2);
|
||||
break;
|
||||
|
||||
default: // Bevel join
|
||||
add_vertex(vc, v1.x + dx1, v1.y - dy1);
|
||||
add_vertex(vc, v1.x + dx2, v1.y - dy2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,75 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_PATH_LENGTH_INCLUDED
|
||||
#define AGG_PATH_LENGTH_INCLUDED
|
||||
|
||||
#include "agg_math.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
template<class VertexSource>
|
||||
double path_length(VertexSource& vs, unsigned path_id = 0)
|
||||
{
|
||||
double len = 0.0;
|
||||
double start_x = 0.0;
|
||||
double start_y = 0.0;
|
||||
double x1 = 0.0;
|
||||
double y1 = 0.0;
|
||||
double x2 = 0.0;
|
||||
double y2 = 0.0;
|
||||
bool first = true;
|
||||
|
||||
unsigned cmd;
|
||||
vs.rewind(path_id);
|
||||
while(!is_stop(cmd = vs.vertex(&x2, &y2)))
|
||||
{
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
if(first || is_move_to(cmd))
|
||||
{
|
||||
start_x = x2;
|
||||
start_y = y2;
|
||||
}
|
||||
else
|
||||
{
|
||||
len += calc_distance(x1, y1, x2, y2);
|
||||
}
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_close(cmd) && !first)
|
||||
{
|
||||
len += calc_distance(x1, y1, start_x, start_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,304 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_PATH_STORAGE_INTEGER_INCLUDED
|
||||
#define AGG_PATH_STORAGE_INTEGER_INCLUDED
|
||||
|
||||
#include <string.h>
|
||||
#include "agg_array.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//---------------------------------------------------------vertex_integer
|
||||
template<class T, unsigned CoordShift=6> struct vertex_integer
|
||||
{
|
||||
enum path_cmd
|
||||
{
|
||||
cmd_move_to = 0,
|
||||
cmd_line_to = 1,
|
||||
cmd_curve3 = 2,
|
||||
cmd_curve4 = 3
|
||||
};
|
||||
|
||||
enum coord_scale_e
|
||||
{
|
||||
coord_shift = CoordShift,
|
||||
coord_scale = 1 << coord_shift
|
||||
};
|
||||
|
||||
T x,y;
|
||||
vertex_integer() {}
|
||||
vertex_integer(T x_, T y_, unsigned flag) :
|
||||
x(((x_ << 1) & ~1) | (flag & 1)),
|
||||
y(((y_ << 1) & ~1) | (flag >> 1)) {}
|
||||
|
||||
unsigned vertex(double* x_, double* y_,
|
||||
double dx=0, double dy=0,
|
||||
double scale=1.0) const
|
||||
{
|
||||
*x_ = dx + (double(x >> 1) / coord_scale) * scale;
|
||||
*y_ = dy + (double(y >> 1) / coord_scale) * scale;
|
||||
switch(((y & 1) << 1) | (x & 1))
|
||||
{
|
||||
case cmd_move_to: return path_cmd_move_to;
|
||||
case cmd_line_to: return path_cmd_line_to;
|
||||
case cmd_curve3: return path_cmd_curve3;
|
||||
case cmd_curve4: return path_cmd_curve4;
|
||||
}
|
||||
return path_cmd_stop;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------path_storage_integer
|
||||
template<class T, unsigned CoordShift=6> class path_storage_integer
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef vertex_integer<T, CoordShift> vertex_integer_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
path_storage_integer() : m_storage(), m_vertex_idx(0), m_closed(true) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void remove_all() { m_storage.remove_all(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void move_to(T x, T y)
|
||||
{
|
||||
m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_move_to));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void line_to(T x, T y)
|
||||
{
|
||||
m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_line_to));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void curve3(T x_ctrl, T y_ctrl,
|
||||
T x_to, T y_to)
|
||||
{
|
||||
m_storage.add(vertex_integer_type(x_ctrl, y_ctrl, vertex_integer_type::cmd_curve3));
|
||||
m_storage.add(vertex_integer_type(x_to, y_to, vertex_integer_type::cmd_curve3));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void curve4(T x_ctrl1, T y_ctrl1,
|
||||
T x_ctrl2, T y_ctrl2,
|
||||
T x_to, T y_to)
|
||||
{
|
||||
m_storage.add(vertex_integer_type(x_ctrl1, y_ctrl1, vertex_integer_type::cmd_curve4));
|
||||
m_storage.add(vertex_integer_type(x_ctrl2, y_ctrl2, vertex_integer_type::cmd_curve4));
|
||||
m_storage.add(vertex_integer_type(x_to, y_to, vertex_integer_type::cmd_curve4));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void close_polygon() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned size() const { return m_storage.size(); }
|
||||
unsigned vertex(unsigned idx, double* x, double* y) const
|
||||
{
|
||||
return m_storage[idx].vertex(x, y);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned byte_size() const { return m_storage.size() * sizeof(vertex_integer_type); }
|
||||
void serialize(int8u* ptr) const
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < m_storage.size(); i++)
|
||||
{
|
||||
memcpy(ptr, &m_storage[i], sizeof(vertex_integer_type));
|
||||
ptr += sizeof(vertex_integer_type);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void rewind(unsigned)
|
||||
{
|
||||
m_vertex_idx = 0;
|
||||
m_closed = true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
if(m_storage.size() < 2 || m_vertex_idx > m_storage.size())
|
||||
{
|
||||
*x = 0;
|
||||
*y = 0;
|
||||
return path_cmd_stop;
|
||||
}
|
||||
if(m_vertex_idx == m_storage.size())
|
||||
{
|
||||
*x = 0;
|
||||
*y = 0;
|
||||
++m_vertex_idx;
|
||||
return path_cmd_end_poly | path_flags_close;
|
||||
}
|
||||
unsigned cmd = m_storage[m_vertex_idx].vertex(x, y);
|
||||
if(is_move_to(cmd) && !m_closed)
|
||||
{
|
||||
*x = 0;
|
||||
*y = 0;
|
||||
m_closed = true;
|
||||
return path_cmd_end_poly | path_flags_close;
|
||||
}
|
||||
m_closed = false;
|
||||
++m_vertex_idx;
|
||||
return cmd;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rect_d bounding_rect() const
|
||||
{
|
||||
rect_d bounds(1e100, 1e100, -1e100, -1e100);
|
||||
if(m_storage.size() == 0)
|
||||
{
|
||||
bounds.x1 = bounds.y1 = bounds.x2 = bounds.y2 = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < m_storage.size(); i++)
|
||||
{
|
||||
double x, y;
|
||||
m_storage[i].vertex(&x, &y);
|
||||
if(x < bounds.x1) bounds.x1 = x;
|
||||
if(y < bounds.y1) bounds.y1 = y;
|
||||
if(x > bounds.x2) bounds.x2 = x;
|
||||
if(y > bounds.y2) bounds.y2 = y;
|
||||
}
|
||||
}
|
||||
return bounds;
|
||||
}
|
||||
|
||||
private:
|
||||
pod_bvector<vertex_integer_type, 6> m_storage;
|
||||
unsigned m_vertex_idx;
|
||||
bool m_closed;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------serialized_integer_path_adaptor
|
||||
template<class T, unsigned CoordShift=6> class serialized_integer_path_adaptor
|
||||
{
|
||||
public:
|
||||
typedef vertex_integer<T, CoordShift> vertex_integer_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
serialized_integer_path_adaptor() :
|
||||
m_data(0),
|
||||
m_end(0),
|
||||
m_ptr(0),
|
||||
m_dx(0.0),
|
||||
m_dy(0.0),
|
||||
m_scale(1.0),
|
||||
m_vertices(0)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
serialized_integer_path_adaptor(const int8u* data, unsigned size,
|
||||
double dx, double dy) :
|
||||
m_data(data),
|
||||
m_end(data + size),
|
||||
m_ptr(data),
|
||||
m_dx(dx),
|
||||
m_dy(dy),
|
||||
m_vertices(0)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void init(const int8u* data, unsigned size,
|
||||
double dx, double dy, double scale=1.0)
|
||||
{
|
||||
m_data = data;
|
||||
m_end = data + size;
|
||||
m_ptr = data;
|
||||
m_dx = dx;
|
||||
m_dy = dy;
|
||||
m_scale = scale;
|
||||
m_vertices = 0;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void rewind(unsigned)
|
||||
{
|
||||
m_ptr = m_data;
|
||||
m_vertices = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
if(m_data == 0 || m_ptr > m_end)
|
||||
{
|
||||
*x = 0;
|
||||
*y = 0;
|
||||
return path_cmd_stop;
|
||||
}
|
||||
|
||||
if(m_ptr == m_end)
|
||||
{
|
||||
*x = 0;
|
||||
*y = 0;
|
||||
m_ptr += sizeof(vertex_integer_type);
|
||||
return path_cmd_end_poly | path_flags_close;
|
||||
}
|
||||
|
||||
vertex_integer_type v;
|
||||
memcpy(&v, m_ptr, sizeof(vertex_integer_type));
|
||||
unsigned cmd = v.vertex(x, y, m_dx, m_dy, m_scale);
|
||||
if(is_move_to(cmd) && m_vertices > 2)
|
||||
{
|
||||
*x = 0;
|
||||
*y = 0;
|
||||
m_vertices = 0;
|
||||
return path_cmd_end_poly | path_flags_close;
|
||||
}
|
||||
++m_vertices;
|
||||
m_ptr += sizeof(vertex_integer_type);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
private:
|
||||
const int8u* m_data;
|
||||
const int8u* m_end;
|
||||
const int8u* m_ptr;
|
||||
double m_dx;
|
||||
double m_dy;
|
||||
double m_scale;
|
||||
unsigned m_vertices;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_PATTERN_FILTERS_RGBA8_INCLUDED
|
||||
#define AGG_PATTERN_FILTERS_RGBA8_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_line_aa_basics.h"
|
||||
#include "agg_color_rgba.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=======================================================pattern_filter_nn
|
||||
template<class ColorT> struct pattern_filter_nn
|
||||
{
|
||||
typedef ColorT color_type;
|
||||
static unsigned dilation() { return 0; }
|
||||
|
||||
static void AGG_INLINE pixel_low_res(color_type const* const* buf,
|
||||
color_type* p, int x, int y)
|
||||
{
|
||||
*p = buf[y][x];
|
||||
}
|
||||
|
||||
static void AGG_INLINE pixel_high_res(color_type const* const* buf,
|
||||
color_type* p, int x, int y)
|
||||
{
|
||||
*p = buf[y >> line_subpixel_shift]
|
||||
[x >> line_subpixel_shift];
|
||||
}
|
||||
};
|
||||
|
||||
typedef pattern_filter_nn<rgba8> pattern_filter_nn_rgba8;
|
||||
typedef pattern_filter_nn<rgba16> pattern_filter_nn_rgba16;
|
||||
|
||||
|
||||
//===========================================pattern_filter_bilinear_rgba
|
||||
template<class ColorT> struct pattern_filter_bilinear_rgba
|
||||
{
|
||||
typedef ColorT color_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
|
||||
|
||||
static unsigned dilation() { return 1; }
|
||||
|
||||
static AGG_INLINE void pixel_low_res(color_type const* const* buf,
|
||||
color_type* p, int x, int y)
|
||||
{
|
||||
*p = buf[y][x];
|
||||
}
|
||||
|
||||
static AGG_INLINE void pixel_high_res(color_type const* const* buf,
|
||||
color_type* p, int x, int y)
|
||||
{
|
||||
calc_type r, g, b, a;
|
||||
r = g = b = a = line_subpixel_scale * line_subpixel_scale / 2;
|
||||
|
||||
calc_type weight;
|
||||
int x_lr = x >> line_subpixel_shift;
|
||||
int y_lr = y >> line_subpixel_shift;
|
||||
|
||||
x &= line_subpixel_mask;
|
||||
y &= line_subpixel_mask;
|
||||
const color_type* ptr = buf[y_lr] + x_lr;
|
||||
|
||||
weight = (line_subpixel_scale - x) *
|
||||
(line_subpixel_scale - y);
|
||||
r += weight * ptr->r;
|
||||
g += weight * ptr->g;
|
||||
b += weight * ptr->b;
|
||||
a += weight * ptr->a;
|
||||
|
||||
++ptr;
|
||||
|
||||
weight = x * (line_subpixel_scale - y);
|
||||
r += weight * ptr->r;
|
||||
g += weight * ptr->g;
|
||||
b += weight * ptr->b;
|
||||
a += weight * ptr->a;
|
||||
|
||||
ptr = buf[y_lr + 1] + x_lr;
|
||||
|
||||
weight = (line_subpixel_scale - x) * y;
|
||||
r += weight * ptr->r;
|
||||
g += weight * ptr->g;
|
||||
b += weight * ptr->b;
|
||||
a += weight * ptr->a;
|
||||
|
||||
++ptr;
|
||||
|
||||
weight = x * y;
|
||||
r += weight * ptr->r;
|
||||
g += weight * ptr->g;
|
||||
b += weight * ptr->b;
|
||||
a += weight * ptr->a;
|
||||
|
||||
p->r = (value_type)(r >> line_subpixel_shift * 2);
|
||||
p->g = (value_type)(g >> line_subpixel_shift * 2);
|
||||
p->b = (value_type)(b >> line_subpixel_shift * 2);
|
||||
p->a = (value_type)(a >> line_subpixel_shift * 2);
|
||||
}
|
||||
};
|
||||
|
||||
typedef pattern_filter_bilinear_rgba<rgba8> pattern_filter_bilinear_rgba8;
|
||||
typedef pattern_filter_bilinear_rgba<rgba16> pattern_filter_bilinear_rgba16;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,249 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED
|
||||
#define AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include "agg_array.h"
|
||||
#include "agg_rendering_buffer.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//==================================================pixfmt_amask_adaptor
|
||||
template<class PixFmt, class AlphaMask> class pixfmt_amask_adaptor
|
||||
{
|
||||
public:
|
||||
typedef PixFmt pixfmt_type;
|
||||
typedef typename pixfmt_type::color_type color_type;
|
||||
typedef typename pixfmt_type::row_data row_data;
|
||||
typedef AlphaMask amask_type;
|
||||
typedef typename amask_type::cover_type cover_type;
|
||||
|
||||
private:
|
||||
enum span_extra_tail_e { span_extra_tail = 256 };
|
||||
|
||||
void realloc_span(unsigned len)
|
||||
{
|
||||
if(len > m_span.size())
|
||||
{
|
||||
m_span.resize(len + span_extra_tail);
|
||||
}
|
||||
}
|
||||
|
||||
void init_span(unsigned len)
|
||||
{
|
||||
realloc_span(len);
|
||||
memset(&m_span[0], amask_type::cover_full, len * sizeof(cover_type));
|
||||
}
|
||||
|
||||
void init_span(unsigned len, const cover_type* covers)
|
||||
{
|
||||
realloc_span(len);
|
||||
memcpy(&m_span[0], covers, len * sizeof(cover_type));
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
pixfmt_amask_adaptor(pixfmt_type& pixf, const amask_type& mask) :
|
||||
m_pixf(&pixf), m_mask(&mask), m_span()
|
||||
{}
|
||||
|
||||
void attach_pixfmt(pixfmt_type& pixf) { m_pixf = &pixf; }
|
||||
void attach_alpha_mask(const amask_type& mask) { m_mask = &mask; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class PixFmt2>
|
||||
bool attach_pixfmt(PixFmt2& pixf, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
return m_pixf->attach(pixf, x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned width() const { return m_pixf->width(); }
|
||||
unsigned height() const { return m_pixf->height(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
color_type pixel(int x, int y)
|
||||
{
|
||||
return m_pixf->pixel(x, y);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
m_pixf->blend_pixel(x, y, c, m_mask->pixel(x, y));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_pixel(int x, int y, const color_type& c, cover_type cover)
|
||||
{
|
||||
m_pixf->blend_pixel(x, y, c, m_mask->combine_pixel(x, y, cover));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_hline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c)
|
||||
{
|
||||
realloc_span(len);
|
||||
m_mask->fill_hspan(x, y, &m_span[0], len);
|
||||
m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_hline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
cover_type cover)
|
||||
{
|
||||
init_span(len);
|
||||
m_mask->combine_hspan(x, y, &m_span[0], len);
|
||||
m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_vline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c)
|
||||
{
|
||||
realloc_span(len);
|
||||
m_mask->fill_vspan(x, y, &m_span[0], len);
|
||||
m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_vline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
cover_type cover)
|
||||
{
|
||||
init_span(len);
|
||||
m_mask->combine_vspan(x, y, &m_span[0], len);
|
||||
m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_from(const rendering_buffer& from,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len)
|
||||
{
|
||||
m_pixf->copy_from(from, xdst, ydst, xsrc, ysrc, len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_hspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
const cover_type* covers)
|
||||
{
|
||||
init_span(len, covers);
|
||||
m_mask->combine_hspan(x, y, &m_span[0], len);
|
||||
m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
const cover_type* covers)
|
||||
{
|
||||
init_span(len, covers);
|
||||
m_mask->combine_vspan(x, y, &m_span[0], len);
|
||||
m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_color_hspan(int x, int y, unsigned len, const color_type* colors)
|
||||
{
|
||||
realloc_span(len);
|
||||
m_mask->fill_hspan(x, y, &m_span[0], len);
|
||||
m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover_full);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_color_vspan(int x, int y, unsigned len, const color_type* colors)
|
||||
{
|
||||
realloc_span(len);
|
||||
m_mask->fill_vspan(x, y, &m_span[0], len);
|
||||
m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover_full);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_hspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors,
|
||||
const cover_type* covers,
|
||||
cover_type cover = cover_full)
|
||||
{
|
||||
if(covers)
|
||||
{
|
||||
init_span(len, covers);
|
||||
m_mask->combine_hspan(x, y, &m_span[0], len);
|
||||
}
|
||||
else
|
||||
{
|
||||
realloc_span(len);
|
||||
m_mask->fill_hspan(x, y, &m_span[0], len);
|
||||
}
|
||||
m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors,
|
||||
const cover_type* covers,
|
||||
cover_type cover = cover_full)
|
||||
{
|
||||
if(covers)
|
||||
{
|
||||
init_span(len, covers);
|
||||
m_mask->combine_vspan(x, y, &m_span[0], len);
|
||||
}
|
||||
else
|
||||
{
|
||||
realloc_span(len);
|
||||
m_mask->fill_vspan(x, y, &m_span[0], len);
|
||||
}
|
||||
m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover);
|
||||
}
|
||||
|
||||
private:
|
||||
pixfmt_type* m_pixf;
|
||||
const amask_type* m_mask;
|
||||
pod_array<cover_type> m_span;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,679 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for high precision colors has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_PIXFMT_GRAY_INCLUDED
|
||||
#define AGG_PIXFMT_GRAY_INCLUDED
|
||||
|
||||
#include <string.h>
|
||||
#include "agg_basics.h"
|
||||
#include "agg_color_gray.h"
|
||||
#include "agg_rendering_buffer.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//============================================================blender_gray
|
||||
template<class ColorT> struct blender_gray
|
||||
{
|
||||
typedef ColorT color_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e { base_shift = color_type::base_shift };
|
||||
|
||||
static AGG_INLINE void blend_pix(value_type* p, unsigned cv,
|
||||
unsigned alpha, unsigned cover=0)
|
||||
{
|
||||
*p = (value_type)((((cv - calc_type(*p)) * alpha) + (calc_type(*p) << base_shift)) >> base_shift);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//======================================================blender_gray_pre
|
||||
template<class ColorT> struct blender_gray_pre
|
||||
{
|
||||
typedef ColorT color_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e { base_shift = color_type::base_shift };
|
||||
|
||||
static AGG_INLINE void blend_pix(value_type* p, unsigned cv,
|
||||
unsigned alpha, unsigned cover)
|
||||
{
|
||||
alpha = color_type::base_mask - alpha;
|
||||
cover = (cover + 1) << (base_shift - 8);
|
||||
*p = (value_type)((*p * alpha + cv * cover) >> base_shift);
|
||||
}
|
||||
|
||||
static AGG_INLINE void blend_pix(value_type* p, unsigned cv,
|
||||
unsigned alpha)
|
||||
{
|
||||
*p = (value_type)(((*p * (color_type::base_mask - alpha)) >> base_shift) + cv);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=====================================================apply_gamma_dir_gray
|
||||
template<class ColorT, class GammaLut> class apply_gamma_dir_gray
|
||||
{
|
||||
public:
|
||||
typedef typename ColorT::value_type value_type;
|
||||
|
||||
apply_gamma_dir_gray(const GammaLut& gamma) : m_gamma(gamma) {}
|
||||
|
||||
AGG_INLINE void operator () (value_type* p)
|
||||
{
|
||||
*p = m_gamma.dir(*p);
|
||||
}
|
||||
|
||||
private:
|
||||
const GammaLut& m_gamma;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=====================================================apply_gamma_inv_gray
|
||||
template<class ColorT, class GammaLut> class apply_gamma_inv_gray
|
||||
{
|
||||
public:
|
||||
typedef typename ColorT::value_type value_type;
|
||||
|
||||
apply_gamma_inv_gray(const GammaLut& gamma) : m_gamma(gamma) {}
|
||||
|
||||
AGG_INLINE void operator () (value_type* p)
|
||||
{
|
||||
*p = m_gamma.inv(*p);
|
||||
}
|
||||
|
||||
private:
|
||||
const GammaLut& m_gamma;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=================================================pixfmt_alpha_blend_gray
|
||||
template<class Blender, class RenBuf, unsigned Step=1, unsigned Offset=0>
|
||||
class pixfmt_alpha_blend_gray
|
||||
{
|
||||
public:
|
||||
typedef RenBuf rbuf_type;
|
||||
typedef typename rbuf_type::row_data row_data;
|
||||
typedef Blender blender_type;
|
||||
typedef typename blender_type::color_type color_type;
|
||||
typedef int order_type; // A fake one
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_scale = color_type::base_scale,
|
||||
base_mask = color_type::base_mask,
|
||||
pix_width = sizeof(value_type),
|
||||
pix_step = Step,
|
||||
pix_offset = Offset
|
||||
};
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
static AGG_INLINE void copy_or_blend_pix(value_type* p,
|
||||
const color_type& c,
|
||||
unsigned cover)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
*p = c.v;
|
||||
}
|
||||
else
|
||||
{
|
||||
Blender::blend_pix(p, c.v, alpha, cover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static AGG_INLINE void copy_or_blend_pix(value_type* p,
|
||||
const color_type& c)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
if(c.a == base_mask)
|
||||
{
|
||||
*p = c.v;
|
||||
}
|
||||
else
|
||||
{
|
||||
Blender::blend_pix(p, c.v, c.a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
explicit pixfmt_alpha_blend_gray(rbuf_type& rb) :
|
||||
m_rbuf(&rb)
|
||||
{}
|
||||
void attach(rbuf_type& rb) { m_rbuf = &rb; }
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
template<class PixFmt>
|
||||
bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
rect_i r(x1, y1, x2, y2);
|
||||
if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
|
||||
{
|
||||
int stride = pixf.stride();
|
||||
m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
|
||||
(r.x2 - r.x1) + 1,
|
||||
(r.y2 - r.y1) + 1,
|
||||
stride);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE unsigned width() const { return m_rbuf->width(); }
|
||||
AGG_INLINE unsigned height() const { return m_rbuf->height(); }
|
||||
AGG_INLINE int stride() const { return m_rbuf->stride(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
|
||||
const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
|
||||
row_data row(int y) const { return m_rbuf->row(y); }
|
||||
|
||||
const int8u* pix_ptr(int x, int y) const
|
||||
{
|
||||
return m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
}
|
||||
|
||||
int8u* pix_ptr(int x, int y)
|
||||
{
|
||||
return m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE static void make_pix(int8u* p, const color_type& c)
|
||||
{
|
||||
*(value_type*)p = c.v;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE color_type pixel(int x, int y) const
|
||||
{
|
||||
value_type* p = (value_type*)m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
return color_type(*p);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
*((value_type*)m_rbuf->row_ptr(x, y, 1) + x * Step + Offset) = c.v;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
|
||||
{
|
||||
copy_or_blend_pix((value_type*)
|
||||
m_rbuf->row_ptr(x, y, 1) + x * Step + Offset,
|
||||
c,
|
||||
cover);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_hline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c)
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
|
||||
|
||||
do
|
||||
{
|
||||
*p = c.v;
|
||||
p += Step;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_vline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c)
|
||||
{
|
||||
do
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
*p = c.v;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_hline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
int8u cover)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
|
||||
|
||||
calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
do
|
||||
{
|
||||
*p = c.v;
|
||||
p += Step;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
Blender::blend_pix(p, c.v, alpha, cover);
|
||||
p += Step;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_vline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
int8u cover)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
value_type* p;
|
||||
calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
*p = c.v;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
Blender::blend_pix(p, c.v, alpha, cover);
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_hspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
const int8u* covers)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
|
||||
|
||||
do
|
||||
{
|
||||
calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
*p = c.v;
|
||||
}
|
||||
else
|
||||
{
|
||||
Blender::blend_pix(p, c.v, alpha, *covers);
|
||||
}
|
||||
p += Step;
|
||||
++covers;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
const int8u* covers)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
do
|
||||
{
|
||||
calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
|
||||
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
*p = c.v;
|
||||
}
|
||||
else
|
||||
{
|
||||
Blender::blend_pix(p, c.v, alpha, *covers);
|
||||
}
|
||||
++covers;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_color_hspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors)
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
|
||||
|
||||
do
|
||||
{
|
||||
*p = colors->v;
|
||||
p += Step;
|
||||
++colors;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_color_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors)
|
||||
{
|
||||
do
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
*p = colors->v;
|
||||
++colors;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_hspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors,
|
||||
const int8u* covers,
|
||||
int8u cover)
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
|
||||
|
||||
if(covers)
|
||||
{
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(p, *colors++, *covers++);
|
||||
p += Step;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(cover == 255)
|
||||
{
|
||||
do
|
||||
{
|
||||
if(colors->a == base_mask)
|
||||
{
|
||||
*p = colors->v;
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_or_blend_pix(p, *colors);
|
||||
}
|
||||
p += Step;
|
||||
++colors;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(p, *colors++, cover);
|
||||
p += Step;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors,
|
||||
const int8u* covers,
|
||||
int8u cover)
|
||||
{
|
||||
value_type* p;
|
||||
if(covers)
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
copy_or_blend_pix(p, *colors++, *covers++);
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(cover == 255)
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
if(colors->a == base_mask)
|
||||
{
|
||||
*p = colors->v;
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_or_blend_pix(p, *colors);
|
||||
}
|
||||
++colors;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
copy_or_blend_pix(p, *colors++, cover);
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Function> void for_each_pixel(Function f)
|
||||
{
|
||||
unsigned y;
|
||||
for(y = 0; y < height(); ++y)
|
||||
{
|
||||
row_data r = m_rbuf->row(y);
|
||||
if(r.ptr)
|
||||
{
|
||||
unsigned len = r.x2 - r.x1 + 1;
|
||||
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(r.x1, y, len) + r.x1 * Step + Offset;
|
||||
|
||||
do
|
||||
{
|
||||
f(p);
|
||||
p += Step;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
|
||||
{
|
||||
for_each_pixel(apply_gamma_dir_gray<color_type, GammaLut>(g));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
|
||||
{
|
||||
for_each_pixel(apply_gamma_inv_gray<color_type, GammaLut>(g));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class RenBuf2>
|
||||
void copy_from(const RenBuf2& from,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len)
|
||||
{
|
||||
const int8u* p = from.row_ptr(ysrc);
|
||||
if(p)
|
||||
{
|
||||
memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
|
||||
p + xsrc * pix_width,
|
||||
len * pix_width);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from_color(const SrcPixelFormatRenderer& from,
|
||||
const color_type& color,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len,
|
||||
int8u cover)
|
||||
{
|
||||
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
|
||||
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
|
||||
if(psrc)
|
||||
{
|
||||
value_type* pdst =
|
||||
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(pdst,
|
||||
color,
|
||||
(*psrc * cover + base_mask) >> base_shift);
|
||||
++psrc;
|
||||
++pdst;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from_lut(const SrcPixelFormatRenderer& from,
|
||||
const color_type* color_lut,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len,
|
||||
int8u cover)
|
||||
{
|
||||
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
|
||||
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
|
||||
if(psrc)
|
||||
{
|
||||
value_type* pdst =
|
||||
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(pdst, color_lut[*psrc], cover);
|
||||
++psrc;
|
||||
++pdst;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
rbuf_type* m_rbuf;
|
||||
};
|
||||
|
||||
typedef blender_gray<gray8> blender_gray8;
|
||||
typedef blender_gray_pre<gray8> blender_gray8_pre;
|
||||
typedef blender_gray<gray16> blender_gray16;
|
||||
typedef blender_gray_pre<gray16> blender_gray16_pre;
|
||||
|
||||
typedef pixfmt_alpha_blend_gray<blender_gray8, rendering_buffer> pixfmt_gray8; //----pixfmt_gray8
|
||||
typedef pixfmt_alpha_blend_gray<blender_gray8_pre, rendering_buffer> pixfmt_gray8_pre; //----pixfmt_gray8_pre
|
||||
typedef pixfmt_alpha_blend_gray<blender_gray16, rendering_buffer> pixfmt_gray16; //----pixfmt_gray16
|
||||
typedef pixfmt_alpha_blend_gray<blender_gray16_pre, rendering_buffer> pixfmt_gray16_pre; //----pixfmt_gray16_pre
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,869 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for high precision colors has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_PIXFMT_RGB_INCLUDED
|
||||
#define AGG_PIXFMT_RGB_INCLUDED
|
||||
|
||||
#include <string.h>
|
||||
#include "agg_basics.h"
|
||||
#include "agg_color_rgba.h"
|
||||
#include "agg_rendering_buffer.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=====================================================apply_gamma_dir_rgb
|
||||
template<class ColorT, class Order, class GammaLut> class apply_gamma_dir_rgb
|
||||
{
|
||||
public:
|
||||
typedef typename ColorT::value_type value_type;
|
||||
|
||||
apply_gamma_dir_rgb(const GammaLut& gamma) : m_gamma(gamma) {}
|
||||
|
||||
AGG_INLINE void operator () (value_type* p)
|
||||
{
|
||||
p[Order::R] = m_gamma.dir(p[Order::R]);
|
||||
p[Order::G] = m_gamma.dir(p[Order::G]);
|
||||
p[Order::B] = m_gamma.dir(p[Order::B]);
|
||||
}
|
||||
|
||||
private:
|
||||
const GammaLut& m_gamma;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=====================================================apply_gamma_inv_rgb
|
||||
template<class ColorT, class Order, class GammaLut> class apply_gamma_inv_rgb
|
||||
{
|
||||
public:
|
||||
typedef typename ColorT::value_type value_type;
|
||||
|
||||
apply_gamma_inv_rgb(const GammaLut& gamma) : m_gamma(gamma) {}
|
||||
|
||||
AGG_INLINE void operator () (value_type* p)
|
||||
{
|
||||
p[Order::R] = m_gamma.inv(p[Order::R]);
|
||||
p[Order::G] = m_gamma.inv(p[Order::G]);
|
||||
p[Order::B] = m_gamma.inv(p[Order::B]);
|
||||
}
|
||||
|
||||
private:
|
||||
const GammaLut& m_gamma;
|
||||
};
|
||||
|
||||
|
||||
//=========================================================blender_rgb
|
||||
template<class ColorT, class Order> struct blender_rgb
|
||||
{
|
||||
typedef ColorT color_type;
|
||||
typedef Order order_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e { base_shift = color_type::base_shift };
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static AGG_INLINE void blend_pix(value_type* p,
|
||||
unsigned cr, unsigned cg, unsigned cb,
|
||||
unsigned alpha,
|
||||
unsigned cover=0)
|
||||
{
|
||||
p[Order::R] += (value_type)(((cr - p[Order::R]) * alpha) >> base_shift);
|
||||
p[Order::G] += (value_type)(((cg - p[Order::G]) * alpha) >> base_shift);
|
||||
p[Order::B] += (value_type)(((cb - p[Order::B]) * alpha) >> base_shift);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//======================================================blender_rgb_pre
|
||||
template<class ColorT, class Order> struct blender_rgb_pre
|
||||
{
|
||||
typedef ColorT color_type;
|
||||
typedef Order order_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e { base_shift = color_type::base_shift };
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static AGG_INLINE void blend_pix(value_type* p,
|
||||
unsigned cr, unsigned cg, unsigned cb,
|
||||
unsigned alpha,
|
||||
unsigned cover)
|
||||
{
|
||||
alpha = color_type::base_mask - alpha;
|
||||
cover = (cover + 1) << (base_shift - 8);
|
||||
p[Order::R] = (value_type)((p[Order::R] * alpha + cr * cover) >> base_shift);
|
||||
p[Order::G] = (value_type)((p[Order::G] * alpha + cg * cover) >> base_shift);
|
||||
p[Order::B] = (value_type)((p[Order::B] * alpha + cb * cover) >> base_shift);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static AGG_INLINE void blend_pix(value_type* p,
|
||||
unsigned cr, unsigned cg, unsigned cb,
|
||||
unsigned alpha)
|
||||
{
|
||||
alpha = color_type::base_mask - alpha;
|
||||
p[Order::R] = (value_type)(((p[Order::R] * alpha) >> base_shift) + cr);
|
||||
p[Order::G] = (value_type)(((p[Order::G] * alpha) >> base_shift) + cg);
|
||||
p[Order::B] = (value_type)(((p[Order::B] * alpha) >> base_shift) + cb);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
//===================================================blender_rgb_gamma
|
||||
template<class ColorT, class Order, class Gamma> class blender_rgb_gamma
|
||||
{
|
||||
public:
|
||||
typedef ColorT color_type;
|
||||
typedef Order order_type;
|
||||
typedef Gamma gamma_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e { base_shift = color_type::base_shift };
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
blender_rgb_gamma() : m_gamma(0) {}
|
||||
void gamma(const gamma_type& g) { m_gamma = &g; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void blend_pix(value_type* p,
|
||||
unsigned cr, unsigned cg, unsigned cb,
|
||||
unsigned alpha,
|
||||
unsigned cover=0)
|
||||
{
|
||||
calc_type r = m_gamma->dir(p[Order::R]);
|
||||
calc_type g = m_gamma->dir(p[Order::G]);
|
||||
calc_type b = m_gamma->dir(p[Order::B]);
|
||||
p[Order::R] = m_gamma->inv((((m_gamma->dir(cr) - r) * alpha) >> base_shift) + r);
|
||||
p[Order::G] = m_gamma->inv((((m_gamma->dir(cg) - g) * alpha) >> base_shift) + g);
|
||||
p[Order::B] = m_gamma->inv((((m_gamma->dir(cb) - b) * alpha) >> base_shift) + b);
|
||||
}
|
||||
|
||||
private:
|
||||
const gamma_type* m_gamma;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//==================================================pixfmt_alpha_blend_rgb
|
||||
template<class Blender, class RenBuf> class pixfmt_alpha_blend_rgb
|
||||
{
|
||||
public:
|
||||
typedef RenBuf rbuf_type;
|
||||
typedef Blender blender_type;
|
||||
typedef typename rbuf_type::row_data row_data;
|
||||
typedef typename blender_type::color_type color_type;
|
||||
typedef typename blender_type::order_type order_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_scale = color_type::base_scale,
|
||||
base_mask = color_type::base_mask,
|
||||
pix_width = sizeof(value_type) * 3
|
||||
};
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_or_blend_pix(value_type* p,
|
||||
const color_type& c,
|
||||
unsigned cover)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
p[order_type::R] = c.r;
|
||||
p[order_type::G] = c.g;
|
||||
p[order_type::B] = c.b;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_or_blend_pix(value_type* p,
|
||||
const color_type& c)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
if(c.a == base_mask)
|
||||
{
|
||||
p[order_type::R] = c.r;
|
||||
p[order_type::G] = c.g;
|
||||
p[order_type::B] = c.b;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_blender.blend_pix(p, c.r, c.g, c.b, c.a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
explicit pixfmt_alpha_blend_rgb(rbuf_type& rb) :
|
||||
m_rbuf(&rb)
|
||||
{}
|
||||
void attach(rbuf_type& rb) { m_rbuf = &rb; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class PixFmt>
|
||||
bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
rect_i r(x1, y1, x2, y2);
|
||||
if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
|
||||
{
|
||||
int stride = pixf.stride();
|
||||
m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
|
||||
(r.x2 - r.x1) + 1,
|
||||
(r.y2 - r.y1) + 1,
|
||||
stride);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
Blender& blender() { return m_blender; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE unsigned width() const { return m_rbuf->width(); }
|
||||
AGG_INLINE unsigned height() const { return m_rbuf->height(); }
|
||||
AGG_INLINE int stride() const { return m_rbuf->stride(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
|
||||
AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
|
||||
AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE int8u* pix_ptr(int x, int y)
|
||||
{
|
||||
return m_rbuf->row_ptr(y) + x * pix_width;
|
||||
}
|
||||
|
||||
AGG_INLINE const int8u* pix_ptr(int x, int y) const
|
||||
{
|
||||
return m_rbuf->row_ptr(y) + x * pix_width;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE static void make_pix(int8u* p, const color_type& c)
|
||||
{
|
||||
((value_type*)p)[order_type::R] = c.r;
|
||||
((value_type*)p)[order_type::G] = c.g;
|
||||
((value_type*)p)[order_type::B] = c.b;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE color_type pixel(int x, int y) const
|
||||
{
|
||||
value_type* p = (value_type*)m_rbuf->row_ptr(y) + x + x + x;
|
||||
return color_type(p[order_type::R],
|
||||
p[order_type::G],
|
||||
p[order_type::B]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
value_type* p = (value_type*)m_rbuf->row_ptr(x, y, 1) + x + x + x;
|
||||
p[order_type::R] = c.r;
|
||||
p[order_type::G] = c.g;
|
||||
p[order_type::B] = c.b;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
|
||||
{
|
||||
copy_or_blend_pix((value_type*)m_rbuf->row_ptr(x, y, 1) + x + x + x, c, cover);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_hline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c)
|
||||
{
|
||||
value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + x + x + x;
|
||||
do
|
||||
{
|
||||
p[order_type::R] = c.r;
|
||||
p[order_type::G] = c.g;
|
||||
p[order_type::B] = c.b;
|
||||
p += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_vline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c)
|
||||
{
|
||||
do
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x + x + x;
|
||||
p[order_type::R] = c.r;
|
||||
p[order_type::G] = c.g;
|
||||
p[order_type::B] = c.b;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_hline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
int8u cover)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x + x + x;
|
||||
|
||||
calc_type alpha = (calc_type(c.a) * (calc_type(cover) + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
do
|
||||
{
|
||||
p[order_type::R] = c.r;
|
||||
p[order_type::G] = c.g;
|
||||
p[order_type::B] = c.b;
|
||||
p += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
|
||||
p += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_vline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
int8u cover)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
value_type* p;
|
||||
calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x + x + x;
|
||||
|
||||
p[order_type::R] = c.r;
|
||||
p[order_type::G] = c.g;
|
||||
p[order_type::B] = c.b;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x + x + x;
|
||||
|
||||
m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_hspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
const int8u* covers)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x + x + x;
|
||||
|
||||
do
|
||||
{
|
||||
calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
p[order_type::R] = c.r;
|
||||
p[order_type::G] = c.g;
|
||||
p[order_type::B] = c.b;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_blender.blend_pix(p, c.r, c.g, c.b, alpha, *covers);
|
||||
}
|
||||
p += 3;
|
||||
++covers;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
const int8u* covers)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
do
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x + x + x;
|
||||
|
||||
calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
p[order_type::R] = c.r;
|
||||
p[order_type::G] = c.g;
|
||||
p[order_type::B] = c.b;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_blender.blend_pix(p, c.r, c.g, c.b, alpha, *covers);
|
||||
}
|
||||
++covers;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_color_hspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors)
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x + x + x;
|
||||
|
||||
do
|
||||
{
|
||||
p[order_type::R] = colors->r;
|
||||
p[order_type::G] = colors->g;
|
||||
p[order_type::B] = colors->b;
|
||||
++colors;
|
||||
p += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_color_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors)
|
||||
{
|
||||
do
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x + x + x;
|
||||
p[order_type::R] = colors->r;
|
||||
p[order_type::G] = colors->g;
|
||||
p[order_type::B] = colors->b;
|
||||
++colors;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_hspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors,
|
||||
const int8u* covers,
|
||||
int8u cover)
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x + x + x;
|
||||
|
||||
if(covers)
|
||||
{
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(p, *colors++, *covers++);
|
||||
p += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(cover == 255)
|
||||
{
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(p, *colors++);
|
||||
p += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(p, *colors++, cover);
|
||||
p += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors,
|
||||
const int8u* covers,
|
||||
int8u cover)
|
||||
{
|
||||
value_type* p;
|
||||
if(covers)
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x + x + x;
|
||||
|
||||
copy_or_blend_pix(p, *colors++, *covers++);
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(cover == 255)
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x + x + x;
|
||||
|
||||
copy_or_blend_pix(p, *colors++);
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x + x + x;
|
||||
|
||||
copy_or_blend_pix(p, *colors++, cover);
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Function> void for_each_pixel(Function f)
|
||||
{
|
||||
unsigned y;
|
||||
for(y = 0; y < height(); ++y)
|
||||
{
|
||||
row_data r = m_rbuf->row(y);
|
||||
if(r.ptr)
|
||||
{
|
||||
unsigned len = r.x2 - r.x1 + 1;
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(r.x1, y, len) + r.x1 * 3;
|
||||
do
|
||||
{
|
||||
f(p);
|
||||
p += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
|
||||
{
|
||||
for_each_pixel(apply_gamma_dir_rgb<color_type, order_type, GammaLut>(g));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
|
||||
{
|
||||
for_each_pixel(apply_gamma_inv_rgb<color_type, order_type, GammaLut>(g));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class RenBuf2>
|
||||
void copy_from(const RenBuf2& from,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len)
|
||||
{
|
||||
const int8u* p = from.row_ptr(ysrc);
|
||||
if(p)
|
||||
{
|
||||
memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
|
||||
p + xsrc * pix_width,
|
||||
len * pix_width);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from(const SrcPixelFormatRenderer& from,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len,
|
||||
int8u cover)
|
||||
{
|
||||
typedef typename SrcPixelFormatRenderer::order_type src_order;
|
||||
|
||||
const value_type* psrc = (const value_type*)from.row_ptr(ysrc);
|
||||
if(psrc)
|
||||
{
|
||||
psrc += xsrc * 4;
|
||||
value_type* pdst =
|
||||
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3;
|
||||
|
||||
if(cover == 255)
|
||||
{
|
||||
do
|
||||
{
|
||||
value_type alpha = psrc[src_order::A];
|
||||
if(alpha)
|
||||
{
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
pdst[order_type::R] = psrc[src_order::R];
|
||||
pdst[order_type::G] = psrc[src_order::G];
|
||||
pdst[order_type::B] = psrc[src_order::B];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_blender.blend_pix(pdst,
|
||||
psrc[src_order::R],
|
||||
psrc[src_order::G],
|
||||
psrc[src_order::B],
|
||||
alpha);
|
||||
}
|
||||
}
|
||||
psrc += 4;
|
||||
pdst += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
color_type color;
|
||||
do
|
||||
{
|
||||
color.r = psrc[src_order::R];
|
||||
color.g = psrc[src_order::G];
|
||||
color.b = psrc[src_order::B];
|
||||
color.a = psrc[src_order::A];
|
||||
copy_or_blend_pix(pdst, color, cover);
|
||||
psrc += 4;
|
||||
pdst += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from_color(const SrcPixelFormatRenderer& from,
|
||||
const color_type& color,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len,
|
||||
int8u cover)
|
||||
{
|
||||
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
|
||||
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
|
||||
if(psrc)
|
||||
{
|
||||
value_type* pdst =
|
||||
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3;
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(pdst,
|
||||
color,
|
||||
(*psrc * cover + base_mask) >> base_shift);
|
||||
++psrc;
|
||||
pdst += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from_lut(const SrcPixelFormatRenderer& from,
|
||||
const color_type* color_lut,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len,
|
||||
int8u cover)
|
||||
{
|
||||
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
|
||||
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
|
||||
if(psrc)
|
||||
{
|
||||
value_type* pdst =
|
||||
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3;
|
||||
|
||||
if(cover == 255)
|
||||
{
|
||||
do
|
||||
{
|
||||
const color_type& color = color_lut[*psrc];
|
||||
m_blender.blend_pix(pdst,
|
||||
color.r, color.g, color.b, color.a);
|
||||
++psrc;
|
||||
pdst += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(pdst, color_lut[*psrc], cover);
|
||||
++psrc;
|
||||
pdst += 3;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
rbuf_type* m_rbuf;
|
||||
Blender m_blender;
|
||||
};
|
||||
|
||||
typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba8, order_rgb>, rendering_buffer> pixfmt_rgb24; //----pixfmt_rgb24
|
||||
typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba8, order_bgr>, rendering_buffer> pixfmt_bgr24; //----pixfmt_bgr24
|
||||
typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba16, order_rgb>, rendering_buffer> pixfmt_rgb48; //----pixfmt_rgb48
|
||||
typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba16, order_bgr>, rendering_buffer> pixfmt_bgr48; //----pixfmt_bgr48
|
||||
|
||||
typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba8, order_rgb>, rendering_buffer> pixfmt_rgb24_pre; //----pixfmt_rgb24_pre
|
||||
typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba8, order_bgr>, rendering_buffer> pixfmt_bgr24_pre; //----pixfmt_bgr24_pre
|
||||
typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba16, order_rgb>, rendering_buffer> pixfmt_rgb48_pre; //----pixfmt_rgb48_pre
|
||||
typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba16, order_bgr>, rendering_buffer> pixfmt_bgr48_pre; //----pixfmt_bgr48_pre
|
||||
|
||||
//-----------------------------------------------------pixfmt_rgb24_gamma
|
||||
template<class Gamma> class pixfmt_rgb24_gamma :
|
||||
public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer>
|
||||
{
|
||||
public:
|
||||
pixfmt_rgb24_gamma(rendering_buffer& rb, const Gamma& g) :
|
||||
pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer>(rb)
|
||||
{
|
||||
this->blender().gamma(g);
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------pixfmt_bgr24_gamma
|
||||
template<class Gamma> class pixfmt_bgr24_gamma :
|
||||
public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer>
|
||||
{
|
||||
public:
|
||||
pixfmt_bgr24_gamma(rendering_buffer& rb, const Gamma& g) :
|
||||
pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer>(rb)
|
||||
{
|
||||
this->blender().gamma(g);
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------pixfmt_rgb48_gamma
|
||||
template<class Gamma> class pixfmt_rgb48_gamma :
|
||||
public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer>
|
||||
{
|
||||
public:
|
||||
pixfmt_rgb48_gamma(rendering_buffer& rb, const Gamma& g) :
|
||||
pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer>(rb)
|
||||
{
|
||||
this->blender().gamma(g);
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------pixfmt_bgr48_gamma
|
||||
template<class Gamma> class pixfmt_bgr48_gamma :
|
||||
public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer>
|
||||
{
|
||||
public:
|
||||
pixfmt_bgr48_gamma(rendering_buffer& rb, const Gamma& g) :
|
||||
pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer>(rb)
|
||||
{
|
||||
this->blender().gamma(g);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,166 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_PIXFMT_TRANSPOSER_INCLUDED
|
||||
#define AGG_PIXFMT_TRANSPOSER_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//=======================================================pixfmt_transposer
|
||||
template<class PixFmt> class pixfmt_transposer
|
||||
{
|
||||
public:
|
||||
typedef PixFmt pixfmt_type;
|
||||
typedef typename pixfmt_type::color_type color_type;
|
||||
typedef typename pixfmt_type::row_data row_data;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
pixfmt_transposer() : m_pixf(0) {}
|
||||
explicit pixfmt_transposer(pixfmt_type& pixf) : m_pixf(&pixf) {}
|
||||
void attach(pixfmt_type& pixf) { m_pixf = &pixf; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE unsigned width() const { return m_pixf->height(); }
|
||||
AGG_INLINE unsigned height() const { return m_pixf->width(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE color_type pixel(int x, int y) const
|
||||
{
|
||||
return m_pixf->pixel(y, x);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
m_pixf->copy_pixel(y, x, c);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void blend_pixel(int x, int y,
|
||||
const color_type& c,
|
||||
int8u cover)
|
||||
{
|
||||
m_pixf->blend_pixel(y, x, c, cover);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_hline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c)
|
||||
{
|
||||
m_pixf->copy_vline(y, x, len, c);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_vline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c)
|
||||
{
|
||||
m_pixf->copy_hline(y, x, len, c);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void blend_hline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
int8u cover)
|
||||
{
|
||||
m_pixf->blend_vline(y, x, len, c, cover);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void blend_vline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
int8u cover)
|
||||
{
|
||||
m_pixf->blend_hline(y, x, len, c, cover);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void blend_solid_hspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
const int8u* covers)
|
||||
{
|
||||
m_pixf->blend_solid_vspan(y, x, len, c, covers);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void blend_solid_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
const int8u* covers)
|
||||
{
|
||||
m_pixf->blend_solid_hspan(y, x, len, c, covers);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_color_hspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors)
|
||||
{
|
||||
m_pixf->copy_color_vspan(y, x, len, colors);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_color_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors)
|
||||
{
|
||||
m_pixf->copy_color_hspan(y, x, len, colors);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void blend_color_hspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors,
|
||||
const int8u* covers,
|
||||
int8u cover)
|
||||
{
|
||||
m_pixf->blend_color_vspan(y, x, len, colors, covers, cover);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void blend_color_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors,
|
||||
const int8u* covers,
|
||||
int8u cover)
|
||||
{
|
||||
m_pixf->blend_color_hspan(y, x, len, colors, covers, cover);
|
||||
}
|
||||
|
||||
private:
|
||||
pixfmt_type* m_pixf;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,764 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// The author 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.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for 32-bit screen coordinates has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RASTERIZER_CELLS_AA_INCLUDED
|
||||
#define AGG_RASTERIZER_CELLS_AA_INCLUDED
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "agg_math.h"
|
||||
#include "agg_array.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-----------------------------------------------------rasterizer_cells_aa
|
||||
// An internal class that implements the main rasterization algorithm.
|
||||
// Used in the rasterizer. Should not be used direcly.
|
||||
template<class Cell> class rasterizer_cells_aa
|
||||
{
|
||||
enum cell_block_scale_e
|
||||
{
|
||||
cell_block_shift = 12,
|
||||
cell_block_size = 1 << cell_block_shift,
|
||||
cell_block_mask = cell_block_size - 1,
|
||||
cell_block_pool = 256,
|
||||
cell_block_limit = 1024
|
||||
};
|
||||
|
||||
struct sorted_y
|
||||
{
|
||||
unsigned start;
|
||||
unsigned num;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef Cell cell_type;
|
||||
typedef rasterizer_cells_aa<Cell> self_type;
|
||||
|
||||
~rasterizer_cells_aa();
|
||||
rasterizer_cells_aa();
|
||||
|
||||
void reset();
|
||||
void style(const cell_type& style_cell);
|
||||
void line(int x1, int y1, int x2, int y2);
|
||||
|
||||
int min_x() const { return m_min_x; }
|
||||
int min_y() const { return m_min_y; }
|
||||
int max_x() const { return m_max_x; }
|
||||
int max_y() const { return m_max_y; }
|
||||
|
||||
void sort_cells();
|
||||
|
||||
unsigned total_cells() const
|
||||
{
|
||||
return m_num_cells;
|
||||
}
|
||||
|
||||
unsigned scanline_num_cells(unsigned y) const
|
||||
{
|
||||
return m_sorted_y[y - m_min_y].num;
|
||||
}
|
||||
|
||||
const cell_type* const* scanline_cells(unsigned y) const
|
||||
{
|
||||
return m_sorted_cells.data() + m_sorted_y[y - m_min_y].start;
|
||||
}
|
||||
|
||||
bool sorted() const { return m_sorted; }
|
||||
|
||||
private:
|
||||
rasterizer_cells_aa(const self_type&);
|
||||
const self_type& operator = (const self_type&);
|
||||
|
||||
void set_curr_cell(int x, int y);
|
||||
void add_curr_cell();
|
||||
void render_hline(int ey, int x1, int y1, int x2, int y2);
|
||||
void allocate_block();
|
||||
|
||||
private:
|
||||
unsigned m_num_blocks;
|
||||
unsigned m_max_blocks;
|
||||
unsigned m_curr_block;
|
||||
unsigned m_num_cells;
|
||||
cell_type** m_cells;
|
||||
cell_type* m_curr_cell_ptr;
|
||||
pod_vector<cell_type*> m_sorted_cells;
|
||||
pod_vector<sorted_y> m_sorted_y;
|
||||
cell_type m_curr_cell;
|
||||
cell_type m_style_cell;
|
||||
int m_min_x;
|
||||
int m_min_y;
|
||||
int m_max_x;
|
||||
int m_max_y;
|
||||
bool m_sorted;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Cell>
|
||||
rasterizer_cells_aa<Cell>::~rasterizer_cells_aa()
|
||||
{
|
||||
if(m_num_blocks)
|
||||
{
|
||||
cell_type** ptr = m_cells + m_num_blocks - 1;
|
||||
while(m_num_blocks--)
|
||||
{
|
||||
pod_allocator<cell_type>::deallocate(*ptr, cell_block_size);
|
||||
ptr--;
|
||||
}
|
||||
pod_allocator<cell_type*>::deallocate(m_cells, m_max_blocks);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Cell>
|
||||
rasterizer_cells_aa<Cell>::rasterizer_cells_aa() :
|
||||
m_num_blocks(0),
|
||||
m_max_blocks(0),
|
||||
m_curr_block(0),
|
||||
m_num_cells(0),
|
||||
m_cells(0),
|
||||
m_curr_cell_ptr(0),
|
||||
m_sorted_cells(),
|
||||
m_sorted_y(),
|
||||
m_min_x(0x7FFFFFFF),
|
||||
m_min_y(0x7FFFFFFF),
|
||||
m_max_x(-0x7FFFFFFF),
|
||||
m_max_y(-0x7FFFFFFF),
|
||||
m_sorted(false)
|
||||
{
|
||||
m_style_cell.initial();
|
||||
m_curr_cell.initial();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Cell>
|
||||
void rasterizer_cells_aa<Cell>::reset()
|
||||
{
|
||||
m_num_cells = 0;
|
||||
m_curr_block = 0;
|
||||
m_curr_cell.initial();
|
||||
m_style_cell.initial();
|
||||
m_sorted = false;
|
||||
m_min_x = 0x7FFFFFFF;
|
||||
m_min_y = 0x7FFFFFFF;
|
||||
m_max_x = -0x7FFFFFFF;
|
||||
m_max_y = -0x7FFFFFFF;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Cell>
|
||||
AGG_INLINE void rasterizer_cells_aa<Cell>::add_curr_cell()
|
||||
{
|
||||
if(m_curr_cell.area | m_curr_cell.cover)
|
||||
{
|
||||
if((m_num_cells & cell_block_mask) == 0)
|
||||
{
|
||||
if(m_num_blocks >= cell_block_limit) return;
|
||||
allocate_block();
|
||||
}
|
||||
*m_curr_cell_ptr++ = m_curr_cell;
|
||||
++m_num_cells;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Cell>
|
||||
AGG_INLINE void rasterizer_cells_aa<Cell>::set_curr_cell(int x, int y)
|
||||
{
|
||||
if(m_curr_cell.not_equal(x, y, m_style_cell))
|
||||
{
|
||||
add_curr_cell();
|
||||
m_curr_cell.style(m_style_cell);
|
||||
m_curr_cell.x = x;
|
||||
m_curr_cell.y = y;
|
||||
m_curr_cell.cover = 0;
|
||||
m_curr_cell.area = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Cell>
|
||||
AGG_INLINE void rasterizer_cells_aa<Cell>::render_hline(int ey,
|
||||
int x1, int y1,
|
||||
int x2, int y2)
|
||||
{
|
||||
int ex1 = x1 >> poly_subpixel_shift;
|
||||
int ex2 = x2 >> poly_subpixel_shift;
|
||||
int fx1 = x1 & poly_subpixel_mask;
|
||||
int fx2 = x2 & poly_subpixel_mask;
|
||||
|
||||
int delta, p, first, dx;
|
||||
int incr, lift, mod, rem;
|
||||
|
||||
//trivial case. Happens often
|
||||
if(y1 == y2)
|
||||
{
|
||||
set_curr_cell(ex2, ey);
|
||||
return;
|
||||
}
|
||||
|
||||
//everything is located in a single cell. That is easy!
|
||||
if(ex1 == ex2)
|
||||
{
|
||||
delta = y2 - y1;
|
||||
m_curr_cell.cover += delta;
|
||||
m_curr_cell.area += (fx1 + fx2) * delta;
|
||||
return;
|
||||
}
|
||||
|
||||
//ok, we'll have to render a run of adjacent cells on the same
|
||||
//hline...
|
||||
p = (poly_subpixel_scale - fx1) * (y2 - y1);
|
||||
first = poly_subpixel_scale;
|
||||
incr = 1;
|
||||
|
||||
dx = x2 - x1;
|
||||
|
||||
if(dx < 0)
|
||||
{
|
||||
p = fx1 * (y2 - y1);
|
||||
first = 0;
|
||||
incr = -1;
|
||||
dx = -dx;
|
||||
}
|
||||
|
||||
delta = p / dx;
|
||||
mod = p % dx;
|
||||
|
||||
if(mod < 0)
|
||||
{
|
||||
delta--;
|
||||
mod += dx;
|
||||
}
|
||||
|
||||
m_curr_cell.cover += delta;
|
||||
m_curr_cell.area += (fx1 + first) * delta;
|
||||
|
||||
ex1 += incr;
|
||||
set_curr_cell(ex1, ey);
|
||||
y1 += delta;
|
||||
|
||||
if(ex1 != ex2)
|
||||
{
|
||||
p = poly_subpixel_scale * (y2 - y1 + delta);
|
||||
lift = p / dx;
|
||||
rem = p % dx;
|
||||
|
||||
if (rem < 0)
|
||||
{
|
||||
lift--;
|
||||
rem += dx;
|
||||
}
|
||||
|
||||
mod -= dx;
|
||||
|
||||
while (ex1 != ex2)
|
||||
{
|
||||
delta = lift;
|
||||
mod += rem;
|
||||
if(mod >= 0)
|
||||
{
|
||||
mod -= dx;
|
||||
delta++;
|
||||
}
|
||||
|
||||
m_curr_cell.cover += delta;
|
||||
m_curr_cell.area += poly_subpixel_scale * delta;
|
||||
y1 += delta;
|
||||
ex1 += incr;
|
||||
set_curr_cell(ex1, ey);
|
||||
}
|
||||
}
|
||||
delta = y2 - y1;
|
||||
m_curr_cell.cover += delta;
|
||||
m_curr_cell.area += (fx2 + poly_subpixel_scale - first) * delta;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Cell>
|
||||
AGG_INLINE void rasterizer_cells_aa<Cell>::style(const cell_type& style_cell)
|
||||
{
|
||||
m_style_cell.style(style_cell);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Cell>
|
||||
void rasterizer_cells_aa<Cell>::line(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
enum dx_limit_e { dx_limit = 16384 << poly_subpixel_shift };
|
||||
|
||||
int dx = x2 - x1;
|
||||
|
||||
if(dx >= dx_limit || dx <= -dx_limit)
|
||||
{
|
||||
int cx = (x1 + x2) >> 1;
|
||||
int cy = (y1 + y2) >> 1;
|
||||
line(x1, y1, cx, cy);
|
||||
line(cx, cy, x2, y2);
|
||||
}
|
||||
|
||||
int dy = y2 - y1;
|
||||
int ex1 = x1 >> poly_subpixel_shift;
|
||||
int ex2 = x2 >> poly_subpixel_shift;
|
||||
int ey1 = y1 >> poly_subpixel_shift;
|
||||
int ey2 = y2 >> poly_subpixel_shift;
|
||||
int fy1 = y1 & poly_subpixel_mask;
|
||||
int fy2 = y2 & poly_subpixel_mask;
|
||||
|
||||
int x_from, x_to;
|
||||
int p, rem, mod, lift, delta, first, incr;
|
||||
|
||||
if(ex1 < m_min_x) m_min_x = ex1;
|
||||
if(ex1 > m_max_x) m_max_x = ex1;
|
||||
if(ey1 < m_min_y) m_min_y = ey1;
|
||||
if(ey1 > m_max_y) m_max_y = ey1;
|
||||
if(ex2 < m_min_x) m_min_x = ex2;
|
||||
if(ex2 > m_max_x) m_max_x = ex2;
|
||||
if(ey2 < m_min_y) m_min_y = ey2;
|
||||
if(ey2 > m_max_y) m_max_y = ey2;
|
||||
|
||||
set_curr_cell(ex1, ey1);
|
||||
|
||||
//everything is on a single hline
|
||||
if(ey1 == ey2)
|
||||
{
|
||||
render_hline(ey1, x1, fy1, x2, fy2);
|
||||
return;
|
||||
}
|
||||
|
||||
//Vertical line - we have to calculate start and end cells,
|
||||
//and then - the common values of the area and coverage for
|
||||
//all cells of the line. We know exactly there's only one
|
||||
//cell, so, we don't have to call render_hline().
|
||||
incr = 1;
|
||||
if(dx == 0)
|
||||
{
|
||||
int ex = x1 >> poly_subpixel_shift;
|
||||
int two_fx = (x1 - (ex << poly_subpixel_shift)) << 1;
|
||||
int area;
|
||||
|
||||
first = poly_subpixel_scale;
|
||||
if(dy < 0)
|
||||
{
|
||||
first = 0;
|
||||
incr = -1;
|
||||
}
|
||||
|
||||
x_from = x1;
|
||||
|
||||
//render_hline(ey1, x_from, fy1, x_from, first);
|
||||
delta = first - fy1;
|
||||
m_curr_cell.cover += delta;
|
||||
m_curr_cell.area += two_fx * delta;
|
||||
|
||||
ey1 += incr;
|
||||
set_curr_cell(ex, ey1);
|
||||
|
||||
delta = first + first - poly_subpixel_scale;
|
||||
area = two_fx * delta;
|
||||
while(ey1 != ey2)
|
||||
{
|
||||
//render_hline(ey1, x_from, poly_subpixel_scale - first, x_from, first);
|
||||
m_curr_cell.cover = delta;
|
||||
m_curr_cell.area = area;
|
||||
ey1 += incr;
|
||||
set_curr_cell(ex, ey1);
|
||||
}
|
||||
//render_hline(ey1, x_from, poly_subpixel_scale - first, x_from, fy2);
|
||||
delta = fy2 - poly_subpixel_scale + first;
|
||||
m_curr_cell.cover += delta;
|
||||
m_curr_cell.area += two_fx * delta;
|
||||
return;
|
||||
}
|
||||
|
||||
//ok, we have to render several hlines
|
||||
p = (poly_subpixel_scale - fy1) * dx;
|
||||
first = poly_subpixel_scale;
|
||||
|
||||
if(dy < 0)
|
||||
{
|
||||
p = fy1 * dx;
|
||||
first = 0;
|
||||
incr = -1;
|
||||
dy = -dy;
|
||||
}
|
||||
|
||||
delta = p / dy;
|
||||
mod = p % dy;
|
||||
|
||||
if(mod < 0)
|
||||
{
|
||||
delta--;
|
||||
mod += dy;
|
||||
}
|
||||
|
||||
x_from = x1 + delta;
|
||||
render_hline(ey1, x1, fy1, x_from, first);
|
||||
|
||||
ey1 += incr;
|
||||
set_curr_cell(x_from >> poly_subpixel_shift, ey1);
|
||||
|
||||
if(ey1 != ey2)
|
||||
{
|
||||
p = poly_subpixel_scale * dx;
|
||||
lift = p / dy;
|
||||
rem = p % dy;
|
||||
|
||||
if(rem < 0)
|
||||
{
|
||||
lift--;
|
||||
rem += dy;
|
||||
}
|
||||
mod -= dy;
|
||||
|
||||
while(ey1 != ey2)
|
||||
{
|
||||
delta = lift;
|
||||
mod += rem;
|
||||
if (mod >= 0)
|
||||
{
|
||||
mod -= dy;
|
||||
delta++;
|
||||
}
|
||||
|
||||
x_to = x_from + delta;
|
||||
render_hline(ey1, x_from, poly_subpixel_scale - first, x_to, first);
|
||||
x_from = x_to;
|
||||
|
||||
ey1 += incr;
|
||||
set_curr_cell(x_from >> poly_subpixel_shift, ey1);
|
||||
}
|
||||
}
|
||||
render_hline(ey1, x_from, poly_subpixel_scale - first, x2, fy2);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Cell>
|
||||
void rasterizer_cells_aa<Cell>::allocate_block()
|
||||
{
|
||||
if(m_curr_block >= m_num_blocks)
|
||||
{
|
||||
if(m_num_blocks >= m_max_blocks)
|
||||
{
|
||||
cell_type** new_cells =
|
||||
pod_allocator<cell_type*>::allocate(m_max_blocks +
|
||||
cell_block_pool);
|
||||
|
||||
if(m_cells)
|
||||
{
|
||||
memcpy(new_cells, m_cells, m_max_blocks * sizeof(cell_type*));
|
||||
pod_allocator<cell_type*>::deallocate(m_cells, m_max_blocks);
|
||||
}
|
||||
m_cells = new_cells;
|
||||
m_max_blocks += cell_block_pool;
|
||||
}
|
||||
|
||||
m_cells[m_num_blocks++] =
|
||||
pod_allocator<cell_type>::allocate(cell_block_size);
|
||||
|
||||
}
|
||||
m_curr_cell_ptr = m_cells[m_curr_block++];
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template <class T> static AGG_INLINE void swap_cells(T* a, T* b)
|
||||
{
|
||||
T temp = *a;
|
||||
*a = *b;
|
||||
*b = temp;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
enum
|
||||
{
|
||||
qsort_threshold = 9
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Cell>
|
||||
void qsort_cells(Cell** start, unsigned num)
|
||||
{
|
||||
Cell** stack[80];
|
||||
Cell*** top;
|
||||
Cell** limit;
|
||||
Cell** base;
|
||||
|
||||
limit = start + num;
|
||||
base = start;
|
||||
top = stack;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int len = int(limit - base);
|
||||
|
||||
Cell** i;
|
||||
Cell** j;
|
||||
Cell** pivot;
|
||||
|
||||
if(len > qsort_threshold)
|
||||
{
|
||||
// we use base + len/2 as the pivot
|
||||
pivot = base + len / 2;
|
||||
swap_cells(base, pivot);
|
||||
|
||||
i = base + 1;
|
||||
j = limit - 1;
|
||||
|
||||
// now ensure that *i <= *base <= *j
|
||||
if((*j)->x < (*i)->x)
|
||||
{
|
||||
swap_cells(i, j);
|
||||
}
|
||||
|
||||
if((*base)->x < (*i)->x)
|
||||
{
|
||||
swap_cells(base, i);
|
||||
}
|
||||
|
||||
if((*j)->x < (*base)->x)
|
||||
{
|
||||
swap_cells(base, j);
|
||||
}
|
||||
|
||||
for(;;)
|
||||
{
|
||||
int x = (*base)->x;
|
||||
do i++; while( (*i)->x < x );
|
||||
do j--; while( x < (*j)->x );
|
||||
|
||||
if(i > j)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
swap_cells(i, j);
|
||||
}
|
||||
|
||||
swap_cells(base, j);
|
||||
|
||||
// now, push the largest sub-array
|
||||
if(j - base > limit - i)
|
||||
{
|
||||
top[0] = base;
|
||||
top[1] = j;
|
||||
base = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
top[0] = i;
|
||||
top[1] = limit;
|
||||
limit = j;
|
||||
}
|
||||
top += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// the sub-array is small, perform insertion sort
|
||||
j = base;
|
||||
i = j + 1;
|
||||
|
||||
for(; i < limit; j = i, i++)
|
||||
{
|
||||
for(; j[1]->x < (*j)->x; j--)
|
||||
{
|
||||
swap_cells(j + 1, j);
|
||||
if (j == base)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(top > stack)
|
||||
{
|
||||
top -= 2;
|
||||
base = top[0];
|
||||
limit = top[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Cell>
|
||||
void rasterizer_cells_aa<Cell>::sort_cells()
|
||||
{
|
||||
if(m_sorted) return; //Perform sort only the first time.
|
||||
|
||||
add_curr_cell();
|
||||
m_curr_cell.x = 0x7FFFFFFF;
|
||||
m_curr_cell.y = 0x7FFFFFFF;
|
||||
m_curr_cell.cover = 0;
|
||||
m_curr_cell.area = 0;
|
||||
|
||||
if(m_num_cells == 0) return;
|
||||
|
||||
// DBG: Check to see if min/max works well.
|
||||
//for(unsigned nc = 0; nc < m_num_cells; nc++)
|
||||
//{
|
||||
// cell_type* cell = m_cells[nc >> cell_block_shift] + (nc & cell_block_mask);
|
||||
// if(cell->x < m_min_x ||
|
||||
// cell->y < m_min_y ||
|
||||
// cell->x > m_max_x ||
|
||||
// cell->y > m_max_y)
|
||||
// {
|
||||
// cell = cell; // Breakpoint here
|
||||
// }
|
||||
//}
|
||||
// Allocate the array of cell pointers
|
||||
m_sorted_cells.allocate(m_num_cells, 16);
|
||||
|
||||
// Allocate and zero the Y array
|
||||
m_sorted_y.allocate(m_max_y - m_min_y + 1, 16);
|
||||
m_sorted_y.zero();
|
||||
|
||||
// Create the Y-histogram (count the numbers of cells for each Y)
|
||||
cell_type** block_ptr = m_cells;
|
||||
cell_type* cell_ptr;
|
||||
unsigned nb = m_num_cells >> cell_block_shift;
|
||||
unsigned i;
|
||||
while(nb--)
|
||||
{
|
||||
cell_ptr = *block_ptr++;
|
||||
i = cell_block_size;
|
||||
while(i--)
|
||||
{
|
||||
m_sorted_y[cell_ptr->y - m_min_y].start++;
|
||||
++cell_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
cell_ptr = *block_ptr++;
|
||||
i = m_num_cells & cell_block_mask;
|
||||
while(i--)
|
||||
{
|
||||
m_sorted_y[cell_ptr->y - m_min_y].start++;
|
||||
++cell_ptr;
|
||||
}
|
||||
|
||||
// Convert the Y-histogram into the array of starting indexes
|
||||
unsigned start = 0;
|
||||
for(i = 0; i < m_sorted_y.size(); i++)
|
||||
{
|
||||
unsigned v = m_sorted_y[i].start;
|
||||
m_sorted_y[i].start = start;
|
||||
start += v;
|
||||
}
|
||||
|
||||
// Fill the cell pointer array sorted by Y
|
||||
block_ptr = m_cells;
|
||||
nb = m_num_cells >> cell_block_shift;
|
||||
while(nb--)
|
||||
{
|
||||
cell_ptr = *block_ptr++;
|
||||
i = cell_block_size;
|
||||
while(i--)
|
||||
{
|
||||
sorted_y& curr_y = m_sorted_y[cell_ptr->y - m_min_y];
|
||||
m_sorted_cells[curr_y.start + curr_y.num] = cell_ptr;
|
||||
++curr_y.num;
|
||||
++cell_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
cell_ptr = *block_ptr++;
|
||||
i = m_num_cells & cell_block_mask;
|
||||
while(i--)
|
||||
{
|
||||
sorted_y& curr_y = m_sorted_y[cell_ptr->y - m_min_y];
|
||||
m_sorted_cells[curr_y.start + curr_y.num] = cell_ptr;
|
||||
++curr_y.num;
|
||||
++cell_ptr;
|
||||
}
|
||||
|
||||
// Finally arrange the X-arrays
|
||||
for(i = 0; i < m_sorted_y.size(); i++)
|
||||
{
|
||||
const sorted_y& curr_y = m_sorted_y[i];
|
||||
if(curr_y.num)
|
||||
{
|
||||
qsort_cells(m_sorted_cells.data() + curr_y.start, curr_y.num);
|
||||
}
|
||||
}
|
||||
m_sorted = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------scanline_hit_test
|
||||
class scanline_hit_test
|
||||
{
|
||||
public:
|
||||
scanline_hit_test(int x) : m_x(x), m_hit(false) {}
|
||||
|
||||
void reset_spans() {}
|
||||
void finalize(int) {}
|
||||
void add_cell(int x, int)
|
||||
{
|
||||
if(m_x == x) m_hit = true;
|
||||
}
|
||||
void add_span(int x, int len, int)
|
||||
{
|
||||
if(m_x >= x && m_x < x+len) m_hit = true;
|
||||
}
|
||||
unsigned num_spans() const { return 1; }
|
||||
bool hit() const { return m_hit; }
|
||||
|
||||
private:
|
||||
int m_x;
|
||||
bool m_hit;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,698 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.3
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// The author 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.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for 32-bit screen coordinates has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_RASTERIZER_COMPOUND_AA_INCLUDED
|
||||
#define AGG_RASTERIZER_COMPOUND_AA_INCLUDED
|
||||
|
||||
#include "agg_rasterizer_cells_aa.h"
|
||||
#include "agg_rasterizer_sl_clip.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-----------------------------------------------------------cell_style_aa
|
||||
// A pixel cell. There're no constructors defined and it was done
|
||||
// intentionally in order to avoid extra overhead when allocating an
|
||||
// array of cells.
|
||||
struct cell_style_aa
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int cover;
|
||||
int area;
|
||||
int16 left, right;
|
||||
|
||||
void initial()
|
||||
{
|
||||
x = 0x7FFFFFFF;
|
||||
y = 0x7FFFFFFF;
|
||||
cover = 0;
|
||||
area = 0;
|
||||
left = -1;
|
||||
right = -1;
|
||||
}
|
||||
|
||||
void style(const cell_style_aa& c)
|
||||
{
|
||||
left = c.left;
|
||||
right = c.right;
|
||||
}
|
||||
|
||||
int not_equal(int ex, int ey, const cell_style_aa& c) const
|
||||
{
|
||||
return (ex - x) | (ey - y) | (left - c.left) | (right - c.right);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//===========================================================layer_order_e
|
||||
enum layer_order_e
|
||||
{
|
||||
layer_unsorted, //------layer_unsorted
|
||||
layer_direct, //------layer_direct
|
||||
layer_inverse //------layer_inverse
|
||||
};
|
||||
|
||||
|
||||
//==================================================rasterizer_compound_aa
|
||||
template<class Clip=rasterizer_sl_clip_int> class rasterizer_compound_aa
|
||||
{
|
||||
struct style_info
|
||||
{
|
||||
unsigned start_cell;
|
||||
unsigned num_cells;
|
||||
int last_x;
|
||||
};
|
||||
|
||||
struct cell_info
|
||||
{
|
||||
int x, area, cover;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef Clip clip_type;
|
||||
typedef typename Clip::conv_type conv_type;
|
||||
typedef typename Clip::coord_type coord_type;
|
||||
|
||||
enum aa_scale_e
|
||||
{
|
||||
aa_shift = 8,
|
||||
aa_scale = 1 << aa_shift,
|
||||
aa_mask = aa_scale - 1,
|
||||
aa_scale2 = aa_scale * 2,
|
||||
aa_mask2 = aa_scale2 - 1
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rasterizer_compound_aa() :
|
||||
m_outline(),
|
||||
m_clipper(),
|
||||
m_filling_rule(fill_non_zero),
|
||||
m_layer_order(layer_direct),
|
||||
m_styles(), // Active Styles
|
||||
m_ast(), // Active Style Table (unique values)
|
||||
m_asm(), // Active Style Mask
|
||||
m_cells(),
|
||||
m_cover_buf(),
|
||||
m_master_alpha(),
|
||||
m_min_style(0x7FFFFFFF),
|
||||
m_max_style(-0x7FFFFFFF),
|
||||
m_start_x(0),
|
||||
m_start_y(0),
|
||||
m_scan_y(0x7FFFFFFF),
|
||||
m_sl_start(0),
|
||||
m_sl_len(0)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset();
|
||||
void reset_clipping();
|
||||
void clip_box(double x1, double y1, double x2, double y2);
|
||||
void filling_rule(filling_rule_e filling_rule);
|
||||
void layer_order(layer_order_e order);
|
||||
void master_alpha(int style, double alpha);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void styles(int left, int right);
|
||||
void move_to(int x, int y);
|
||||
void line_to(int x, int y);
|
||||
void move_to_d(double x, double y);
|
||||
void line_to_d(double x, double y);
|
||||
void add_vertex(double x, double y, unsigned cmd);
|
||||
|
||||
void edge(int x1, int y1, int x2, int y2);
|
||||
void edge_d(double x1, double y1, double x2, double y2);
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
template<class VertexSource>
|
||||
void add_path(VertexSource& vs, unsigned path_id=0)
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
|
||||
unsigned cmd;
|
||||
vs.rewind(path_id);
|
||||
if(m_outline.sorted()) reset();
|
||||
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||
{
|
||||
add_vertex(x, y, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int min_x() const { return m_outline.min_x(); }
|
||||
int min_y() const { return m_outline.min_y(); }
|
||||
int max_x() const { return m_outline.max_x(); }
|
||||
int max_y() const { return m_outline.max_y(); }
|
||||
int min_style() const { return m_min_style; }
|
||||
int max_style() const { return m_max_style; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void sort();
|
||||
bool rewind_scanlines();
|
||||
unsigned sweep_styles();
|
||||
int scanline_start() const { return m_sl_start; }
|
||||
unsigned scanline_length() const { return m_sl_len; }
|
||||
unsigned style(unsigned style_idx) const;
|
||||
|
||||
cover_type* allocate_cover_buffer(unsigned len);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
bool navigate_scanline(int y);
|
||||
bool hit_test(int tx, int ty);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE unsigned calculate_alpha(int area, unsigned master_alpha) const
|
||||
{
|
||||
int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift);
|
||||
if(cover < 0) cover = -cover;
|
||||
if(m_filling_rule == fill_even_odd)
|
||||
{
|
||||
cover &= aa_mask2;
|
||||
if(cover > aa_scale)
|
||||
{
|
||||
cover = aa_scale2 - cover;
|
||||
}
|
||||
}
|
||||
if(cover > aa_mask) cover = aa_mask;
|
||||
return (cover * master_alpha + aa_mask) >> aa_shift;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Sweeps one scanline with one style index. The style ID can be
|
||||
// determined by calling style().
|
||||
template<class Scanline> bool sweep_scanline(Scanline& sl, int style_idx)
|
||||
{
|
||||
int scan_y = m_scan_y - 1;
|
||||
if(scan_y > m_outline.max_y()) return false;
|
||||
|
||||
sl.reset_spans();
|
||||
|
||||
unsigned master_alpha = aa_mask;
|
||||
|
||||
if(style_idx < 0)
|
||||
{
|
||||
style_idx = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
style_idx++;
|
||||
master_alpha = m_master_alpha[m_ast[style_idx] + m_min_style - 1];
|
||||
}
|
||||
|
||||
const style_info& st = m_styles[m_ast[style_idx]];
|
||||
|
||||
unsigned num_cells = st.num_cells;
|
||||
cell_info* cell = &m_cells[st.start_cell];
|
||||
|
||||
int cover = 0;
|
||||
while(num_cells--)
|
||||
{
|
||||
unsigned alpha;
|
||||
int x = cell->x;
|
||||
int area = cell->area;
|
||||
|
||||
cover += cell->cover;
|
||||
|
||||
++cell;
|
||||
|
||||
if(area)
|
||||
{
|
||||
alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area,
|
||||
master_alpha);
|
||||
sl.add_cell(x, alpha);
|
||||
x++;
|
||||
}
|
||||
|
||||
if(num_cells && cell->x > x)
|
||||
{
|
||||
alpha = calculate_alpha(cover << (poly_subpixel_shift + 1),
|
||||
master_alpha);
|
||||
if(alpha)
|
||||
{
|
||||
sl.add_span(x, cell->x - x, alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(sl.num_spans() == 0) return false;
|
||||
sl.finalize(scan_y);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
void add_style(int style_id);
|
||||
void allocate_master_alpha();
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Disable copying
|
||||
rasterizer_compound_aa(const rasterizer_compound_aa<Clip>&);
|
||||
const rasterizer_compound_aa<Clip>&
|
||||
operator = (const rasterizer_compound_aa<Clip>&);
|
||||
|
||||
private:
|
||||
rasterizer_cells_aa<cell_style_aa> m_outline;
|
||||
clip_type m_clipper;
|
||||
filling_rule_e m_filling_rule;
|
||||
layer_order_e m_layer_order;
|
||||
pod_vector<style_info> m_styles; // Active Styles
|
||||
pod_vector<unsigned> m_ast; // Active Style Table (unique values)
|
||||
pod_vector<int8u> m_asm; // Active Style Mask
|
||||
pod_vector<cell_info> m_cells;
|
||||
pod_vector<cover_type> m_cover_buf;
|
||||
pod_bvector<unsigned> m_master_alpha;
|
||||
|
||||
int m_min_style;
|
||||
int m_max_style;
|
||||
coord_type m_start_x;
|
||||
coord_type m_start_y;
|
||||
int m_scan_y;
|
||||
int m_sl_start;
|
||||
unsigned m_sl_len;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::reset()
|
||||
{
|
||||
m_outline.reset();
|
||||
m_min_style = 0x7FFFFFFF;
|
||||
m_max_style = -0x7FFFFFFF;
|
||||
m_scan_y = 0x7FFFFFFF;
|
||||
m_sl_start = 0;
|
||||
m_sl_len = 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::filling_rule(filling_rule_e filling_rule)
|
||||
{
|
||||
m_filling_rule = filling_rule;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::layer_order(layer_order_e order)
|
||||
{
|
||||
m_layer_order = order;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::clip_box(double x1, double y1,
|
||||
double x2, double y2)
|
||||
{
|
||||
reset();
|
||||
m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1),
|
||||
conv_type::upscale(x2), conv_type::upscale(y2));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::reset_clipping()
|
||||
{
|
||||
reset();
|
||||
m_clipper.reset_clipping();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::styles(int left, int right)
|
||||
{
|
||||
cell_style_aa cell;
|
||||
cell.initial();
|
||||
cell.left = (int16)left;
|
||||
cell.right = (int16)right;
|
||||
m_outline.style(cell);
|
||||
if(left >= 0 && left < m_min_style) m_min_style = left;
|
||||
if(left >= 0 && left > m_max_style) m_max_style = left;
|
||||
if(right >= 0 && right < m_min_style) m_min_style = right;
|
||||
if(right >= 0 && right > m_max_style) m_max_style = right;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::move_to(int x, int y)
|
||||
{
|
||||
if(m_outline.sorted()) reset();
|
||||
m_clipper.move_to(m_start_x = conv_type::downscale(x),
|
||||
m_start_y = conv_type::downscale(y));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::line_to(int x, int y)
|
||||
{
|
||||
m_clipper.line_to(m_outline,
|
||||
conv_type::downscale(x),
|
||||
conv_type::downscale(y));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::move_to_d(double x, double y)
|
||||
{
|
||||
if(m_outline.sorted()) reset();
|
||||
m_clipper.move_to(m_start_x = conv_type::upscale(x),
|
||||
m_start_y = conv_type::upscale(y));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::line_to_d(double x, double y)
|
||||
{
|
||||
m_clipper.line_to(m_outline,
|
||||
conv_type::upscale(x),
|
||||
conv_type::upscale(y));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::add_vertex(double x, double y, unsigned cmd)
|
||||
{
|
||||
if(is_move_to(cmd))
|
||||
{
|
||||
move_to_d(x, y);
|
||||
}
|
||||
else
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
line_to_d(x, y);
|
||||
}
|
||||
else
|
||||
if(is_close(cmd))
|
||||
{
|
||||
m_clipper.line_to(m_outline, m_start_x, m_start_y);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::edge(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
if(m_outline.sorted()) reset();
|
||||
m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1));
|
||||
m_clipper.line_to(m_outline,
|
||||
conv_type::downscale(x2),
|
||||
conv_type::downscale(y2));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::edge_d(double x1, double y1,
|
||||
double x2, double y2)
|
||||
{
|
||||
if(m_outline.sorted()) reset();
|
||||
m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1));
|
||||
m_clipper.line_to(m_outline,
|
||||
conv_type::upscale(x2),
|
||||
conv_type::upscale(y2));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
AGG_INLINE void rasterizer_compound_aa<Clip>::sort()
|
||||
{
|
||||
m_outline.sort_cells();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
AGG_INLINE bool rasterizer_compound_aa<Clip>::rewind_scanlines()
|
||||
{
|
||||
m_outline.sort_cells();
|
||||
if(m_outline.total_cells() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(m_max_style < m_min_style)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_scan_y = m_outline.min_y();
|
||||
m_styles.allocate(m_max_style - m_min_style + 2, 128);
|
||||
allocate_master_alpha();
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
AGG_INLINE void rasterizer_compound_aa<Clip>::add_style(int style_id)
|
||||
{
|
||||
if(style_id < 0) style_id = 0;
|
||||
else style_id -= m_min_style - 1;
|
||||
|
||||
unsigned nbyte = style_id >> 3;
|
||||
unsigned mask = 1 << (style_id & 7);
|
||||
|
||||
style_info* style = &m_styles[style_id];
|
||||
if((m_asm[nbyte] & mask) == 0)
|
||||
{
|
||||
m_ast.add(style_id);
|
||||
m_asm[nbyte] |= mask;
|
||||
style->start_cell = 0;
|
||||
style->num_cells = 0;
|
||||
style->last_x = -0x7FFFFFFF;
|
||||
}
|
||||
++style->start_cell;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Returns the number of styles
|
||||
template<class Clip>
|
||||
unsigned rasterizer_compound_aa<Clip>::sweep_styles()
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
if(m_scan_y > m_outline.max_y()) return 0;
|
||||
unsigned num_cells = m_outline.scanline_num_cells(m_scan_y);
|
||||
const cell_style_aa* const* cells = m_outline.scanline_cells(m_scan_y);
|
||||
unsigned num_styles = m_max_style - m_min_style + 2;
|
||||
const cell_style_aa* curr_cell;
|
||||
unsigned style_id;
|
||||
style_info* style;
|
||||
cell_info* cell;
|
||||
|
||||
m_cells.allocate(num_cells * 2, 256); // Each cell can have two styles
|
||||
m_ast.capacity(num_styles, 64);
|
||||
m_asm.allocate((num_styles + 7) >> 3, 8);
|
||||
m_asm.zero();
|
||||
|
||||
if(num_cells)
|
||||
{
|
||||
// Pre-add zero (for no-fill style, that is, -1).
|
||||
// We need that to ensure that the "-1 style" would go first.
|
||||
m_asm[0] |= 1;
|
||||
m_ast.add(0);
|
||||
style = &m_styles[0];
|
||||
style->start_cell = 0;
|
||||
style->num_cells = 0;
|
||||
style->last_x = -0x7FFFFFFF;
|
||||
|
||||
m_sl_start = cells[0]->x;
|
||||
m_sl_len = cells[num_cells-1]->x - m_sl_start + 1;
|
||||
while(num_cells--)
|
||||
{
|
||||
curr_cell = *cells++;
|
||||
add_style(curr_cell->left);
|
||||
add_style(curr_cell->right);
|
||||
}
|
||||
|
||||
// Convert the Y-histogram into the array of starting indexes
|
||||
unsigned i;
|
||||
unsigned start_cell = 0;
|
||||
for(i = 0; i < m_ast.size(); i++)
|
||||
{
|
||||
style_info& st = m_styles[m_ast[i]];
|
||||
unsigned v = st.start_cell;
|
||||
st.start_cell = start_cell;
|
||||
start_cell += v;
|
||||
}
|
||||
|
||||
cells = m_outline.scanline_cells(m_scan_y);
|
||||
num_cells = m_outline.scanline_num_cells(m_scan_y);
|
||||
|
||||
while(num_cells--)
|
||||
{
|
||||
curr_cell = *cells++;
|
||||
style_id = (curr_cell->left < 0) ? 0 :
|
||||
curr_cell->left - m_min_style + 1;
|
||||
|
||||
style = &m_styles[style_id];
|
||||
if(curr_cell->x == style->last_x)
|
||||
{
|
||||
cell = &m_cells[style->start_cell + style->num_cells - 1];
|
||||
cell->area += curr_cell->area;
|
||||
cell->cover += curr_cell->cover;
|
||||
}
|
||||
else
|
||||
{
|
||||
cell = &m_cells[style->start_cell + style->num_cells];
|
||||
cell->x = curr_cell->x;
|
||||
cell->area = curr_cell->area;
|
||||
cell->cover = curr_cell->cover;
|
||||
style->last_x = curr_cell->x;
|
||||
style->num_cells++;
|
||||
}
|
||||
|
||||
style_id = (curr_cell->right < 0) ? 0 :
|
||||
curr_cell->right - m_min_style + 1;
|
||||
|
||||
style = &m_styles[style_id];
|
||||
if(curr_cell->x == style->last_x)
|
||||
{
|
||||
cell = &m_cells[style->start_cell + style->num_cells - 1];
|
||||
cell->area -= curr_cell->area;
|
||||
cell->cover -= curr_cell->cover;
|
||||
}
|
||||
else
|
||||
{
|
||||
cell = &m_cells[style->start_cell + style->num_cells];
|
||||
cell->x = curr_cell->x;
|
||||
cell->area = -curr_cell->area;
|
||||
cell->cover = -curr_cell->cover;
|
||||
style->last_x = curr_cell->x;
|
||||
style->num_cells++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(m_ast.size() > 1) break;
|
||||
++m_scan_y;
|
||||
}
|
||||
++m_scan_y;
|
||||
|
||||
if(m_layer_order != layer_unsorted)
|
||||
{
|
||||
range_adaptor<pod_vector<unsigned> > ra(m_ast, 1, m_ast.size() - 1);
|
||||
if(m_layer_order == layer_direct) quick_sort(ra, unsigned_greater);
|
||||
else quick_sort(ra, unsigned_less);
|
||||
}
|
||||
|
||||
return m_ast.size() - 1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Returns style ID depending of the existing style index
|
||||
template<class Clip>
|
||||
AGG_INLINE
|
||||
unsigned rasterizer_compound_aa<Clip>::style(unsigned style_idx) const
|
||||
{
|
||||
return m_ast[style_idx + 1] + m_min_style - 1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
AGG_INLINE bool rasterizer_compound_aa<Clip>::navigate_scanline(int y)
|
||||
{
|
||||
m_outline.sort_cells();
|
||||
if(m_outline.total_cells() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(m_max_style < m_min_style)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(y < m_outline.min_y() || y > m_outline.max_y())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_scan_y = y;
|
||||
m_styles.allocate(m_max_style - m_min_style + 2, 128);
|
||||
allocate_master_alpha();
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
bool rasterizer_compound_aa<Clip>::hit_test(int tx, int ty)
|
||||
{
|
||||
if(!navigate_scanline(ty))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned num_styles = sweep_styles();
|
||||
if(num_styles <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
scanline_hit_test sl(tx);
|
||||
sweep_scanline(sl, -1);
|
||||
return sl.hit();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
cover_type* rasterizer_compound_aa<Clip>::allocate_cover_buffer(unsigned len)
|
||||
{
|
||||
m_cover_buf.allocate(len, 256);
|
||||
return &m_cover_buf[0];
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::allocate_master_alpha()
|
||||
{
|
||||
while((int)m_master_alpha.size() <= m_max_style)
|
||||
{
|
||||
m_master_alpha.add(aa_mask);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_compound_aa<Clip>::master_alpha(int style, double alpha)
|
||||
{
|
||||
if(style >= 0)
|
||||
{
|
||||
while((int)m_master_alpha.size() <= style)
|
||||
{
|
||||
m_master_alpha.add(aa_mask);
|
||||
}
|
||||
m_master_alpha[style] = uround(alpha * aa_mask);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RASTERIZER_OUTLINE_INCLUDED
|
||||
#define AGG_RASTERIZER_OUTLINE_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//======================================================rasterizer_outline
|
||||
template<class Renderer> class rasterizer_outline
|
||||
{
|
||||
public:
|
||||
explicit rasterizer_outline(Renderer& ren) :
|
||||
m_ren(&ren),
|
||||
m_start_x(0),
|
||||
m_start_y(0),
|
||||
m_vertices(0)
|
||||
{}
|
||||
void attach(Renderer& ren) { m_ren = &ren; }
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void move_to(int x, int y)
|
||||
{
|
||||
m_vertices = 1;
|
||||
m_ren->move_to(m_start_x = x, m_start_y = y);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void line_to(int x, int y)
|
||||
{
|
||||
++m_vertices;
|
||||
m_ren->line_to(x, y);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void move_to_d(double x, double y)
|
||||
{
|
||||
move_to(m_ren->coord(x), m_ren->coord(y));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void line_to_d(double x, double y)
|
||||
{
|
||||
line_to(m_ren->coord(x), m_ren->coord(y));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void close()
|
||||
{
|
||||
if(m_vertices > 2)
|
||||
{
|
||||
line_to(m_start_x, m_start_y);
|
||||
}
|
||||
m_vertices = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_vertex(double x, double y, unsigned cmd)
|
||||
{
|
||||
if(is_move_to(cmd))
|
||||
{
|
||||
move_to_d(x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_end_poly(cmd))
|
||||
{
|
||||
if(is_closed(cmd)) close();
|
||||
}
|
||||
else
|
||||
{
|
||||
line_to_d(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class VertexSource>
|
||||
void add_path(VertexSource& vs, unsigned path_id=0)
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
|
||||
unsigned cmd;
|
||||
vs.rewind(path_id);
|
||||
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||
{
|
||||
add_vertex(x, y, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class VertexSource, class ColorStorage, class PathId>
|
||||
void render_all_paths(VertexSource& vs,
|
||||
const ColorStorage& colors,
|
||||
const PathId& path_id,
|
||||
unsigned num_paths)
|
||||
{
|
||||
for(unsigned i = 0; i < num_paths; i++)
|
||||
{
|
||||
m_ren->line_color(colors[i]);
|
||||
add_path(vs, path_id[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Ctrl> void render_ctrl(Ctrl& c)
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < c.num_paths(); i++)
|
||||
{
|
||||
m_ren->line_color(c.color(i));
|
||||
add_path(c, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
Renderer* m_ren;
|
||||
int m_start_x;
|
||||
int m_start_y;
|
||||
unsigned m_vertices;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,609 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RASTERIZER_OUTLINE_AA_INCLUDED
|
||||
#define AGG_RASTERIZER_OUTLINE_AA_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_line_aa_basics.h"
|
||||
#include "agg_vertex_sequence.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
inline bool cmp_dist_start(int d) { return d > 0; }
|
||||
inline bool cmp_dist_end(int d) { return d <= 0; }
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------line_aa_vertex
|
||||
// Vertex (x, y) with the distance to the next one. The last vertex has
|
||||
// the distance between the last and the first points
|
||||
struct line_aa_vertex
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int len;
|
||||
|
||||
line_aa_vertex() {}
|
||||
line_aa_vertex(int x_, int y_) :
|
||||
x(x_),
|
||||
y(y_),
|
||||
len(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator () (const line_aa_vertex& val)
|
||||
{
|
||||
double dx = val.x - x;
|
||||
double dy = val.y - y;
|
||||
return (len = uround(sqrt(dx * dx + dy * dy))) >
|
||||
(line_subpixel_scale + line_subpixel_scale / 2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------outline_aa_join_e
|
||||
enum outline_aa_join_e
|
||||
{
|
||||
outline_no_join, //-----outline_no_join
|
||||
outline_miter_join, //-----outline_miter_join
|
||||
outline_round_join, //-----outline_round_join
|
||||
outline_miter_accurate_join //-----outline_accurate_join
|
||||
};
|
||||
|
||||
//=======================================================rasterizer_outline_aa
|
||||
template<class Renderer, class Coord=line_coord> class rasterizer_outline_aa
|
||||
{
|
||||
private:
|
||||
//------------------------------------------------------------------------
|
||||
struct draw_vars
|
||||
{
|
||||
unsigned idx;
|
||||
int x1, y1, x2, y2;
|
||||
line_parameters curr, next;
|
||||
int lcurr, lnext;
|
||||
int xb1, yb1, xb2, yb2;
|
||||
unsigned flags;
|
||||
};
|
||||
|
||||
void draw(draw_vars& dv, unsigned start, unsigned end);
|
||||
|
||||
public:
|
||||
typedef line_aa_vertex vertex_type;
|
||||
typedef vertex_sequence<vertex_type, 6> vertex_storage_type;
|
||||
|
||||
explicit rasterizer_outline_aa(Renderer& ren) :
|
||||
m_ren(&ren),
|
||||
m_line_join(ren.accurate_join_only() ?
|
||||
outline_miter_accurate_join :
|
||||
outline_round_join),
|
||||
m_round_cap(false),
|
||||
m_start_x(0),
|
||||
m_start_y(0)
|
||||
{}
|
||||
void attach(Renderer& ren) { m_ren = &ren; }
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void line_join(outline_aa_join_e join)
|
||||
{
|
||||
m_line_join = m_ren->accurate_join_only() ?
|
||||
outline_miter_accurate_join :
|
||||
join;
|
||||
}
|
||||
bool line_join() const { return m_line_join; }
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void round_cap(bool v) { m_round_cap = v; }
|
||||
bool round_cap() const { return m_round_cap; }
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void move_to(int x, int y)
|
||||
{
|
||||
m_src_vertices.modify_last(vertex_type(m_start_x = x, m_start_y = y));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void line_to(int x, int y)
|
||||
{
|
||||
m_src_vertices.add(vertex_type(x, y));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void move_to_d(double x, double y)
|
||||
{
|
||||
move_to(Coord::conv(x), Coord::conv(y));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void line_to_d(double x, double y)
|
||||
{
|
||||
line_to(Coord::conv(x), Coord::conv(y));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void render(bool close_polygon);
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void add_vertex(double x, double y, unsigned cmd)
|
||||
{
|
||||
if(is_move_to(cmd))
|
||||
{
|
||||
render(false);
|
||||
move_to_d(x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_end_poly(cmd))
|
||||
{
|
||||
render(is_closed(cmd));
|
||||
if(is_closed(cmd))
|
||||
{
|
||||
move_to(m_start_x, m_start_y);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
line_to_d(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource>
|
||||
void add_path(VertexSource& vs, unsigned path_id=0)
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
|
||||
unsigned cmd;
|
||||
vs.rewind(path_id);
|
||||
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||
{
|
||||
add_vertex(x, y, cmd);
|
||||
}
|
||||
render(false);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource, class ColorStorage, class PathId>
|
||||
void render_all_paths(VertexSource& vs,
|
||||
const ColorStorage& colors,
|
||||
const PathId& path_id,
|
||||
unsigned num_paths)
|
||||
{
|
||||
for(unsigned i = 0; i < num_paths; i++)
|
||||
{
|
||||
m_ren->color(colors[i]);
|
||||
add_path(vs, path_id[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Ctrl> void render_ctrl(Ctrl& c)
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < c.num_paths(); i++)
|
||||
{
|
||||
m_ren->color(c.color(i));
|
||||
add_path(c, i);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
rasterizer_outline_aa(const rasterizer_outline_aa<Renderer, Coord>&);
|
||||
const rasterizer_outline_aa<Renderer, Coord>& operator =
|
||||
(const rasterizer_outline_aa<Renderer, Coord>&);
|
||||
|
||||
Renderer* m_ren;
|
||||
vertex_storage_type m_src_vertices;
|
||||
outline_aa_join_e m_line_join;
|
||||
bool m_round_cap;
|
||||
int m_start_x;
|
||||
int m_start_y;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<class Renderer, class Coord>
|
||||
void rasterizer_outline_aa<Renderer, Coord>::draw(draw_vars& dv,
|
||||
unsigned start,
|
||||
unsigned end)
|
||||
{
|
||||
unsigned i;
|
||||
const vertex_storage_type::value_type* v;
|
||||
|
||||
for(i = start; i < end; i++)
|
||||
{
|
||||
if(m_line_join == outline_round_join)
|
||||
{
|
||||
dv.xb1 = dv.curr.x1 + (dv.curr.y2 - dv.curr.y1);
|
||||
dv.yb1 = dv.curr.y1 - (dv.curr.x2 - dv.curr.x1);
|
||||
dv.xb2 = dv.curr.x2 + (dv.curr.y2 - dv.curr.y1);
|
||||
dv.yb2 = dv.curr.y2 - (dv.curr.x2 - dv.curr.x1);
|
||||
}
|
||||
|
||||
switch(dv.flags)
|
||||
{
|
||||
case 0: m_ren->line3(dv.curr, dv.xb1, dv.yb1, dv.xb2, dv.yb2); break;
|
||||
case 1: m_ren->line2(dv.curr, dv.xb2, dv.yb2); break;
|
||||
case 2: m_ren->line1(dv.curr, dv.xb1, dv.yb1); break;
|
||||
case 3: m_ren->line0(dv.curr); break;
|
||||
}
|
||||
|
||||
if(m_line_join == outline_round_join && (dv.flags & 2) == 0)
|
||||
{
|
||||
m_ren->pie(dv.curr.x2, dv.curr.y2,
|
||||
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
|
||||
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1),
|
||||
dv.curr.x2 + (dv.next.y2 - dv.next.y1),
|
||||
dv.curr.y2 - (dv.next.x2 - dv.next.x1));
|
||||
}
|
||||
|
||||
dv.x1 = dv.x2;
|
||||
dv.y1 = dv.y2;
|
||||
dv.lcurr = dv.lnext;
|
||||
dv.lnext = m_src_vertices[dv.idx].len;
|
||||
|
||||
++dv.idx;
|
||||
if(dv.idx >= m_src_vertices.size()) dv.idx = 0;
|
||||
|
||||
v = &m_src_vertices[dv.idx];
|
||||
dv.x2 = v->x;
|
||||
dv.y2 = v->y;
|
||||
|
||||
dv.curr = dv.next;
|
||||
dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
|
||||
dv.xb1 = dv.xb2;
|
||||
dv.yb1 = dv.yb2;
|
||||
|
||||
switch(m_line_join)
|
||||
{
|
||||
case outline_no_join:
|
||||
dv.flags = 3;
|
||||
break;
|
||||
|
||||
case outline_miter_join:
|
||||
dv.flags >>= 1;
|
||||
dv.flags |= ((dv.curr.diagonal_quadrant() ==
|
||||
dv.next.diagonal_quadrant()) << 1);
|
||||
if((dv.flags & 2) == 0)
|
||||
{
|
||||
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
|
||||
}
|
||||
break;
|
||||
|
||||
case outline_round_join:
|
||||
dv.flags >>= 1;
|
||||
dv.flags |= ((dv.curr.diagonal_quadrant() ==
|
||||
dv.next.diagonal_quadrant()) << 1);
|
||||
break;
|
||||
|
||||
case outline_miter_accurate_join:
|
||||
dv.flags = 0;
|
||||
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<class Renderer, class Coord>
|
||||
void rasterizer_outline_aa<Renderer, Coord>::render(bool close_polygon)
|
||||
{
|
||||
m_src_vertices.close(close_polygon);
|
||||
draw_vars dv;
|
||||
const vertex_storage_type::value_type* v;
|
||||
int x1;
|
||||
int y1;
|
||||
int x2;
|
||||
int y2;
|
||||
int lprev;
|
||||
|
||||
if(close_polygon)
|
||||
{
|
||||
if(m_src_vertices.size() >= 3)
|
||||
{
|
||||
dv.idx = 2;
|
||||
|
||||
v = &m_src_vertices[m_src_vertices.size() - 1];
|
||||
x1 = v->x;
|
||||
y1 = v->y;
|
||||
lprev = v->len;
|
||||
|
||||
v = &m_src_vertices[0];
|
||||
x2 = v->x;
|
||||
y2 = v->y;
|
||||
dv.lcurr = v->len;
|
||||
line_parameters prev(x1, y1, x2, y2, lprev);
|
||||
|
||||
v = &m_src_vertices[1];
|
||||
dv.x1 = v->x;
|
||||
dv.y1 = v->y;
|
||||
dv.lnext = v->len;
|
||||
dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr);
|
||||
|
||||
v = &m_src_vertices[dv.idx];
|
||||
dv.x2 = v->x;
|
||||
dv.y2 = v->y;
|
||||
dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
|
||||
|
||||
dv.xb1 = 0;
|
||||
dv.yb1 = 0;
|
||||
dv.xb2 = 0;
|
||||
dv.yb2 = 0;
|
||||
|
||||
switch(m_line_join)
|
||||
{
|
||||
case outline_no_join:
|
||||
dv.flags = 3;
|
||||
break;
|
||||
|
||||
case outline_miter_join:
|
||||
case outline_round_join:
|
||||
dv.flags =
|
||||
(prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) |
|
||||
((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1);
|
||||
break;
|
||||
|
||||
case outline_miter_accurate_join:
|
||||
dv.flags = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if((dv.flags & 1) == 0 && m_line_join != outline_round_join)
|
||||
{
|
||||
bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
|
||||
}
|
||||
|
||||
if((dv.flags & 2) == 0 && m_line_join != outline_round_join)
|
||||
{
|
||||
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
|
||||
}
|
||||
draw(dv, 0, m_src_vertices.size());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(m_src_vertices.size())
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
v = &m_src_vertices[0];
|
||||
x1 = v->x;
|
||||
y1 = v->y;
|
||||
lprev = v->len;
|
||||
v = &m_src_vertices[1];
|
||||
x2 = v->x;
|
||||
y2 = v->y;
|
||||
line_parameters lp(x1, y1, x2, y2, lprev);
|
||||
if(m_round_cap)
|
||||
{
|
||||
m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
|
||||
}
|
||||
m_ren->line3(lp,
|
||||
x1 + (y2 - y1),
|
||||
y1 - (x2 - x1),
|
||||
x2 + (y2 - y1),
|
||||
y2 - (x2 - x1));
|
||||
if(m_round_cap)
|
||||
{
|
||||
m_ren->semidot(cmp_dist_end, x2, y2, x2 + (y2 - y1), y2 - (x2 - x1));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
{
|
||||
int x3, y3;
|
||||
int lnext;
|
||||
v = &m_src_vertices[0];
|
||||
x1 = v->x;
|
||||
y1 = v->y;
|
||||
lprev = v->len;
|
||||
v = &m_src_vertices[1];
|
||||
x2 = v->x;
|
||||
y2 = v->y;
|
||||
lnext = v->len;
|
||||
v = &m_src_vertices[2];
|
||||
x3 = v->x;
|
||||
y3 = v->y;
|
||||
line_parameters lp1(x1, y1, x2, y2, lprev);
|
||||
line_parameters lp2(x2, y2, x3, y3, lnext);
|
||||
|
||||
if(m_round_cap)
|
||||
{
|
||||
m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
|
||||
}
|
||||
|
||||
if(m_line_join == outline_round_join)
|
||||
{
|
||||
m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1),
|
||||
x2 + (y2 - y1), y2 - (x2 - x1));
|
||||
|
||||
m_ren->pie(x2, y2, x2 + (y2 - y1), y2 - (x2 - x1),
|
||||
x2 + (y3 - y2), y2 - (x3 - x2));
|
||||
|
||||
m_ren->line3(lp2, x2 + (y3 - y2), y2 - (x3 - x2),
|
||||
x3 + (y3 - y2), y3 - (x3 - x2));
|
||||
}
|
||||
else
|
||||
{
|
||||
bisectrix(lp1, lp2, &dv.xb1, &dv.yb1);
|
||||
m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1),
|
||||
dv.xb1, dv.yb1);
|
||||
|
||||
m_ren->line3(lp2, dv.xb1, dv.yb1,
|
||||
x3 + (y3 - y2), y3 - (x3 - x2));
|
||||
}
|
||||
if(m_round_cap)
|
||||
{
|
||||
m_ren->semidot(cmp_dist_end, x3, y3, x3 + (y3 - y2), y3 - (x3 - x2));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
dv.idx = 3;
|
||||
|
||||
v = &m_src_vertices[0];
|
||||
x1 = v->x;
|
||||
y1 = v->y;
|
||||
lprev = v->len;
|
||||
|
||||
v = &m_src_vertices[1];
|
||||
x2 = v->x;
|
||||
y2 = v->y;
|
||||
dv.lcurr = v->len;
|
||||
line_parameters prev(x1, y1, x2, y2, lprev);
|
||||
|
||||
v = &m_src_vertices[2];
|
||||
dv.x1 = v->x;
|
||||
dv.y1 = v->y;
|
||||
dv.lnext = v->len;
|
||||
dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr);
|
||||
|
||||
v = &m_src_vertices[dv.idx];
|
||||
dv.x2 = v->x;
|
||||
dv.y2 = v->y;
|
||||
dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
|
||||
|
||||
dv.xb1 = 0;
|
||||
dv.yb1 = 0;
|
||||
dv.xb2 = 0;
|
||||
dv.yb2 = 0;
|
||||
|
||||
switch(m_line_join)
|
||||
{
|
||||
case outline_no_join:
|
||||
dv.flags = 3;
|
||||
break;
|
||||
|
||||
case outline_miter_join:
|
||||
case outline_round_join:
|
||||
dv.flags =
|
||||
(prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) |
|
||||
((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1);
|
||||
break;
|
||||
|
||||
case outline_miter_accurate_join:
|
||||
dv.flags = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if(m_round_cap)
|
||||
{
|
||||
m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
|
||||
}
|
||||
if((dv.flags & 1) == 0)
|
||||
{
|
||||
if(m_line_join == outline_round_join)
|
||||
{
|
||||
m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1),
|
||||
x2 + (y2 - y1), y2 - (x2 - x1));
|
||||
m_ren->pie(prev.x2, prev.y2,
|
||||
x2 + (y2 - y1), y2 - (x2 - x1),
|
||||
dv.curr.x1 + (dv.curr.y2 - dv.curr.y1),
|
||||
dv.curr.y1 - (dv.curr.x2 - dv.curr.x1));
|
||||
}
|
||||
else
|
||||
{
|
||||
bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
|
||||
m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1),
|
||||
dv.xb1, dv.yb1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ren->line1(prev,
|
||||
x1 + (y2 - y1),
|
||||
y1 - (x2 - x1));
|
||||
}
|
||||
if((dv.flags & 2) == 0 && m_line_join != outline_round_join)
|
||||
{
|
||||
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
|
||||
}
|
||||
|
||||
draw(dv, 1, m_src_vertices.size() - 2);
|
||||
|
||||
if((dv.flags & 1) == 0)
|
||||
{
|
||||
if(m_line_join == outline_round_join)
|
||||
{
|
||||
m_ren->line3(dv.curr,
|
||||
dv.curr.x1 + (dv.curr.y2 - dv.curr.y1),
|
||||
dv.curr.y1 - (dv.curr.x2 - dv.curr.x1),
|
||||
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
|
||||
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ren->line3(dv.curr, dv.xb1, dv.yb1,
|
||||
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
|
||||
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ren->line2(dv.curr,
|
||||
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
|
||||
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
|
||||
}
|
||||
if(m_round_cap)
|
||||
{
|
||||
m_ren->semidot(cmp_dist_end, dv.curr.x2, dv.curr.y2,
|
||||
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
|
||||
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_src_vertices.remove_all();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,520 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// The author 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.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for 32-bit screen coordinates has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RASTERIZER_SCANLINE_AA_INCLUDED
|
||||
#define AGG_RASTERIZER_SCANLINE_AA_INCLUDED
|
||||
|
||||
#include "agg_rasterizer_cells_aa.h"
|
||||
#include "agg_rasterizer_sl_clip.h"
|
||||
#include "agg_gamma_functions.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
|
||||
//-----------------------------------------------------------------cell_aa
|
||||
// A pixel cell. There're no constructors defined and it was done
|
||||
// intentionally in order to avoid extra overhead when allocating an
|
||||
// array of cells.
|
||||
struct cell_aa
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int cover;
|
||||
int area;
|
||||
|
||||
void initial()
|
||||
{
|
||||
x = 0x7FFFFFFF;
|
||||
y = 0x7FFFFFFF;
|
||||
cover = 0;
|
||||
area = 0;
|
||||
}
|
||||
|
||||
void style(const cell_aa&) {}
|
||||
|
||||
int not_equal(int ex, int ey, const cell_aa&) const
|
||||
{
|
||||
return (ex - x) | (ey - y);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//==================================================rasterizer_scanline_aa
|
||||
// Polygon rasterizer that is used to render filled polygons with
|
||||
// high-quality Anti-Aliasing. Internally, by default, the class uses
|
||||
// integer coordinates in format 24.8, i.e. 24 bits for integer part
|
||||
// and 8 bits for fractional - see poly_subpixel_shift. This class can be
|
||||
// used in the following way:
|
||||
//
|
||||
// 1. filling_rule(filling_rule_e ft) - optional.
|
||||
//
|
||||
// 2. gamma() - optional.
|
||||
//
|
||||
// 3. reset()
|
||||
//
|
||||
// 4. move_to(x, y) / line_to(x, y) - make the polygon. One can create
|
||||
// more than one contour, but each contour must consist of at least 3
|
||||
// vertices, i.e. move_to(x1, y1); line_to(x2, y2); line_to(x3, y3);
|
||||
// is the absolute minimum of vertices that define a triangle.
|
||||
// The algorithm does not check either the number of vertices nor
|
||||
// coincidence of their coordinates, but in the worst case it just
|
||||
// won't draw anything.
|
||||
// The orger of the vertices (clockwise or counterclockwise)
|
||||
// is important when using the non-zero filling rule (fill_non_zero).
|
||||
// In this case the vertex order of all the contours must be the same
|
||||
// if you want your intersecting polygons to be without "holes".
|
||||
// You actually can use different vertices order. If the contours do not
|
||||
// intersect each other the order is not important anyway. If they do,
|
||||
// contours with the same vertex order will be rendered without "holes"
|
||||
// while the intersecting contours with different orders will have "holes".
|
||||
//
|
||||
// filling_rule() and gamma() can be called anytime before "sweeping".
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip=rasterizer_sl_clip_int> class rasterizer_scanline_aa
|
||||
{
|
||||
enum status
|
||||
{
|
||||
status_initial,
|
||||
status_move_to,
|
||||
status_line_to,
|
||||
status_closed
|
||||
};
|
||||
|
||||
public:
|
||||
typedef Clip clip_type;
|
||||
typedef typename Clip::conv_type conv_type;
|
||||
typedef typename Clip::coord_type coord_type;
|
||||
|
||||
enum aa_scale_e
|
||||
{
|
||||
aa_shift = 8,
|
||||
aa_scale = 1 << aa_shift,
|
||||
aa_mask = aa_scale - 1,
|
||||
aa_scale2 = aa_scale * 2,
|
||||
aa_mask2 = aa_scale2 - 1
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rasterizer_scanline_aa() :
|
||||
m_outline(),
|
||||
m_clipper(),
|
||||
m_filling_rule(fill_non_zero),
|
||||
m_auto_close(true),
|
||||
m_start_x(0),
|
||||
m_start_y(0),
|
||||
m_status(status_initial)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < aa_scale; i++) m_gamma[i] = i;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaF>
|
||||
rasterizer_scanline_aa(const GammaF& gamma_function) :
|
||||
m_outline(),
|
||||
m_clipper(m_outline),
|
||||
m_filling_rule(fill_non_zero),
|
||||
m_auto_close(true),
|
||||
m_start_x(0),
|
||||
m_start_y(0),
|
||||
m_status(status_initial)
|
||||
{
|
||||
gamma(gamma_function);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset();
|
||||
void reset_clipping();
|
||||
void clip_box(double x1, double y1, double x2, double y2);
|
||||
void filling_rule(filling_rule_e filling_rule);
|
||||
void auto_close(bool flag) { m_auto_close = flag; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaF> void gamma(const GammaF& gamma_function)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < aa_scale; i++)
|
||||
{
|
||||
m_gamma[i] = uround(gamma_function(double(i) / aa_mask) * aa_mask);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned apply_gamma(unsigned cover) const
|
||||
{
|
||||
return m_gamma[cover];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void move_to(int x, int y);
|
||||
void line_to(int x, int y);
|
||||
void move_to_d(double x, double y);
|
||||
void line_to_d(double x, double y);
|
||||
void close_polygon();
|
||||
void add_vertex(double x, double y, unsigned cmd);
|
||||
|
||||
void edge(int x1, int y1, int x2, int y2);
|
||||
void edge_d(double x1, double y1, double x2, double y2);
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
template<class VertexSource>
|
||||
void add_path(VertexSource& vs, unsigned path_id=0)
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
|
||||
unsigned cmd;
|
||||
vs.rewind(path_id);
|
||||
if(m_outline.sorted()) reset();
|
||||
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||
{
|
||||
add_vertex(x, y, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int min_x() const { return m_outline.min_x(); }
|
||||
int min_y() const { return m_outline.min_y(); }
|
||||
int max_x() const { return m_outline.max_x(); }
|
||||
int max_y() const { return m_outline.max_y(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void sort();
|
||||
bool rewind_scanlines();
|
||||
bool navigate_scanline(int y);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE unsigned calculate_alpha(int area) const
|
||||
{
|
||||
int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift);
|
||||
|
||||
if(cover < 0) cover = -cover;
|
||||
if(m_filling_rule == fill_even_odd)
|
||||
{
|
||||
cover &= aa_mask2;
|
||||
if(cover > aa_scale)
|
||||
{
|
||||
cover = aa_scale2 - cover;
|
||||
}
|
||||
}
|
||||
if(cover > aa_mask) cover = aa_mask;
|
||||
return m_gamma[cover];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Scanline> bool sweep_scanline(Scanline& sl)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
if(m_scan_y > m_outline.max_y()) return false;
|
||||
sl.reset_spans();
|
||||
unsigned num_cells = m_outline.scanline_num_cells(m_scan_y);
|
||||
const cell_aa* const* cells = m_outline.scanline_cells(m_scan_y);
|
||||
int cover = 0;
|
||||
|
||||
while(num_cells)
|
||||
{
|
||||
const cell_aa* cur_cell = *cells;
|
||||
int x = cur_cell->x;
|
||||
int area = cur_cell->area;
|
||||
unsigned alpha;
|
||||
|
||||
cover += cur_cell->cover;
|
||||
|
||||
//accumulate all cells with the same X
|
||||
while(--num_cells)
|
||||
{
|
||||
cur_cell = *++cells;
|
||||
if(cur_cell->x != x) break;
|
||||
area += cur_cell->area;
|
||||
cover += cur_cell->cover;
|
||||
}
|
||||
|
||||
if(area)
|
||||
{
|
||||
alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area);
|
||||
if(alpha)
|
||||
{
|
||||
sl.add_cell(x, alpha);
|
||||
}
|
||||
x++;
|
||||
}
|
||||
|
||||
if(num_cells && cur_cell->x > x)
|
||||
{
|
||||
alpha = calculate_alpha(cover << (poly_subpixel_shift + 1));
|
||||
if(alpha)
|
||||
{
|
||||
sl.add_span(x, cur_cell->x - x, alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(sl.num_spans()) break;
|
||||
++m_scan_y;
|
||||
}
|
||||
|
||||
sl.finalize(m_scan_y);
|
||||
++m_scan_y;
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
bool hit_test(int tx, int ty);
|
||||
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
// Disable copying
|
||||
rasterizer_scanline_aa(const rasterizer_scanline_aa<Clip>&);
|
||||
const rasterizer_scanline_aa<Clip>&
|
||||
operator = (const rasterizer_scanline_aa<Clip>&);
|
||||
|
||||
private:
|
||||
rasterizer_cells_aa<cell_aa> m_outline;
|
||||
clip_type m_clipper;
|
||||
int m_gamma[aa_scale];
|
||||
filling_rule_e m_filling_rule;
|
||||
bool m_auto_close;
|
||||
coord_type m_start_x;
|
||||
coord_type m_start_y;
|
||||
unsigned m_status;
|
||||
int m_scan_y;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::reset()
|
||||
{
|
||||
m_outline.reset();
|
||||
m_status = status_initial;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::filling_rule(filling_rule_e filling_rule)
|
||||
{
|
||||
m_filling_rule = filling_rule;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::clip_box(double x1, double y1,
|
||||
double x2, double y2)
|
||||
{
|
||||
reset();
|
||||
m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1),
|
||||
conv_type::upscale(x2), conv_type::upscale(y2));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::reset_clipping()
|
||||
{
|
||||
reset();
|
||||
m_clipper.reset_clipping();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::close_polygon()
|
||||
{
|
||||
if(m_status == status_line_to)
|
||||
{
|
||||
m_clipper.line_to(m_outline, m_start_x, m_start_y);
|
||||
m_status = status_closed;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::move_to(int x, int y)
|
||||
{
|
||||
if(m_outline.sorted()) reset();
|
||||
if(m_auto_close) close_polygon();
|
||||
m_clipper.move_to(m_start_x = conv_type::downscale(x),
|
||||
m_start_y = conv_type::downscale(y));
|
||||
m_status = status_move_to;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::line_to(int x, int y)
|
||||
{
|
||||
m_clipper.line_to(m_outline,
|
||||
conv_type::downscale(x),
|
||||
conv_type::downscale(y));
|
||||
m_status = status_line_to;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::move_to_d(double x, double y)
|
||||
{
|
||||
if(m_outline.sorted()) reset();
|
||||
if(m_auto_close) close_polygon();
|
||||
m_clipper.move_to(m_start_x = conv_type::upscale(x),
|
||||
m_start_y = conv_type::upscale(y));
|
||||
m_status = status_move_to;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::line_to_d(double x, double y)
|
||||
{
|
||||
m_clipper.line_to(m_outline,
|
||||
conv_type::upscale(x),
|
||||
conv_type::upscale(y));
|
||||
m_status = status_line_to;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::add_vertex(double x, double y, unsigned cmd)
|
||||
{
|
||||
if(is_move_to(cmd))
|
||||
{
|
||||
move_to_d(x, y);
|
||||
}
|
||||
else
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
line_to_d(x, y);
|
||||
}
|
||||
else
|
||||
if(is_close(cmd))
|
||||
{
|
||||
close_polygon();
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::edge(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
if(m_outline.sorted()) reset();
|
||||
m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1));
|
||||
m_clipper.line_to(m_outline,
|
||||
conv_type::downscale(x2),
|
||||
conv_type::downscale(y2));
|
||||
m_status = status_move_to;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::edge_d(double x1, double y1,
|
||||
double x2, double y2)
|
||||
{
|
||||
if(m_outline.sorted()) reset();
|
||||
m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1));
|
||||
m_clipper.line_to(m_outline,
|
||||
conv_type::upscale(x2),
|
||||
conv_type::upscale(y2));
|
||||
m_status = status_move_to;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa<Clip>::sort()
|
||||
{
|
||||
if(m_auto_close) close_polygon();
|
||||
m_outline.sort_cells();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
AGG_INLINE bool rasterizer_scanline_aa<Clip>::rewind_scanlines()
|
||||
{
|
||||
if(m_auto_close) close_polygon();
|
||||
m_outline.sort_cells();
|
||||
if(m_outline.total_cells() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_scan_y = m_outline.min_y();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
AGG_INLINE bool rasterizer_scanline_aa<Clip>::navigate_scanline(int y)
|
||||
{
|
||||
if(m_auto_close) close_polygon();
|
||||
m_outline.sort_cells();
|
||||
if(m_outline.total_cells() == 0 ||
|
||||
y < m_outline.min_y() ||
|
||||
y > m_outline.max_y())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_scan_y = y;
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
bool rasterizer_scanline_aa<Clip>::hit_test(int tx, int ty)
|
||||
{
|
||||
if(!navigate_scanline(ty)) return false;
|
||||
scanline_hit_test sl(tx);
|
||||
sweep_scanline(sl);
|
||||
return sl.hit();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,361 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RASTERIZER_SL_CLIP_INCLUDED
|
||||
#define AGG_RASTERIZER_SL_CLIP_INCLUDED
|
||||
|
||||
#include "agg_clip_liang_barsky.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//--------------------------------------------------------poly_max_coord_e
|
||||
enum poly_max_coord_e
|
||||
{
|
||||
poly_max_coord = (1 << 30) - 1 //----poly_max_coord
|
||||
};
|
||||
|
||||
//------------------------------------------------------------ras_conv_int
|
||||
struct ras_conv_int
|
||||
{
|
||||
typedef int coord_type;
|
||||
static AGG_INLINE int mul_div(double a, double b, double c)
|
||||
{
|
||||
return iround(a * b / c);
|
||||
}
|
||||
static int xi(int v) { return v; }
|
||||
static int yi(int v) { return v; }
|
||||
static int upscale(double v) { return iround(v * poly_subpixel_scale); }
|
||||
static int downscale(int v) { return v; }
|
||||
};
|
||||
|
||||
//--------------------------------------------------------ras_conv_int_sat
|
||||
struct ras_conv_int_sat
|
||||
{
|
||||
typedef int coord_type;
|
||||
static AGG_INLINE int mul_div(double a, double b, double c)
|
||||
{
|
||||
return saturation<poly_max_coord>::iround(a * b / c);
|
||||
}
|
||||
static int xi(int v) { return v; }
|
||||
static int yi(int v) { return v; }
|
||||
static int upscale(double v)
|
||||
{
|
||||
return saturation<poly_max_coord>::iround(v * poly_subpixel_scale);
|
||||
}
|
||||
static int downscale(int v) { return v; }
|
||||
};
|
||||
|
||||
//---------------------------------------------------------ras_conv_int_3x
|
||||
struct ras_conv_int_3x
|
||||
{
|
||||
typedef int coord_type;
|
||||
static AGG_INLINE int mul_div(double a, double b, double c)
|
||||
{
|
||||
return iround(a * b / c);
|
||||
}
|
||||
static int xi(int v) { return v * 3; }
|
||||
static int yi(int v) { return v; }
|
||||
static int upscale(double v) { return iround(v * poly_subpixel_scale); }
|
||||
static int downscale(int v) { return v; }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------ras_conv_dbl
|
||||
struct ras_conv_dbl
|
||||
{
|
||||
typedef double coord_type;
|
||||
static AGG_INLINE double mul_div(double a, double b, double c)
|
||||
{
|
||||
return a * b / c;
|
||||
}
|
||||
static int xi(double v) { return iround(v * poly_subpixel_scale); }
|
||||
static int yi(double v) { return iround(v * poly_subpixel_scale); }
|
||||
static double upscale(double v) { return v; }
|
||||
static double downscale(int v) { return v / double(poly_subpixel_scale); }
|
||||
};
|
||||
|
||||
//--------------------------------------------------------ras_conv_dbl_3x
|
||||
struct ras_conv_dbl_3x
|
||||
{
|
||||
typedef double coord_type;
|
||||
static AGG_INLINE double mul_div(double a, double b, double c)
|
||||
{
|
||||
return a * b / c;
|
||||
}
|
||||
static int xi(double v) { return iround(v * poly_subpixel_scale * 3); }
|
||||
static int yi(double v) { return iround(v * poly_subpixel_scale); }
|
||||
static double upscale(double v) { return v; }
|
||||
static double downscale(int v) { return v / double(poly_subpixel_scale); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------rasterizer_sl_clip
|
||||
template<class Conv> class rasterizer_sl_clip
|
||||
{
|
||||
public:
|
||||
typedef Conv conv_type;
|
||||
typedef typename Conv::coord_type coord_type;
|
||||
typedef rect_base<coord_type> rect_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rasterizer_sl_clip() :
|
||||
m_clip_box(0,0,0,0),
|
||||
m_x1(0),
|
||||
m_y1(0),
|
||||
m_f1(0),
|
||||
m_clipping(false)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset_clipping()
|
||||
{
|
||||
m_clipping = false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clip_box(coord_type x1, coord_type y1, coord_type x2, coord_type y2)
|
||||
{
|
||||
m_clip_box = rect_type(x1, y1, x2, y2);
|
||||
m_clip_box.normalize();
|
||||
m_clipping = true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void move_to(coord_type x1, coord_type y1)
|
||||
{
|
||||
m_x1 = x1;
|
||||
m_y1 = y1;
|
||||
if(m_clipping) m_f1 = clipping_flags(x1, y1, m_clip_box);
|
||||
}
|
||||
|
||||
private:
|
||||
//------------------------------------------------------------------------
|
||||
template<class Rasterizer>
|
||||
AGG_INLINE void line_clip_y(Rasterizer& ras,
|
||||
coord_type x1, coord_type y1,
|
||||
coord_type x2, coord_type y2,
|
||||
unsigned f1, unsigned f2) const
|
||||
{
|
||||
f1 &= 10;
|
||||
f2 &= 10;
|
||||
if((f1 | f2) == 0)
|
||||
{
|
||||
// Fully visible
|
||||
ras.line(Conv::xi(x1), Conv::yi(y1), Conv::xi(x2), Conv::yi(y2));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(f1 == f2)
|
||||
{
|
||||
// Invisible by Y
|
||||
return;
|
||||
}
|
||||
|
||||
coord_type tx1 = x1;
|
||||
coord_type ty1 = y1;
|
||||
coord_type tx2 = x2;
|
||||
coord_type ty2 = y2;
|
||||
|
||||
if(f1 & 8) // y1 < clip.y1
|
||||
{
|
||||
tx1 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1);
|
||||
ty1 = m_clip_box.y1;
|
||||
}
|
||||
|
||||
if(f1 & 2) // y1 > clip.y2
|
||||
{
|
||||
tx1 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1);
|
||||
ty1 = m_clip_box.y2;
|
||||
}
|
||||
|
||||
if(f2 & 8) // y2 < clip.y1
|
||||
{
|
||||
tx2 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1);
|
||||
ty2 = m_clip_box.y1;
|
||||
}
|
||||
|
||||
if(f2 & 2) // y2 > clip.y2
|
||||
{
|
||||
tx2 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1);
|
||||
ty2 = m_clip_box.y2;
|
||||
}
|
||||
ras.line(Conv::xi(tx1), Conv::yi(ty1),
|
||||
Conv::xi(tx2), Conv::yi(ty2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
template<class Rasterizer>
|
||||
void line_to(Rasterizer& ras, coord_type x2, coord_type y2)
|
||||
{
|
||||
if(m_clipping)
|
||||
{
|
||||
unsigned f2 = clipping_flags(x2, y2, m_clip_box);
|
||||
|
||||
if((m_f1 & 10) == (f2 & 10) && (m_f1 & 10) != 0)
|
||||
{
|
||||
// Invisible by Y
|
||||
m_x1 = x2;
|
||||
m_y1 = y2;
|
||||
m_f1 = f2;
|
||||
return;
|
||||
}
|
||||
|
||||
coord_type x1 = m_x1;
|
||||
coord_type y1 = m_y1;
|
||||
unsigned f1 = m_f1;
|
||||
coord_type y3, y4;
|
||||
unsigned f3, f4;
|
||||
|
||||
switch(((f1 & 5) << 1) | (f2 & 5))
|
||||
{
|
||||
case 0: // Visible by X
|
||||
line_clip_y(ras, x1, y1, x2, y2, f1, f2);
|
||||
break;
|
||||
|
||||
case 1: // x2 > clip.x2
|
||||
y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1);
|
||||
f3 = clipping_flags_y(y3, m_clip_box);
|
||||
line_clip_y(ras, x1, y1, m_clip_box.x2, y3, f1, f3);
|
||||
line_clip_y(ras, m_clip_box.x2, y3, m_clip_box.x2, y2, f3, f2);
|
||||
break;
|
||||
|
||||
case 2: // x1 > clip.x2
|
||||
y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1);
|
||||
f3 = clipping_flags_y(y3, m_clip_box);
|
||||
line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y3, f1, f3);
|
||||
line_clip_y(ras, m_clip_box.x2, y3, x2, y2, f3, f2);
|
||||
break;
|
||||
|
||||
case 3: // x1 > clip.x2 && x2 > clip.x2
|
||||
line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y2, f1, f2);
|
||||
break;
|
||||
|
||||
case 4: // x2 < clip.x1
|
||||
y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1);
|
||||
f3 = clipping_flags_y(y3, m_clip_box);
|
||||
line_clip_y(ras, x1, y1, m_clip_box.x1, y3, f1, f3);
|
||||
line_clip_y(ras, m_clip_box.x1, y3, m_clip_box.x1, y2, f3, f2);
|
||||
break;
|
||||
|
||||
case 6: // x1 > clip.x2 && x2 < clip.x1
|
||||
y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1);
|
||||
y4 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1);
|
||||
f3 = clipping_flags_y(y3, m_clip_box);
|
||||
f4 = clipping_flags_y(y4, m_clip_box);
|
||||
line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y3, f1, f3);
|
||||
line_clip_y(ras, m_clip_box.x2, y3, m_clip_box.x1, y4, f3, f4);
|
||||
line_clip_y(ras, m_clip_box.x1, y4, m_clip_box.x1, y2, f4, f2);
|
||||
break;
|
||||
|
||||
case 8: // x1 < clip.x1
|
||||
y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1);
|
||||
f3 = clipping_flags_y(y3, m_clip_box);
|
||||
line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y3, f1, f3);
|
||||
line_clip_y(ras, m_clip_box.x1, y3, x2, y2, f3, f2);
|
||||
break;
|
||||
|
||||
case 9: // x1 < clip.x1 && x2 > clip.x2
|
||||
y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1);
|
||||
y4 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1);
|
||||
f3 = clipping_flags_y(y3, m_clip_box);
|
||||
f4 = clipping_flags_y(y4, m_clip_box);
|
||||
line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y3, f1, f3);
|
||||
line_clip_y(ras, m_clip_box.x1, y3, m_clip_box.x2, y4, f3, f4);
|
||||
line_clip_y(ras, m_clip_box.x2, y4, m_clip_box.x2, y2, f4, f2);
|
||||
break;
|
||||
|
||||
case 12: // x1 < clip.x1 && x2 < clip.x1
|
||||
line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y2, f1, f2);
|
||||
break;
|
||||
}
|
||||
m_f1 = f2;
|
||||
}
|
||||
else
|
||||
{
|
||||
ras.line(Conv::xi(m_x1), Conv::yi(m_y1),
|
||||
Conv::xi(x2), Conv::yi(y2));
|
||||
}
|
||||
m_x1 = x2;
|
||||
m_y1 = y2;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
rect_type m_clip_box;
|
||||
coord_type m_x1;
|
||||
coord_type m_y1;
|
||||
unsigned m_f1;
|
||||
bool m_clipping;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------rasterizer_sl_no_clip
|
||||
class rasterizer_sl_no_clip
|
||||
{
|
||||
public:
|
||||
typedef ras_conv_int conv_type;
|
||||
typedef int coord_type;
|
||||
|
||||
rasterizer_sl_no_clip() : m_x1(0), m_y1(0) {}
|
||||
|
||||
void reset_clipping() {}
|
||||
void clip_box(coord_type x1, coord_type y1, coord_type x2, coord_type y2) {}
|
||||
void move_to(coord_type x1, coord_type y1) { m_x1 = x1; m_y1 = y1; }
|
||||
|
||||
template<class Rasterizer>
|
||||
void line_to(Rasterizer& ras, coord_type x2, coord_type y2)
|
||||
{
|
||||
ras.line(m_x1, m_y1, x2, y2);
|
||||
m_x1 = x2;
|
||||
m_y1 = y2;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_x1, m_y1;
|
||||
};
|
||||
|
||||
|
||||
// -----rasterizer_sl_clip_int
|
||||
// -----rasterizer_sl_clip_int_sat
|
||||
// -----rasterizer_sl_clip_int_3x
|
||||
// -----rasterizer_sl_clip_dbl
|
||||
// -----rasterizer_sl_clip_dbl_3x
|
||||
//------------------------------------------------------------------------
|
||||
typedef rasterizer_sl_clip<ras_conv_int> rasterizer_sl_clip_int;
|
||||
typedef rasterizer_sl_clip<ras_conv_int_sat> rasterizer_sl_clip_int_sat;
|
||||
typedef rasterizer_sl_clip<ras_conv_int_3x> rasterizer_sl_clip_int_3x;
|
||||
typedef rasterizer_sl_clip<ras_conv_dbl> rasterizer_sl_clip_dbl;
|
||||
typedef rasterizer_sl_clip<ras_conv_dbl_3x> rasterizer_sl_clip_dbl_3x;
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,723 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RENDERER_BASE_INCLUDED
|
||||
#define AGG_RENDERER_BASE_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_rendering_buffer.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-----------------------------------------------------------renderer_base
|
||||
template<class PixelFormat> class renderer_base
|
||||
{
|
||||
public:
|
||||
typedef PixelFormat pixfmt_type;
|
||||
typedef typename pixfmt_type::color_type color_type;
|
||||
typedef typename pixfmt_type::row_data row_data;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_base() : m_ren(0), m_clip_box(1, 1, 0, 0) {}
|
||||
explicit renderer_base(pixfmt_type& ren) :
|
||||
m_ren(&ren),
|
||||
m_clip_box(0, 0, ren.width() - 1, ren.height() - 1)
|
||||
{}
|
||||
void attach(pixfmt_type& ren)
|
||||
{
|
||||
m_ren = &ren;
|
||||
m_clip_box = rect_i(0, 0, ren.width() - 1, ren.height() - 1);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const pixfmt_type& ren() const { return *m_ren; }
|
||||
pixfmt_type& ren() { return *m_ren; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned width() const { return m_ren->width(); }
|
||||
unsigned height() const { return m_ren->height(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
bool clip_box(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
rect_i cb(x1, y1, x2, y2);
|
||||
cb.normalize();
|
||||
if(cb.clip(rect_i(0, 0, width() - 1, height() - 1)))
|
||||
{
|
||||
m_clip_box = cb;
|
||||
return true;
|
||||
}
|
||||
m_clip_box.x1 = 1;
|
||||
m_clip_box.y1 = 1;
|
||||
m_clip_box.x2 = 0;
|
||||
m_clip_box.y2 = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset_clipping(bool visibility)
|
||||
{
|
||||
if(visibility)
|
||||
{
|
||||
m_clip_box.x1 = 0;
|
||||
m_clip_box.y1 = 0;
|
||||
m_clip_box.x2 = width() - 1;
|
||||
m_clip_box.y2 = height() - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_clip_box.x1 = 1;
|
||||
m_clip_box.y1 = 1;
|
||||
m_clip_box.x2 = 0;
|
||||
m_clip_box.y2 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clip_box_naked(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
m_clip_box.x1 = x1;
|
||||
m_clip_box.y1 = y1;
|
||||
m_clip_box.x2 = x2;
|
||||
m_clip_box.y2 = y2;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
bool inbox(int x, int y) const
|
||||
{
|
||||
return x >= m_clip_box.x1 && y >= m_clip_box.y1 &&
|
||||
x <= m_clip_box.x2 && y <= m_clip_box.y2;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const rect_i& clip_box() const { return m_clip_box; }
|
||||
int xmin() const { return m_clip_box.x1; }
|
||||
int ymin() const { return m_clip_box.y1; }
|
||||
int xmax() const { return m_clip_box.x2; }
|
||||
int ymax() const { return m_clip_box.y2; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const rect_i& bounding_clip_box() const { return m_clip_box; }
|
||||
int bounding_xmin() const { return m_clip_box.x1; }
|
||||
int bounding_ymin() const { return m_clip_box.y1; }
|
||||
int bounding_xmax() const { return m_clip_box.x2; }
|
||||
int bounding_ymax() const { return m_clip_box.y2; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clear(const color_type& c)
|
||||
{
|
||||
unsigned y;
|
||||
if(width())
|
||||
{
|
||||
for(y = 0; y < height(); y++)
|
||||
{
|
||||
m_ren->copy_hline(0, y, width(), c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
if(inbox(x, y))
|
||||
{
|
||||
m_ren->copy_pixel(x, y, c);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_pixel(int x, int y, const color_type& c, cover_type cover)
|
||||
{
|
||||
if(inbox(x, y))
|
||||
{
|
||||
m_ren->blend_pixel(x, y, c, cover);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
color_type pixel(int x, int y) const
|
||||
{
|
||||
return inbox(x, y) ?
|
||||
m_ren->pixel(x, y) :
|
||||
color_type::no_color();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_hline(int x1, int y, int x2, const color_type& c)
|
||||
{
|
||||
if(x1 > x2) { int t = x2; x2 = x1; x1 = t; }
|
||||
if(y > ymax()) return;
|
||||
if(y < ymin()) return;
|
||||
if(x1 > xmax()) return;
|
||||
if(x2 < xmin()) return;
|
||||
|
||||
if(x1 < xmin()) x1 = xmin();
|
||||
if(x2 > xmax()) x2 = xmax();
|
||||
|
||||
m_ren->copy_hline(x1, y, x2 - x1 + 1, c);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_vline(int x, int y1, int y2, const color_type& c)
|
||||
{
|
||||
if(y1 > y2) { int t = y2; y2 = y1; y1 = t; }
|
||||
if(x > xmax()) return;
|
||||
if(x < xmin()) return;
|
||||
if(y1 > ymax()) return;
|
||||
if(y2 < ymin()) return;
|
||||
|
||||
if(y1 < ymin()) y1 = ymin();
|
||||
if(y2 > ymax()) y2 = ymax();
|
||||
|
||||
m_ren->copy_vline(x, y1, y2 - y1 + 1, c);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_hline(int x1, int y, int x2,
|
||||
const color_type& c, cover_type cover)
|
||||
{
|
||||
if(x1 > x2) { int t = x2; x2 = x1; x1 = t; }
|
||||
if(y > ymax()) return;
|
||||
if(y < ymin()) return;
|
||||
if(x1 > xmax()) return;
|
||||
if(x2 < xmin()) return;
|
||||
|
||||
if(x1 < xmin()) x1 = xmin();
|
||||
if(x2 > xmax()) x2 = xmax();
|
||||
|
||||
m_ren->blend_hline(x1, y, x2 - x1 + 1, c, cover);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_vline(int x, int y1, int y2,
|
||||
const color_type& c, cover_type cover)
|
||||
{
|
||||
if(y1 > y2) { int t = y2; y2 = y1; y1 = t; }
|
||||
if(x > xmax()) return;
|
||||
if(x < xmin()) return;
|
||||
if(y1 > ymax()) return;
|
||||
if(y2 < ymin()) return;
|
||||
|
||||
if(y1 < ymin()) y1 = ymin();
|
||||
if(y2 > ymax()) y2 = ymax();
|
||||
|
||||
m_ren->blend_vline(x, y1, y2 - y1 + 1, c, cover);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_bar(int x1, int y1, int x2, int y2, const color_type& c)
|
||||
{
|
||||
rect_i rc(x1, y1, x2, y2);
|
||||
rc.normalize();
|
||||
if(rc.clip(clip_box()))
|
||||
{
|
||||
int y;
|
||||
for(y = rc.y1; y <= rc.y2; y++)
|
||||
{
|
||||
m_ren->copy_hline(rc.x1, y, unsigned(rc.x2 - rc.x1 + 1), c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_bar(int x1, int y1, int x2, int y2,
|
||||
const color_type& c, cover_type cover)
|
||||
{
|
||||
rect_i rc(x1, y1, x2, y2);
|
||||
rc.normalize();
|
||||
if(rc.clip(clip_box()))
|
||||
{
|
||||
int y;
|
||||
for(y = rc.y1; y <= rc.y2; y++)
|
||||
{
|
||||
m_ren->blend_hline(rc.x1,
|
||||
y,
|
||||
unsigned(rc.x2 - rc.x1 + 1),
|
||||
c,
|
||||
cover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_hspan(int x, int y, int len,
|
||||
const color_type& c,
|
||||
const cover_type* covers)
|
||||
{
|
||||
if(y > ymax()) return;
|
||||
if(y < ymin()) return;
|
||||
|
||||
if(x < xmin())
|
||||
{
|
||||
len -= xmin() - x;
|
||||
if(len <= 0) return;
|
||||
covers += xmin() - x;
|
||||
x = xmin();
|
||||
}
|
||||
if(x + len > xmax())
|
||||
{
|
||||
len = xmax() - x + 1;
|
||||
if(len <= 0) return;
|
||||
}
|
||||
m_ren->blend_solid_hspan(x, y, len, c, covers);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_vspan(int x, int y, int len,
|
||||
const color_type& c,
|
||||
const cover_type* covers)
|
||||
{
|
||||
if(x > xmax()) return;
|
||||
if(x < xmin()) return;
|
||||
|
||||
if(y < ymin())
|
||||
{
|
||||
len -= ymin() - y;
|
||||
if(len <= 0) return;
|
||||
covers += ymin() - y;
|
||||
y = ymin();
|
||||
}
|
||||
if(y + len > ymax())
|
||||
{
|
||||
len = ymax() - y + 1;
|
||||
if(len <= 0) return;
|
||||
}
|
||||
m_ren->blend_solid_vspan(x, y, len, c, covers);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_color_hspan(int x, int y, int len, const color_type* colors)
|
||||
{
|
||||
if(y > ymax()) return;
|
||||
if(y < ymin()) return;
|
||||
|
||||
if(x < xmin())
|
||||
{
|
||||
int d = xmin() - x;
|
||||
len -= d;
|
||||
if(len <= 0) return;
|
||||
colors += d;
|
||||
x = xmin();
|
||||
}
|
||||
if(x + len > xmax())
|
||||
{
|
||||
len = xmax() - x + 1;
|
||||
if(len <= 0) return;
|
||||
}
|
||||
m_ren->copy_color_hspan(x, y, len, colors);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_color_vspan(int x, int y, int len, const color_type* colors)
|
||||
{
|
||||
if(x > xmax()) return;
|
||||
if(x < xmin()) return;
|
||||
|
||||
if(y < ymin())
|
||||
{
|
||||
int d = ymin() - y;
|
||||
len -= d;
|
||||
if(len <= 0) return;
|
||||
colors += d;
|
||||
y = ymin();
|
||||
}
|
||||
if(y + len > ymax())
|
||||
{
|
||||
len = ymax() - y + 1;
|
||||
if(len <= 0) return;
|
||||
}
|
||||
m_ren->copy_color_vspan(x, y, len, colors);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_hspan(int x, int y, int len,
|
||||
const color_type* colors,
|
||||
const cover_type* covers,
|
||||
cover_type cover = agg::cover_full)
|
||||
{
|
||||
if(y > ymax()) return;
|
||||
if(y < ymin()) return;
|
||||
|
||||
if(x < xmin())
|
||||
{
|
||||
int d = xmin() - x;
|
||||
len -= d;
|
||||
if(len <= 0) return;
|
||||
if(covers) covers += d;
|
||||
colors += d;
|
||||
x = xmin();
|
||||
}
|
||||
if(x + len > xmax())
|
||||
{
|
||||
len = xmax() - x + 1;
|
||||
if(len <= 0) return;
|
||||
}
|
||||
m_ren->blend_color_hspan(x, y, len, colors, covers, cover);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_vspan(int x, int y, int len,
|
||||
const color_type* colors,
|
||||
const cover_type* covers,
|
||||
cover_type cover = agg::cover_full)
|
||||
{
|
||||
if(x > xmax()) return;
|
||||
if(x < xmin()) return;
|
||||
|
||||
if(y < ymin())
|
||||
{
|
||||
int d = ymin() - y;
|
||||
len -= d;
|
||||
if(len <= 0) return;
|
||||
if(covers) covers += d;
|
||||
colors += d;
|
||||
y = ymin();
|
||||
}
|
||||
if(y + len > ymax())
|
||||
{
|
||||
len = ymax() - y + 1;
|
||||
if(len <= 0) return;
|
||||
}
|
||||
m_ren->blend_color_vspan(x, y, len, colors, covers, cover);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rect_i clip_rect_area(rect_i& dst, rect_i& src, int wsrc, int hsrc) const
|
||||
{
|
||||
rect_i rc(0,0,0,0);
|
||||
rect_i cb = clip_box();
|
||||
++cb.x2;
|
||||
++cb.y2;
|
||||
|
||||
if(src.x1 < 0)
|
||||
{
|
||||
dst.x1 -= src.x1;
|
||||
src.x1 = 0;
|
||||
}
|
||||
if(src.y1 < 0)
|
||||
{
|
||||
dst.y1 -= src.y1;
|
||||
src.y1 = 0;
|
||||
}
|
||||
|
||||
if(src.x2 > wsrc) src.x2 = wsrc;
|
||||
if(src.y2 > hsrc) src.y2 = hsrc;
|
||||
|
||||
if(dst.x1 < cb.x1)
|
||||
{
|
||||
src.x1 += cb.x1 - dst.x1;
|
||||
dst.x1 = cb.x1;
|
||||
}
|
||||
if(dst.y1 < cb.y1)
|
||||
{
|
||||
src.y1 += cb.y1 - dst.y1;
|
||||
dst.y1 = cb.y1;
|
||||
}
|
||||
|
||||
if(dst.x2 > cb.x2) dst.x2 = cb.x2;
|
||||
if(dst.y2 > cb.y2) dst.y2 = cb.y2;
|
||||
|
||||
rc.x2 = dst.x2 - dst.x1;
|
||||
rc.y2 = dst.y2 - dst.y1;
|
||||
|
||||
if(rc.x2 > src.x2 - src.x1) rc.x2 = src.x2 - src.x1;
|
||||
if(rc.y2 > src.y2 - src.y1) rc.y2 = src.y2 - src.y1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class RenBuf>
|
||||
void copy_from(const RenBuf& src,
|
||||
const rect_i* rect_src_ptr = 0,
|
||||
int dx = 0,
|
||||
int dy = 0)
|
||||
{
|
||||
rect_i rsrc(0, 0, src.width(), src.height());
|
||||
if(rect_src_ptr)
|
||||
{
|
||||
rsrc.x1 = rect_src_ptr->x1;
|
||||
rsrc.y1 = rect_src_ptr->y1;
|
||||
rsrc.x2 = rect_src_ptr->x2 + 1;
|
||||
rsrc.y2 = rect_src_ptr->y2 + 1;
|
||||
}
|
||||
|
||||
// Version with xdst, ydst (absolute positioning)
|
||||
//rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1);
|
||||
|
||||
// Version with dx, dy (relative positioning)
|
||||
rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy);
|
||||
|
||||
rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height());
|
||||
|
||||
if(rc.x2 > 0)
|
||||
{
|
||||
int incy = 1;
|
||||
if(rdst.y1 > rsrc.y1)
|
||||
{
|
||||
rsrc.y1 += rc.y2 - 1;
|
||||
rdst.y1 += rc.y2 - 1;
|
||||
incy = -1;
|
||||
}
|
||||
while(rc.y2 > 0)
|
||||
{
|
||||
m_ren->copy_from(src,
|
||||
rdst.x1, rdst.y1,
|
||||
rsrc.x1, rsrc.y1,
|
||||
rc.x2);
|
||||
rdst.y1 += incy;
|
||||
rsrc.y1 += incy;
|
||||
--rc.y2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from(const SrcPixelFormatRenderer& src,
|
||||
const rect_i* rect_src_ptr = 0,
|
||||
int dx = 0,
|
||||
int dy = 0,
|
||||
cover_type cover = agg::cover_full)
|
||||
{
|
||||
rect_i rsrc(0, 0, src.width(), src.height());
|
||||
if(rect_src_ptr)
|
||||
{
|
||||
rsrc.x1 = rect_src_ptr->x1;
|
||||
rsrc.y1 = rect_src_ptr->y1;
|
||||
rsrc.x2 = rect_src_ptr->x2 + 1;
|
||||
rsrc.y2 = rect_src_ptr->y2 + 1;
|
||||
}
|
||||
|
||||
// Version with xdst, ydst (absolute positioning)
|
||||
//rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1);
|
||||
|
||||
// Version with dx, dy (relative positioning)
|
||||
rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy);
|
||||
rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height());
|
||||
|
||||
if(rc.x2 > 0)
|
||||
{
|
||||
int incy = 1;
|
||||
if(rdst.y1 > rsrc.y1)
|
||||
{
|
||||
rsrc.y1 += rc.y2 - 1;
|
||||
rdst.y1 += rc.y2 - 1;
|
||||
incy = -1;
|
||||
}
|
||||
while(rc.y2 > 0)
|
||||
{
|
||||
typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1);
|
||||
if(rw.ptr)
|
||||
{
|
||||
int x1src = rsrc.x1;
|
||||
int x1dst = rdst.x1;
|
||||
int len = rc.x2;
|
||||
if(rw.x1 > x1src)
|
||||
{
|
||||
x1dst += rw.x1 - x1src;
|
||||
len -= rw.x1 - x1src;
|
||||
x1src = rw.x1;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
if(x1src + len-1 > rw.x2)
|
||||
{
|
||||
len -= x1src + len - rw.x2 - 1;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
m_ren->blend_from(src,
|
||||
x1dst, rdst.y1,
|
||||
x1src, rsrc.y1,
|
||||
len,
|
||||
cover);
|
||||
}
|
||||
}
|
||||
}
|
||||
rdst.y1 += incy;
|
||||
rsrc.y1 += incy;
|
||||
--rc.y2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from_color(const SrcPixelFormatRenderer& src,
|
||||
const color_type& color,
|
||||
const rect_i* rect_src_ptr = 0,
|
||||
int dx = 0,
|
||||
int dy = 0,
|
||||
cover_type cover = agg::cover_full)
|
||||
{
|
||||
rect_i rsrc(0, 0, src.width(), src.height());
|
||||
if(rect_src_ptr)
|
||||
{
|
||||
rsrc.x1 = rect_src_ptr->x1;
|
||||
rsrc.y1 = rect_src_ptr->y1;
|
||||
rsrc.x2 = rect_src_ptr->x2 + 1;
|
||||
rsrc.y2 = rect_src_ptr->y2 + 1;
|
||||
}
|
||||
|
||||
// Version with xdst, ydst (absolute positioning)
|
||||
//rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1);
|
||||
|
||||
// Version with dx, dy (relative positioning)
|
||||
rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy);
|
||||
rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height());
|
||||
|
||||
if(rc.x2 > 0)
|
||||
{
|
||||
int incy = 1;
|
||||
if(rdst.y1 > rsrc.y1)
|
||||
{
|
||||
rsrc.y1 += rc.y2 - 1;
|
||||
rdst.y1 += rc.y2 - 1;
|
||||
incy = -1;
|
||||
}
|
||||
while(rc.y2 > 0)
|
||||
{
|
||||
typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1);
|
||||
if(rw.ptr)
|
||||
{
|
||||
int x1src = rsrc.x1;
|
||||
int x1dst = rdst.x1;
|
||||
int len = rc.x2;
|
||||
if(rw.x1 > x1src)
|
||||
{
|
||||
x1dst += rw.x1 - x1src;
|
||||
len -= rw.x1 - x1src;
|
||||
x1src = rw.x1;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
if(x1src + len-1 > rw.x2)
|
||||
{
|
||||
len -= x1src + len - rw.x2 - 1;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
m_ren->blend_from_color(src,
|
||||
color,
|
||||
x1dst, rdst.y1,
|
||||
x1src, rsrc.y1,
|
||||
len,
|
||||
cover);
|
||||
}
|
||||
}
|
||||
}
|
||||
rdst.y1 += incy;
|
||||
rsrc.y1 += incy;
|
||||
--rc.y2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from_lut(const SrcPixelFormatRenderer& src,
|
||||
const color_type* color_lut,
|
||||
const rect_i* rect_src_ptr = 0,
|
||||
int dx = 0,
|
||||
int dy = 0,
|
||||
cover_type cover = agg::cover_full)
|
||||
{
|
||||
rect_i rsrc(0, 0, src.width(), src.height());
|
||||
if(rect_src_ptr)
|
||||
{
|
||||
rsrc.x1 = rect_src_ptr->x1;
|
||||
rsrc.y1 = rect_src_ptr->y1;
|
||||
rsrc.x2 = rect_src_ptr->x2 + 1;
|
||||
rsrc.y2 = rect_src_ptr->y2 + 1;
|
||||
}
|
||||
|
||||
// Version with xdst, ydst (absolute positioning)
|
||||
//rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1);
|
||||
|
||||
// Version with dx, dy (relative positioning)
|
||||
rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy);
|
||||
rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height());
|
||||
|
||||
if(rc.x2 > 0)
|
||||
{
|
||||
int incy = 1;
|
||||
if(rdst.y1 > rsrc.y1)
|
||||
{
|
||||
rsrc.y1 += rc.y2 - 1;
|
||||
rdst.y1 += rc.y2 - 1;
|
||||
incy = -1;
|
||||
}
|
||||
while(rc.y2 > 0)
|
||||
{
|
||||
typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1);
|
||||
if(rw.ptr)
|
||||
{
|
||||
int x1src = rsrc.x1;
|
||||
int x1dst = rdst.x1;
|
||||
int len = rc.x2;
|
||||
if(rw.x1 > x1src)
|
||||
{
|
||||
x1dst += rw.x1 - x1src;
|
||||
len -= rw.x1 - x1src;
|
||||
x1src = rw.x1;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
if(x1src + len-1 > rw.x2)
|
||||
{
|
||||
len -= x1src + len - rw.x2 - 1;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
m_ren->blend_from_lut(src,
|
||||
color_lut,
|
||||
x1dst, rdst.y1,
|
||||
x1src, rsrc.y1,
|
||||
len,
|
||||
cover);
|
||||
}
|
||||
}
|
||||
}
|
||||
rdst.y1 += incy;
|
||||
rsrc.y1 += incy;
|
||||
--rc.y2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
pixfmt_type* m_ren;
|
||||
rect_i m_clip_box;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,711 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RENDERER_MARKERS_INCLUDED
|
||||
#define AGG_RENDERER_MARKERS_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_renderer_primitives.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//---------------------------------------------------------------marker_e
|
||||
enum marker_e
|
||||
{
|
||||
marker_square,
|
||||
marker_diamond,
|
||||
marker_circle,
|
||||
marker_crossed_circle,
|
||||
marker_semiellipse_left,
|
||||
marker_semiellipse_right,
|
||||
marker_semiellipse_up,
|
||||
marker_semiellipse_down,
|
||||
marker_triangle_left,
|
||||
marker_triangle_right,
|
||||
marker_triangle_up,
|
||||
marker_triangle_down,
|
||||
marker_four_rays,
|
||||
marker_cross,
|
||||
marker_x,
|
||||
marker_dash,
|
||||
marker_dot,
|
||||
marker_pixel,
|
||||
|
||||
end_of_markers
|
||||
};
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------renderer_markers
|
||||
template<class BaseRenderer> class renderer_markers :
|
||||
public renderer_primitives<BaseRenderer>
|
||||
{
|
||||
public:
|
||||
typedef renderer_primitives<BaseRenderer> base_type;
|
||||
typedef BaseRenderer base_ren_type;
|
||||
typedef typename base_ren_type::color_type color_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_markers(base_ren_type& rbuf) :
|
||||
base_type(rbuf)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
bool visible(int x, int y, int r) const
|
||||
{
|
||||
rect_i rc(x-r, y-r, x+y, y+r);
|
||||
return rc.clip(base_type::ren().bounding_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void square(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r) base_type::outlined_rectangle(x-r, y-r, x+r, y+r);
|
||||
else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void diamond(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
int dy = -r;
|
||||
int dx = 0;
|
||||
do
|
||||
{
|
||||
base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full);
|
||||
|
||||
if(dx)
|
||||
{
|
||||
base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full);
|
||||
base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full);
|
||||
}
|
||||
++dy;
|
||||
++dx;
|
||||
}
|
||||
while(dy <= 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void circle(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r) base_type::outlined_ellipse(x, y, r, r);
|
||||
else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void crossed_circle(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
base_type::outlined_ellipse(x, y, r, r);
|
||||
int r6 = r + (r >> 1);
|
||||
if(r <= 2) r6++;
|
||||
r >>= 1;
|
||||
base_type::ren().blend_hline(x-r6, y, x-r, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_hline(x+r, y, x+r6, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_vline(x, y-r6, y-r, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_vline(x, y+r, y+r6, base_type::line_color(), cover_full);
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void semiellipse_left(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
int r8 = r * 4 / 5;
|
||||
int dy = -r;
|
||||
int dx = 0;
|
||||
ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8);
|
||||
do
|
||||
{
|
||||
dx += ei.dx();
|
||||
dy += ei.dy();
|
||||
|
||||
base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full);
|
||||
|
||||
if(ei.dy() && dx)
|
||||
{
|
||||
base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
|
||||
}
|
||||
++ei;
|
||||
}
|
||||
while(dy < r8);
|
||||
base_type::ren().blend_vline(x+dy, y-dx, y+dx, base_type::line_color(), cover_full);
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void semiellipse_right(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
int r8 = r * 4 / 5;
|
||||
int dy = -r;
|
||||
int dx = 0;
|
||||
ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8);
|
||||
do
|
||||
{
|
||||
dx += ei.dx();
|
||||
dy += ei.dy();
|
||||
|
||||
base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full);
|
||||
|
||||
if(ei.dy() && dx)
|
||||
{
|
||||
base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
|
||||
}
|
||||
++ei;
|
||||
}
|
||||
while(dy < r8);
|
||||
base_type::ren().blend_vline(x-dy, y-dx, y+dx, base_type::line_color(), cover_full);
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void semiellipse_up(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
int r8 = r * 4 / 5;
|
||||
int dy = -r;
|
||||
int dx = 0;
|
||||
ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8);
|
||||
do
|
||||
{
|
||||
dx += ei.dx();
|
||||
dy += ei.dy();
|
||||
|
||||
base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full);
|
||||
|
||||
if(ei.dy() && dx)
|
||||
{
|
||||
base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full);
|
||||
}
|
||||
++ei;
|
||||
}
|
||||
while(dy < r8);
|
||||
base_type::ren().blend_hline(x-dx, y-dy-1, x+dx, base_type::line_color(), cover_full);
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void semiellipse_down(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
int r8 = r * 4 / 5;
|
||||
int dy = -r;
|
||||
int dx = 0;
|
||||
ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8);
|
||||
do
|
||||
{
|
||||
dx += ei.dx();
|
||||
dy += ei.dy();
|
||||
|
||||
base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full);
|
||||
|
||||
if(ei.dy() && dx)
|
||||
{
|
||||
base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full);
|
||||
}
|
||||
++ei;
|
||||
}
|
||||
while(dy < r8);
|
||||
base_type::ren().blend_hline(x-dx, y+dy+1, x+dx, base_type::line_color(), cover_full);
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void triangle_left(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
int dy = -r;
|
||||
int dx = 0;
|
||||
int flip = 0;
|
||||
int r6 = r * 3 / 5;
|
||||
do
|
||||
{
|
||||
base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full);
|
||||
|
||||
if(dx)
|
||||
{
|
||||
base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
|
||||
}
|
||||
++dy;
|
||||
dx += flip;
|
||||
flip ^= 1;
|
||||
}
|
||||
while(dy < r6);
|
||||
base_type::ren().blend_vline(x+dy, y-dx, y+dx, base_type::line_color(), cover_full);
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void triangle_right(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
int dy = -r;
|
||||
int dx = 0;
|
||||
int flip = 0;
|
||||
int r6 = r * 3 / 5;
|
||||
do
|
||||
{
|
||||
base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full);
|
||||
|
||||
if(dx)
|
||||
{
|
||||
base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
|
||||
}
|
||||
++dy;
|
||||
dx += flip;
|
||||
flip ^= 1;
|
||||
}
|
||||
while(dy < r6);
|
||||
base_type::ren().blend_vline(x-dy, y-dx, y+dx, base_type::line_color(), cover_full);
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void triangle_up(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
int dy = -r;
|
||||
int dx = 0;
|
||||
int flip = 0;
|
||||
int r6 = r * 3 / 5;
|
||||
do
|
||||
{
|
||||
base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full);
|
||||
|
||||
if(dx)
|
||||
{
|
||||
base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full);
|
||||
}
|
||||
++dy;
|
||||
dx += flip;
|
||||
flip ^= 1;
|
||||
}
|
||||
while(dy < r6);
|
||||
base_type::ren().blend_hline(x-dx, y-dy, x+dx, base_type::line_color(), cover_full);
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void triangle_down(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
int dy = -r;
|
||||
int dx = 0;
|
||||
int flip = 0;
|
||||
int r6 = r * 3 / 5;
|
||||
do
|
||||
{
|
||||
base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full);
|
||||
|
||||
if(dx)
|
||||
{
|
||||
base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full);
|
||||
}
|
||||
++dy;
|
||||
dx += flip;
|
||||
flip ^= 1;
|
||||
}
|
||||
while(dy < r6);
|
||||
base_type::ren().blend_hline(x-dx, y+dy, x+dx, base_type::line_color(), cover_full);
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void four_rays(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
int dy = -r;
|
||||
int dx = 0;
|
||||
int flip = 0;
|
||||
int r3 = -(r / 3);
|
||||
do
|
||||
{
|
||||
base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full);
|
||||
|
||||
if(dx)
|
||||
{
|
||||
base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full);
|
||||
base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full);
|
||||
base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
|
||||
base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
|
||||
}
|
||||
++dy;
|
||||
dx += flip;
|
||||
flip ^= 1;
|
||||
}
|
||||
while(dy <= r3);
|
||||
base_type::solid_rectangle(x+r3+1, y+r3+1, x-r3-1, y-r3-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void cross(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
base_type::ren().blend_vline(x, y-r, y+r, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_hline(x-r, y, x+r, base_type::line_color(), cover_full);
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void xing(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r)
|
||||
{
|
||||
int dy = -r * 7 / 10;
|
||||
do
|
||||
{
|
||||
base_type::ren().blend_pixel(x + dy, y + dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x - dy, y + dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x + dy, y - dy, base_type::line_color(), cover_full);
|
||||
base_type::ren().blend_pixel(x - dy, y - dy, base_type::line_color(), cover_full);
|
||||
++dy;
|
||||
}
|
||||
while(dy < 0);
|
||||
}
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void dash(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r) base_type::ren().blend_hline(x-r, y, x+r, base_type::line_color(), cover_full);
|
||||
else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void dot(int x, int y, int r)
|
||||
{
|
||||
if(visible(x, y, r))
|
||||
{
|
||||
if(r) base_type::solid_ellipse(x, y, r, r);
|
||||
else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void pixel(int x, int y, int)
|
||||
{
|
||||
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void marker(int x, int y, int r, marker_e type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case marker_square: square(x, y, r); break;
|
||||
case marker_diamond: diamond(x, y, r); break;
|
||||
case marker_circle: circle(x, y, r); break;
|
||||
case marker_crossed_circle: crossed_circle(x, y, r); break;
|
||||
case marker_semiellipse_left: semiellipse_left(x, y, r); break;
|
||||
case marker_semiellipse_right: semiellipse_right(x, y, r); break;
|
||||
case marker_semiellipse_up: semiellipse_up(x, y, r); break;
|
||||
case marker_semiellipse_down: semiellipse_down(x, y, r); break;
|
||||
case marker_triangle_left: triangle_left(x, y, r); break;
|
||||
case marker_triangle_right: triangle_right(x, y, r); break;
|
||||
case marker_triangle_up: triangle_up(x, y, r); break;
|
||||
case marker_triangle_down: triangle_down(x, y, r); break;
|
||||
case marker_four_rays: four_rays(x, y, r); break;
|
||||
case marker_cross: cross(x, y, r); break;
|
||||
case marker_x: xing(x, y, r); break;
|
||||
case marker_dash: dash(x, y, r); break;
|
||||
case marker_dot: dot(x, y, r); break;
|
||||
case marker_pixel: pixel(x, y, r); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class T>
|
||||
void markers(int n, const T* x, const T* y, T r, marker_e type)
|
||||
{
|
||||
if(n <= 0) return;
|
||||
if(r == 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
base_type::ren().blend_pixel(int(*x), int(*y), base_type::fill_color(), cover_full);
|
||||
++x;
|
||||
++y;
|
||||
}
|
||||
while(--n);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case marker_square: do { square (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_diamond: do { diamond (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_circle: do { circle (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_crossed_circle: do { crossed_circle (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_semiellipse_left: do { semiellipse_left (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_semiellipse_right: do { semiellipse_right(int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_semiellipse_up: do { semiellipse_up (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_semiellipse_down: do { semiellipse_down (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_triangle_left: do { triangle_left (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_triangle_right: do { triangle_right (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_triangle_up: do { triangle_up (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_triangle_down: do { triangle_down (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_four_rays: do { four_rays (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_cross: do { cross (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_x: do { xing (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_dash: do { dash (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_dot: do { dot (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
case marker_pixel: do { pixel (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class T>
|
||||
void markers(int n, const T* x, const T* y, const T* r, marker_e type)
|
||||
{
|
||||
if(n <= 0) return;
|
||||
switch(type)
|
||||
{
|
||||
case marker_square: do { square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_diamond: do { diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_circle: do { circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_crossed_circle: do { crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_semiellipse_left: do { semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_semiellipse_right: do { semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_semiellipse_up: do { semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_semiellipse_down: do { semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_triangle_left: do { triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_triangle_right: do { triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_triangle_up: do { triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_triangle_down: do { triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_four_rays: do { four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_cross: do { cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_x: do { xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_dash: do { dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_dot: do { dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
case marker_pixel: do { pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class T>
|
||||
void markers(int n, const T* x, const T* y, const T* r, const color_type* fc, marker_e type)
|
||||
{
|
||||
if(n <= 0) return;
|
||||
switch(type)
|
||||
{
|
||||
case marker_square: do { base_type::fill_color(*fc); square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_diamond: do { base_type::fill_color(*fc); diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_circle: do { base_type::fill_color(*fc); circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_crossed_circle: do { base_type::fill_color(*fc); crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_semiellipse_left: do { base_type::fill_color(*fc); semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_semiellipse_right: do { base_type::fill_color(*fc); semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_semiellipse_up: do { base_type::fill_color(*fc); semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_semiellipse_down: do { base_type::fill_color(*fc); semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_triangle_left: do { base_type::fill_color(*fc); triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_triangle_right: do { base_type::fill_color(*fc); triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_triangle_up: do { base_type::fill_color(*fc); triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_triangle_down: do { base_type::fill_color(*fc); triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_four_rays: do { base_type::fill_color(*fc); four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_cross: do { base_type::fill_color(*fc); cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_x: do { base_type::fill_color(*fc); xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_dash: do { base_type::fill_color(*fc); dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_dot: do { base_type::fill_color(*fc); dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
case marker_pixel: do { base_type::fill_color(*fc); pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class T>
|
||||
void markers(int n, const T* x, const T* y, const T* r, const color_type* fc, const color_type* lc, marker_e type)
|
||||
{
|
||||
if(n <= 0) return;
|
||||
switch(type)
|
||||
{
|
||||
case marker_square: do { base_type::fill_color(*fc); base_type::line_color(*lc); square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_diamond: do { base_type::fill_color(*fc); base_type::line_color(*lc); diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_circle: do { base_type::fill_color(*fc); base_type::line_color(*lc); circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_crossed_circle: do { base_type::fill_color(*fc); base_type::line_color(*lc); crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_semiellipse_left: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_semiellipse_right: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_semiellipse_up: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_semiellipse_down: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_triangle_left: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_triangle_right: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_triangle_up: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_triangle_down: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_four_rays: do { base_type::fill_color(*fc); base_type::line_color(*lc); four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_cross: do { base_type::fill_color(*fc); base_type::line_color(*lc); cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_x: do { base_type::fill_color(*fc); base_type::line_color(*lc); xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_dash: do { base_type::fill_color(*fc); base_type::line_color(*lc); dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_dot: do { base_type::fill_color(*fc); base_type::line_color(*lc); dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
case marker_pixel: do { base_type::fill_color(*fc); base_type::line_color(*lc); pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,349 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RENDERER_MCLIP_INCLUDED
|
||||
#define AGG_RENDERER_MCLIP_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_array.h"
|
||||
#include "agg_renderer_base.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//----------------------------------------------------------renderer_mclip
|
||||
template<class PixelFormat> class renderer_mclip
|
||||
{
|
||||
public:
|
||||
typedef PixelFormat pixfmt_type;
|
||||
typedef typename pixfmt_type::color_type color_type;
|
||||
typedef typename pixfmt_type::row_data row_data;
|
||||
typedef renderer_base<pixfmt_type> base_ren_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
explicit renderer_mclip(pixfmt_type& pixf) :
|
||||
m_ren(pixf),
|
||||
m_curr_cb(0),
|
||||
m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax())
|
||||
{}
|
||||
void attach(pixfmt_type& pixf)
|
||||
{
|
||||
m_ren.attach(pixf);
|
||||
reset_clipping(true);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const pixfmt_type& ren() const { return m_ren.ren(); }
|
||||
pixfmt_type& ren() { return m_ren.ren(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned width() const { return m_ren.width(); }
|
||||
unsigned height() const { return m_ren.height(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const rect_i& clip_box() const { return m_ren.clip_box(); }
|
||||
int xmin() const { return m_ren.xmin(); }
|
||||
int ymin() const { return m_ren.ymin(); }
|
||||
int xmax() const { return m_ren.xmax(); }
|
||||
int ymax() const { return m_ren.ymax(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const rect_i& bounding_clip_box() const { return m_bounds; }
|
||||
int bounding_xmin() const { return m_bounds.x1; }
|
||||
int bounding_ymin() const { return m_bounds.y1; }
|
||||
int bounding_xmax() const { return m_bounds.x2; }
|
||||
int bounding_ymax() const { return m_bounds.y2; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void first_clip_box()
|
||||
{
|
||||
m_curr_cb = 0;
|
||||
if(m_clip.size())
|
||||
{
|
||||
const rect_i& cb = m_clip[0];
|
||||
m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
bool next_clip_box()
|
||||
{
|
||||
if(++m_curr_cb < m_clip.size())
|
||||
{
|
||||
const rect_i& cb = m_clip[m_curr_cb];
|
||||
m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset_clipping(bool visibility)
|
||||
{
|
||||
m_ren.reset_clipping(visibility);
|
||||
m_clip.remove_all();
|
||||
m_curr_cb = 0;
|
||||
m_bounds = m_ren.clip_box();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_clip_box(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
rect_i cb(x1, y1, x2, y2);
|
||||
cb.normalize();
|
||||
if(cb.clip(rect_i(0, 0, width() - 1, height() - 1)))
|
||||
{
|
||||
m_clip.add(cb);
|
||||
if(cb.x1 < m_bounds.x1) m_bounds.x1 = cb.x1;
|
||||
if(cb.y1 < m_bounds.y1) m_bounds.y1 = cb.y1;
|
||||
if(cb.x2 > m_bounds.x2) m_bounds.x2 = cb.x2;
|
||||
if(cb.y2 > m_bounds.y2) m_bounds.y2 = cb.y2;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clear(const color_type& c)
|
||||
{
|
||||
m_ren.clear(c);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
if(m_ren.inbox(x, y))
|
||||
{
|
||||
m_ren.ren().copy_pixel(x, y, c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_pixel(int x, int y, const color_type& c, cover_type cover)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
if(m_ren.inbox(x, y))
|
||||
{
|
||||
m_ren.ren().blend_pixel(x, y, c, cover);
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
color_type pixel(int x, int y) const
|
||||
{
|
||||
if(m_ren.inbox(x, y))
|
||||
{
|
||||
return m_ren.ren().pixel(x, y);
|
||||
}
|
||||
return color_type::no_color();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_hline(int x1, int y, int x2, const color_type& c)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.copy_hline(x1, y, x2, c);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_vline(int x, int y1, int y2, const color_type& c)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.copy_vline(x, y1, y2, c);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_hline(int x1, int y, int x2,
|
||||
const color_type& c, cover_type cover)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.blend_hline(x1, y, x2, c, cover);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_vline(int x, int y1, int y2,
|
||||
const color_type& c, cover_type cover)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.blend_vline(x, y1, y2, c, cover);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_bar(int x1, int y1, int x2, int y2, const color_type& c)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.copy_bar(x1, y1, x2, y2, c);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_bar(int x1, int y1, int x2, int y2,
|
||||
const color_type& c, cover_type cover)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.blend_bar(x1, y1, x2, y2, c, cover);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_hspan(int x, int y, int len,
|
||||
const color_type& c, const cover_type* covers)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.blend_solid_hspan(x, y, len, c, covers);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_vspan(int x, int y, int len,
|
||||
const color_type& c, const cover_type* covers)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.blend_solid_vspan(x, y, len, c, covers);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_color_hspan(int x, int y, int len, const color_type* colors)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.copy_color_hspan(x, y, len, colors);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_hspan(int x, int y, int len,
|
||||
const color_type* colors,
|
||||
const cover_type* covers,
|
||||
cover_type cover = cover_full)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.blend_color_hspan(x, y, len, colors, covers, cover);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_vspan(int x, int y, int len,
|
||||
const color_type* colors,
|
||||
const cover_type* covers,
|
||||
cover_type cover = cover_full)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.blend_color_vspan(x, y, len, colors, covers, cover);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_from(const rendering_buffer& from,
|
||||
const rect_i* rc=0,
|
||||
int x_to=0,
|
||||
int y_to=0)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.copy_from(from, rc, x_to, y_to);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from(const SrcPixelFormatRenderer& src,
|
||||
const rect_i* rect_src_ptr = 0,
|
||||
int dx = 0,
|
||||
int dy = 0,
|
||||
cover_type cover = cover_full)
|
||||
{
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
m_ren.blend_from(src, rect_src_ptr, dx, dy, cover);
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
renderer_mclip(const renderer_mclip<PixelFormat>&);
|
||||
const renderer_mclip<PixelFormat>&
|
||||
operator = (const renderer_mclip<PixelFormat>&);
|
||||
|
||||
base_ren_type m_ren;
|
||||
pod_bvector<rect_i, 4> m_clip;
|
||||
unsigned m_curr_cb;
|
||||
rect_i m_bounds;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,229 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RENDERER_PRIMITIVES_INCLUDED
|
||||
#define AGG_RENDERER_PRIMITIVES_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_renderer_base.h"
|
||||
#include "agg_dda_line.h"
|
||||
#include "agg_ellipse_bresenham.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//-----------------------------------------------------renderer_primitives
|
||||
template<class BaseRenderer> class renderer_primitives
|
||||
{
|
||||
public:
|
||||
typedef BaseRenderer base_ren_type;
|
||||
typedef typename base_ren_type::color_type color_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
explicit renderer_primitives(base_ren_type& ren) :
|
||||
m_ren(&ren),
|
||||
m_fill_color(),
|
||||
m_line_color(),
|
||||
m_curr_x(0),
|
||||
m_curr_y(0)
|
||||
{}
|
||||
void attach(base_ren_type& ren) { m_ren = &ren; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static int coord(double c)
|
||||
{
|
||||
return iround(c * line_bresenham_interpolator::subpixel_scale);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void fill_color(const color_type& c) { m_fill_color = c; }
|
||||
void line_color(const color_type& c) { m_line_color = c; }
|
||||
const color_type& fill_color() const { return m_fill_color; }
|
||||
const color_type& line_color() const { return m_line_color; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void rectangle(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
m_ren->blend_hline(x1, y1, x2-1, m_line_color, cover_full);
|
||||
m_ren->blend_vline(x2, y1, y2-1, m_line_color, cover_full);
|
||||
m_ren->blend_hline(x1+1, y2, x2, m_line_color, cover_full);
|
||||
m_ren->blend_vline(x1, y1+1, y2, m_line_color, cover_full);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void solid_rectangle(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
m_ren->blend_bar(x1, y1, x2, y2, m_fill_color, cover_full);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void outlined_rectangle(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
rectangle(x1, y1, x2, y2);
|
||||
m_ren->blend_bar(x1+1, y1+1, x2-1, y2-1, m_fill_color, cover_full);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void ellipse(int x, int y, int rx, int ry)
|
||||
{
|
||||
ellipse_bresenham_interpolator ei(rx, ry);
|
||||
int dx = 0;
|
||||
int dy = -ry;
|
||||
do
|
||||
{
|
||||
dx += ei.dx();
|
||||
dy += ei.dy();
|
||||
m_ren->blend_pixel(x + dx, y + dy, m_line_color, cover_full);
|
||||
m_ren->blend_pixel(x + dx, y - dy, m_line_color, cover_full);
|
||||
m_ren->blend_pixel(x - dx, y - dy, m_line_color, cover_full);
|
||||
m_ren->blend_pixel(x - dx, y + dy, m_line_color, cover_full);
|
||||
++ei;
|
||||
}
|
||||
while(dy < 0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void solid_ellipse(int x, int y, int rx, int ry)
|
||||
{
|
||||
ellipse_bresenham_interpolator ei(rx, ry);
|
||||
int dx = 0;
|
||||
int dy = -ry;
|
||||
int dy0 = dy;
|
||||
int dx0 = dx;
|
||||
|
||||
do
|
||||
{
|
||||
dx += ei.dx();
|
||||
dy += ei.dy();
|
||||
|
||||
if(dy != dy0)
|
||||
{
|
||||
m_ren->blend_hline(x-dx0, y+dy0, x+dx0, m_fill_color, cover_full);
|
||||
m_ren->blend_hline(x-dx0, y-dy0, x+dx0, m_fill_color, cover_full);
|
||||
}
|
||||
dx0 = dx;
|
||||
dy0 = dy;
|
||||
++ei;
|
||||
}
|
||||
while(dy < 0);
|
||||
m_ren->blend_hline(x-dx0, y+dy0, x+dx0, m_fill_color, cover_full);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void outlined_ellipse(int x, int y, int rx, int ry)
|
||||
{
|
||||
ellipse_bresenham_interpolator ei(rx, ry);
|
||||
int dx = 0;
|
||||
int dy = -ry;
|
||||
|
||||
do
|
||||
{
|
||||
dx += ei.dx();
|
||||
dy += ei.dy();
|
||||
|
||||
m_ren->blend_pixel(x + dx, y + dy, m_line_color, cover_full);
|
||||
m_ren->blend_pixel(x + dx, y - dy, m_line_color, cover_full);
|
||||
m_ren->blend_pixel(x - dx, y - dy, m_line_color, cover_full);
|
||||
m_ren->blend_pixel(x - dx, y + dy, m_line_color, cover_full);
|
||||
|
||||
if(ei.dy() && dx)
|
||||
{
|
||||
m_ren->blend_hline(x-dx+1, y+dy, x+dx-1, m_fill_color, cover_full);
|
||||
m_ren->blend_hline(x-dx+1, y-dy, x+dx-1, m_fill_color, cover_full);
|
||||
}
|
||||
++ei;
|
||||
}
|
||||
while(dy < 0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void line(int x1, int y1, int x2, int y2, bool last=false)
|
||||
{
|
||||
line_bresenham_interpolator li(x1, y1, x2, y2);
|
||||
|
||||
unsigned len = li.len();
|
||||
if(len == 0)
|
||||
{
|
||||
if(last)
|
||||
{
|
||||
m_ren->blend_pixel(li.line_lr(x1), li.line_lr(y1), m_line_color, cover_full);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(last) ++len;
|
||||
|
||||
if(li.is_ver())
|
||||
{
|
||||
do
|
||||
{
|
||||
m_ren->blend_pixel(li.x2(), li.y1(), m_line_color, cover_full);
|
||||
li.vstep();
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
m_ren->blend_pixel(li.x1(), li.y2(), m_line_color, cover_full);
|
||||
li.hstep();
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void move_to(int x, int y)
|
||||
{
|
||||
m_curr_x = x;
|
||||
m_curr_y = y;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void line_to(int x, int y, bool last=false)
|
||||
{
|
||||
line(m_curr_x, m_curr_y, x, y, last);
|
||||
m_curr_x = x;
|
||||
m_curr_y = y;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const base_ren_type& ren() const { return *m_ren; }
|
||||
base_ren_type& ren() { return *m_ren; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const rendering_buffer& rbuf() const { return m_ren->rbuf(); }
|
||||
rendering_buffer& rbuf() { return m_ren->rbuf(); }
|
||||
|
||||
private:
|
||||
base_ren_type* m_ren;
|
||||
color_type m_fill_color;
|
||||
color_type m_line_color;
|
||||
int m_curr_x;
|
||||
int m_curr_y;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,273 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RENDERER_RASTER_TEXT_INCLUDED
|
||||
#define AGG_RENDERER_RASTER_TEXT_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//==============================================renderer_raster_htext_solid
|
||||
template<class BaseRenderer, class GlyphGenerator>
|
||||
class renderer_raster_htext_solid
|
||||
{
|
||||
public:
|
||||
typedef BaseRenderer ren_type;
|
||||
typedef GlyphGenerator glyph_gen_type;
|
||||
typedef typename glyph_gen_type::glyph_rect glyph_rect;
|
||||
typedef typename ren_type::color_type color_type;
|
||||
|
||||
renderer_raster_htext_solid(ren_type& ren, glyph_gen_type& glyph) :
|
||||
m_ren(&ren),
|
||||
m_glyph(&glyph)
|
||||
{}
|
||||
void attach(ren_type& ren) { m_ren = &ren; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void color(const color_type& c) { m_color = c; }
|
||||
const color_type& color() const { return m_color; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class CharT>
|
||||
void render_text(double x, double y, const CharT* str, bool flip=false)
|
||||
{
|
||||
glyph_rect r;
|
||||
while(*str)
|
||||
{
|
||||
m_glyph->prepare(&r, x, y, *str, flip);
|
||||
if(r.x2 >= r.x1)
|
||||
{
|
||||
int i;
|
||||
if(flip)
|
||||
{
|
||||
for(i = r.y1; i <= r.y2; i++)
|
||||
{
|
||||
m_ren->blend_solid_hspan(r.x1, i, (r.x2 - r.x1 + 1),
|
||||
m_color,
|
||||
m_glyph->span(r.y2 - i));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i = r.y1; i <= r.y2; i++)
|
||||
{
|
||||
m_ren->blend_solid_hspan(r.x1, i, (r.x2 - r.x1 + 1),
|
||||
m_color,
|
||||
m_glyph->span(i - r.y1));
|
||||
}
|
||||
}
|
||||
}
|
||||
x += r.dx;
|
||||
y += r.dy;
|
||||
++str;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ren_type* m_ren;
|
||||
glyph_gen_type* m_glyph;
|
||||
color_type m_color;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=============================================renderer_raster_vtext_solid
|
||||
template<class BaseRenderer, class GlyphGenerator>
|
||||
class renderer_raster_vtext_solid
|
||||
{
|
||||
public:
|
||||
typedef BaseRenderer ren_type;
|
||||
typedef GlyphGenerator glyph_gen_type;
|
||||
typedef typename glyph_gen_type::glyph_rect glyph_rect;
|
||||
typedef typename ren_type::color_type color_type;
|
||||
|
||||
renderer_raster_vtext_solid(ren_type& ren, glyph_gen_type& glyph) :
|
||||
m_ren(&ren),
|
||||
m_glyph(&glyph)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void color(const color_type& c) { m_color = c; }
|
||||
const color_type& color() const { return m_color; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class CharT>
|
||||
void render_text(double x, double y, const CharT* str, bool flip=false)
|
||||
{
|
||||
glyph_rect r;
|
||||
while(*str)
|
||||
{
|
||||
m_glyph->prepare(&r, x, y, *str, !flip);
|
||||
if(r.x2 >= r.x1)
|
||||
{
|
||||
int i;
|
||||
if(flip)
|
||||
{
|
||||
for(i = r.y1; i <= r.y2; i++)
|
||||
{
|
||||
m_ren->blend_solid_vspan(i, r.x1, (r.x2 - r.x1 + 1),
|
||||
m_color,
|
||||
m_glyph->span(i - r.y1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i = r.y1; i <= r.y2; i++)
|
||||
{
|
||||
m_ren->blend_solid_vspan(i, r.x1, (r.x2 - r.x1 + 1),
|
||||
m_color,
|
||||
m_glyph->span(r.y2 - i));
|
||||
}
|
||||
}
|
||||
}
|
||||
x += r.dx;
|
||||
y += r.dy;
|
||||
++str;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ren_type* m_ren;
|
||||
glyph_gen_type* m_glyph;
|
||||
color_type m_color;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===================================================renderer_raster_htext
|
||||
template<class ScanlineRenderer, class GlyphGenerator>
|
||||
class renderer_raster_htext
|
||||
{
|
||||
public:
|
||||
typedef ScanlineRenderer ren_type;
|
||||
typedef GlyphGenerator glyph_gen_type;
|
||||
typedef typename glyph_gen_type::glyph_rect glyph_rect;
|
||||
|
||||
class scanline_single_span
|
||||
{
|
||||
public:
|
||||
typedef agg::cover_type cover_type;
|
||||
|
||||
//----------------------------------------------------------------
|
||||
struct const_span
|
||||
{
|
||||
int x;
|
||||
unsigned len;
|
||||
const cover_type* covers;
|
||||
|
||||
const_span() {}
|
||||
const_span(int x_, unsigned len_, const cover_type* covers_) :
|
||||
x(x_), len(len_), covers(covers_)
|
||||
{}
|
||||
};
|
||||
|
||||
typedef const const_span* const_iterator;
|
||||
|
||||
//----------------------------------------------------------------
|
||||
scanline_single_span(int x, int y, unsigned len,
|
||||
const cover_type* covers) :
|
||||
m_y(y),
|
||||
m_span(x, len, covers)
|
||||
{}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
int y() const { return m_y; }
|
||||
unsigned num_spans() const { return 1; }
|
||||
const_iterator begin() const { return &m_span; }
|
||||
|
||||
private:
|
||||
//----------------------------------------------------------------
|
||||
int m_y;
|
||||
const_span m_span;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_raster_htext(ren_type& ren, glyph_gen_type& glyph) :
|
||||
m_ren(&ren),
|
||||
m_glyph(&glyph)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class CharT>
|
||||
void render_text(double x, double y, const CharT* str, bool flip=false)
|
||||
{
|
||||
glyph_rect r;
|
||||
while(*str)
|
||||
{
|
||||
m_glyph->prepare(&r, x, y, *str, flip);
|
||||
if(r.x2 >= r.x1)
|
||||
{
|
||||
m_ren->prepare();
|
||||
int i;
|
||||
if(flip)
|
||||
{
|
||||
for(i = r.y1; i <= r.y2; i++)
|
||||
{
|
||||
m_ren->render(
|
||||
scanline_single_span(r.x1,
|
||||
i,
|
||||
(r.x2 - r.x1 + 1),
|
||||
m_glyph->span(r.y2 - i)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i = r.y1; i <= r.y2; i++)
|
||||
{
|
||||
m_ren->render(
|
||||
scanline_single_span(r.x1,
|
||||
i,
|
||||
(r.x2 - r.x1 + 1),
|
||||
m_glyph->span(i - r.y1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
x += r.dx;
|
||||
y += r.dy;
|
||||
++str;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ren_type* m_ren;
|
||||
glyph_gen_type* m_glyph;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,861 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RENDERER_SCANLINE_INCLUDED
|
||||
#define AGG_RENDERER_SCANLINE_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_renderer_base.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//================================================render_scanline_aa_solid
|
||||
template<class Scanline, class BaseRenderer, class ColorT>
|
||||
void render_scanline_aa_solid(const Scanline& sl,
|
||||
BaseRenderer& ren,
|
||||
const ColorT& color)
|
||||
{
|
||||
int y = sl.y();
|
||||
unsigned num_spans = sl.num_spans();
|
||||
typename Scanline::const_iterator span = sl.begin();
|
||||
|
||||
for(;;)
|
||||
{
|
||||
int x = span->x;
|
||||
if(span->len > 0)
|
||||
{
|
||||
ren.blend_solid_hspan(x, y, (unsigned)span->len,
|
||||
color,
|
||||
span->covers);
|
||||
}
|
||||
else
|
||||
{
|
||||
ren.blend_hline(x, y, (unsigned)(x - span->len - 1),
|
||||
color,
|
||||
*(span->covers));
|
||||
}
|
||||
if(--num_spans == 0) break;
|
||||
++span;
|
||||
}
|
||||
}
|
||||
|
||||
//===============================================render_scanlines_aa_solid
|
||||
template<class Rasterizer, class Scanline,
|
||||
class BaseRenderer, class ColorT>
|
||||
void render_scanlines_aa_solid(Rasterizer& ras, Scanline& sl,
|
||||
BaseRenderer& ren, const ColorT& color)
|
||||
{
|
||||
if(ras.rewind_scanlines())
|
||||
{
|
||||
// Explicitly convert "color" to the BaseRenderer color type.
|
||||
// For example, it can be called with color type "rgba", while
|
||||
// "rgba8" is needed. Otherwise it will be implicitly
|
||||
// converted in the loop many times.
|
||||
//----------------------
|
||||
typename BaseRenderer::color_type ren_color(color);
|
||||
|
||||
sl.reset(ras.min_x(), ras.max_x());
|
||||
while(ras.sweep_scanline(sl))
|
||||
{
|
||||
//render_scanline_aa_solid(sl, ren, ren_color);
|
||||
|
||||
// This code is equivalent to the above call (copy/paste).
|
||||
// It's just a "manual" optimization for old compilers,
|
||||
// like Microsoft Visual C++ v6.0
|
||||
//-------------------------------
|
||||
int y = sl.y();
|
||||
unsigned num_spans = sl.num_spans();
|
||||
typename Scanline::const_iterator span = sl.begin();
|
||||
|
||||
for(;;)
|
||||
{
|
||||
int x = span->x;
|
||||
if(span->len > 0)
|
||||
{
|
||||
ren.blend_solid_hspan(x, y, (unsigned)span->len,
|
||||
ren_color,
|
||||
span->covers);
|
||||
}
|
||||
else
|
||||
{
|
||||
ren.blend_hline(x, y, (unsigned)(x - span->len - 1),
|
||||
ren_color,
|
||||
*(span->covers));
|
||||
}
|
||||
if(--num_spans == 0) break;
|
||||
++span;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================renderer_scanline_aa_solid
|
||||
template<class BaseRenderer> class renderer_scanline_aa_solid
|
||||
{
|
||||
public:
|
||||
typedef BaseRenderer base_ren_type;
|
||||
typedef typename base_ren_type::color_type color_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_scanline_aa_solid() : m_ren(0) {}
|
||||
explicit renderer_scanline_aa_solid(base_ren_type& ren) : m_ren(&ren) {}
|
||||
void attach(base_ren_type& ren)
|
||||
{
|
||||
m_ren = &ren;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void color(const color_type& c) { m_color = c; }
|
||||
const color_type& color() const { return m_color; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Scanline> void render(const Scanline& sl)
|
||||
{
|
||||
render_scanline_aa_solid(sl, *m_ren, m_color);
|
||||
}
|
||||
|
||||
private:
|
||||
base_ren_type* m_ren;
|
||||
color_type m_color;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//======================================================render_scanline_aa
|
||||
template<class Scanline, class BaseRenderer,
|
||||
class SpanAllocator, class SpanGenerator>
|
||||
void render_scanline_aa(const Scanline& sl, BaseRenderer& ren,
|
||||
SpanAllocator& alloc, SpanGenerator& span_gen)
|
||||
{
|
||||
int y = sl.y();
|
||||
|
||||
unsigned num_spans = sl.num_spans();
|
||||
typename Scanline::const_iterator span = sl.begin();
|
||||
for(;;)
|
||||
{
|
||||
int x = span->x;
|
||||
int len = span->len;
|
||||
const typename Scanline::cover_type* covers = span->covers;
|
||||
|
||||
if(len < 0) len = -len;
|
||||
typename BaseRenderer::color_type* colors = alloc.allocate(len);
|
||||
span_gen.generate(colors, x, y, len);
|
||||
ren.blend_color_hspan(x, y, len, colors,
|
||||
(span->len < 0) ? 0 : covers, *covers);
|
||||
|
||||
if(--num_spans == 0) break;
|
||||
++span;
|
||||
}
|
||||
}
|
||||
|
||||
//=====================================================render_scanlines_aa
|
||||
template<class Rasterizer, class Scanline, class BaseRenderer,
|
||||
class SpanAllocator, class SpanGenerator>
|
||||
void render_scanlines_aa(Rasterizer& ras, Scanline& sl, BaseRenderer& ren,
|
||||
SpanAllocator& alloc, SpanGenerator& span_gen)
|
||||
{
|
||||
if(ras.rewind_scanlines())
|
||||
{
|
||||
sl.reset(ras.min_x(), ras.max_x());
|
||||
span_gen.prepare();
|
||||
while(ras.sweep_scanline(sl))
|
||||
{
|
||||
render_scanline_aa(sl, ren, alloc, span_gen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//====================================================renderer_scanline_aa
|
||||
template<class BaseRenderer, class SpanAllocator, class SpanGenerator>
|
||||
class renderer_scanline_aa
|
||||
{
|
||||
public:
|
||||
typedef BaseRenderer base_ren_type;
|
||||
typedef SpanAllocator alloc_type;
|
||||
typedef SpanGenerator span_gen_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_scanline_aa() : m_ren(0), m_alloc(0), m_span_gen(0) {}
|
||||
renderer_scanline_aa(base_ren_type& ren,
|
||||
alloc_type& alloc,
|
||||
span_gen_type& span_gen) :
|
||||
m_ren(&ren),
|
||||
m_alloc(&alloc),
|
||||
m_span_gen(&span_gen)
|
||||
{}
|
||||
void attach(base_ren_type& ren,
|
||||
alloc_type& alloc,
|
||||
span_gen_type& span_gen)
|
||||
{
|
||||
m_ren = &ren;
|
||||
m_alloc = &alloc;
|
||||
m_span_gen = &span_gen;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare() { m_span_gen->prepare(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Scanline> void render(const Scanline& sl)
|
||||
{
|
||||
render_scanline_aa(sl, *m_ren, *m_alloc, *m_span_gen);
|
||||
}
|
||||
|
||||
private:
|
||||
base_ren_type* m_ren;
|
||||
alloc_type* m_alloc;
|
||||
span_gen_type* m_span_gen;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===============================================render_scanline_bin_solid
|
||||
template<class Scanline, class BaseRenderer, class ColorT>
|
||||
void render_scanline_bin_solid(const Scanline& sl,
|
||||
BaseRenderer& ren,
|
||||
const ColorT& color)
|
||||
{
|
||||
unsigned num_spans = sl.num_spans();
|
||||
typename Scanline::const_iterator span = sl.begin();
|
||||
for(;;)
|
||||
{
|
||||
ren.blend_hline(span->x,
|
||||
sl.y(),
|
||||
span->x - 1 + ((span->len < 0) ?
|
||||
-span->len :
|
||||
span->len),
|
||||
color,
|
||||
cover_full);
|
||||
if(--num_spans == 0) break;
|
||||
++span;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================render_scanlines_bin_solid
|
||||
template<class Rasterizer, class Scanline,
|
||||
class BaseRenderer, class ColorT>
|
||||
void render_scanlines_bin_solid(Rasterizer& ras, Scanline& sl,
|
||||
BaseRenderer& ren, const ColorT& color)
|
||||
{
|
||||
if(ras.rewind_scanlines())
|
||||
{
|
||||
// Explicitly convert "color" to the BaseRenderer color type.
|
||||
// For example, it can be called with color type "rgba", while
|
||||
// "rgba8" is needed. Otherwise it will be implicitly
|
||||
// converted in the loop many times.
|
||||
//----------------------
|
||||
typename BaseRenderer::color_type ren_color(color);
|
||||
|
||||
sl.reset(ras.min_x(), ras.max_x());
|
||||
while(ras.sweep_scanline(sl))
|
||||
{
|
||||
//render_scanline_bin_solid(sl, ren, ren_color);
|
||||
|
||||
// This code is equivalent to the above call (copy/paste).
|
||||
// It's just a "manual" optimization for old compilers,
|
||||
// like Microsoft Visual C++ v6.0
|
||||
//-------------------------------
|
||||
unsigned num_spans = sl.num_spans();
|
||||
typename Scanline::const_iterator span = sl.begin();
|
||||
for(;;)
|
||||
{
|
||||
ren.blend_hline(span->x,
|
||||
sl.y(),
|
||||
span->x - 1 + ((span->len < 0) ?
|
||||
-span->len :
|
||||
span->len),
|
||||
ren_color,
|
||||
cover_full);
|
||||
if(--num_spans == 0) break;
|
||||
++span;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================renderer_scanline_bin_solid
|
||||
template<class BaseRenderer> class renderer_scanline_bin_solid
|
||||
{
|
||||
public:
|
||||
typedef BaseRenderer base_ren_type;
|
||||
typedef typename base_ren_type::color_type color_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_scanline_bin_solid() : m_ren(0) {}
|
||||
explicit renderer_scanline_bin_solid(base_ren_type& ren) : m_ren(&ren) {}
|
||||
void attach(base_ren_type& ren)
|
||||
{
|
||||
m_ren = &ren;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void color(const color_type& c) { m_color = c; }
|
||||
const color_type& color() const { return m_color; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Scanline> void render(const Scanline& sl)
|
||||
{
|
||||
render_scanline_bin_solid(sl, *m_ren, m_color);
|
||||
}
|
||||
|
||||
private:
|
||||
base_ren_type* m_ren;
|
||||
color_type m_color;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//======================================================render_scanline_bin
|
||||
template<class Scanline, class BaseRenderer,
|
||||
class SpanAllocator, class SpanGenerator>
|
||||
void render_scanline_bin(const Scanline& sl, BaseRenderer& ren,
|
||||
SpanAllocator& alloc, SpanGenerator& span_gen)
|
||||
{
|
||||
int y = sl.y();
|
||||
|
||||
unsigned num_spans = sl.num_spans();
|
||||
typename Scanline::const_iterator span = sl.begin();
|
||||
for(;;)
|
||||
{
|
||||
int x = span->x;
|
||||
int len = span->len;
|
||||
if(len < 0) len = -len;
|
||||
typename BaseRenderer::color_type* colors = alloc.allocate(len);
|
||||
span_gen.generate(colors, x, y, len);
|
||||
ren.blend_color_hspan(x, y, len, colors, 0, cover_full);
|
||||
if(--num_spans == 0) break;
|
||||
++span;
|
||||
}
|
||||
}
|
||||
|
||||
//=====================================================render_scanlines_bin
|
||||
template<class Rasterizer, class Scanline, class BaseRenderer,
|
||||
class SpanAllocator, class SpanGenerator>
|
||||
void render_scanlines_bin(Rasterizer& ras, Scanline& sl, BaseRenderer& ren,
|
||||
SpanAllocator& alloc, SpanGenerator& span_gen)
|
||||
{
|
||||
if(ras.rewind_scanlines())
|
||||
{
|
||||
sl.reset(ras.min_x(), ras.max_x());
|
||||
span_gen.prepare();
|
||||
while(ras.sweep_scanline(sl))
|
||||
{
|
||||
render_scanline_bin(sl, ren, alloc, span_gen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//====================================================renderer_scanline_bin
|
||||
template<class BaseRenderer, class SpanAllocator, class SpanGenerator>
|
||||
class renderer_scanline_bin
|
||||
{
|
||||
public:
|
||||
typedef BaseRenderer base_ren_type;
|
||||
typedef SpanAllocator alloc_type;
|
||||
typedef SpanGenerator span_gen_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
renderer_scanline_bin() : m_ren(0), m_alloc(0), m_span_gen(0) {}
|
||||
renderer_scanline_bin(base_ren_type& ren,
|
||||
alloc_type& alloc,
|
||||
span_gen_type& span_gen) :
|
||||
m_ren(&ren),
|
||||
m_alloc(&alloc),
|
||||
m_span_gen(&span_gen)
|
||||
{}
|
||||
void attach(base_ren_type& ren,
|
||||
alloc_type& alloc,
|
||||
span_gen_type& span_gen)
|
||||
{
|
||||
m_ren = &ren;
|
||||
m_alloc = &alloc;
|
||||
m_span_gen = &span_gen;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void prepare() { m_span_gen->prepare(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Scanline> void render(const Scanline& sl)
|
||||
{
|
||||
render_scanline_bin(sl, *m_ren, *m_alloc, *m_span_gen);
|
||||
}
|
||||
|
||||
private:
|
||||
base_ren_type* m_ren;
|
||||
alloc_type* m_alloc;
|
||||
span_gen_type* m_span_gen;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//========================================================render_scanlines
|
||||
template<class Rasterizer, class Scanline, class Renderer>
|
||||
void render_scanlines(Rasterizer& ras, Scanline& sl, Renderer& ren)
|
||||
{
|
||||
if(ras.rewind_scanlines())
|
||||
{
|
||||
sl.reset(ras.min_x(), ras.max_x());
|
||||
ren.prepare();
|
||||
while(ras.sweep_scanline(sl))
|
||||
{
|
||||
ren.render(sl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//========================================================render_all_paths
|
||||
template<class Rasterizer, class Scanline, class Renderer,
|
||||
class VertexSource, class ColorStorage, class PathId>
|
||||
void render_all_paths(Rasterizer& ras,
|
||||
Scanline& sl,
|
||||
Renderer& r,
|
||||
VertexSource& vs,
|
||||
const ColorStorage& as,
|
||||
const PathId& path_id,
|
||||
unsigned num_paths)
|
||||
{
|
||||
for(unsigned i = 0; i < num_paths; i++)
|
||||
{
|
||||
ras.reset();
|
||||
ras.add_path(vs, path_id[i]);
|
||||
r.color(as[i]);
|
||||
render_scanlines(ras, sl, r);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=============================================render_scanlines_compound
|
||||
template<class Rasterizer,
|
||||
class ScanlineAA,
|
||||
class ScanlineBin,
|
||||
class BaseRenderer,
|
||||
class SpanAllocator,
|
||||
class StyleHandler>
|
||||
void render_scanlines_compound(Rasterizer& ras,
|
||||
ScanlineAA& sl_aa,
|
||||
ScanlineBin& sl_bin,
|
||||
BaseRenderer& ren,
|
||||
SpanAllocator& alloc,
|
||||
StyleHandler& sh)
|
||||
{
|
||||
if(ras.rewind_scanlines())
|
||||
{
|
||||
int min_x = ras.min_x();
|
||||
int len = ras.max_x() - min_x + 2;
|
||||
sl_aa.reset(min_x, ras.max_x());
|
||||
sl_bin.reset(min_x, ras.max_x());
|
||||
|
||||
typedef typename BaseRenderer::color_type color_type;
|
||||
color_type* color_span = alloc.allocate(len * 2);
|
||||
color_type* mix_buffer = color_span + len;
|
||||
unsigned num_spans;
|
||||
|
||||
unsigned num_styles;
|
||||
unsigned style;
|
||||
bool solid;
|
||||
while((num_styles = ras.sweep_styles()) > 0)
|
||||
{
|
||||
typename ScanlineAA::const_iterator span_aa;
|
||||
if(num_styles == 1)
|
||||
{
|
||||
// Optimization for a single style. Happens often
|
||||
//-------------------------
|
||||
if(ras.sweep_scanline(sl_aa, 0))
|
||||
{
|
||||
style = ras.style(0);
|
||||
if(sh.is_solid(style))
|
||||
{
|
||||
// Just solid fill
|
||||
//-----------------------
|
||||
render_scanline_aa_solid(sl_aa, ren, sh.color(style));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Arbitrary span generator
|
||||
//-----------------------
|
||||
span_aa = sl_aa.begin();
|
||||
num_spans = sl_aa.num_spans();
|
||||
for(;;)
|
||||
{
|
||||
len = span_aa->len;
|
||||
sh.generate_span(color_span,
|
||||
span_aa->x,
|
||||
sl_aa.y(),
|
||||
len,
|
||||
style);
|
||||
|
||||
ren.blend_color_hspan(span_aa->x,
|
||||
sl_aa.y(),
|
||||
span_aa->len,
|
||||
color_span,
|
||||
span_aa->covers);
|
||||
if(--num_spans == 0) break;
|
||||
++span_aa;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ras.sweep_scanline(sl_bin, -1))
|
||||
{
|
||||
// Clear the spans of the mix_buffer
|
||||
//--------------------
|
||||
typename ScanlineBin::const_iterator span_bin = sl_bin.begin();
|
||||
num_spans = sl_bin.num_spans();
|
||||
for(;;)
|
||||
{
|
||||
memset(mix_buffer + span_bin->x - min_x,
|
||||
0,
|
||||
span_bin->len * sizeof(color_type));
|
||||
|
||||
if(--num_spans == 0) break;
|
||||
++span_bin;
|
||||
}
|
||||
|
||||
unsigned i;
|
||||
for(i = 0; i < num_styles; i++)
|
||||
{
|
||||
style = ras.style(i);
|
||||
solid = sh.is_solid(style);
|
||||
|
||||
if(ras.sweep_scanline(sl_aa, i))
|
||||
{
|
||||
color_type* colors;
|
||||
color_type* cspan;
|
||||
typename ScanlineAA::cover_type* covers;
|
||||
span_aa = sl_aa.begin();
|
||||
num_spans = sl_aa.num_spans();
|
||||
if(solid)
|
||||
{
|
||||
// Just solid fill
|
||||
//-----------------------
|
||||
for(;;)
|
||||
{
|
||||
color_type c = sh.color(style);
|
||||
len = span_aa->len;
|
||||
colors = mix_buffer + span_aa->x - min_x;
|
||||
covers = span_aa->covers;
|
||||
do
|
||||
{
|
||||
if(*covers == cover_full)
|
||||
{
|
||||
*colors = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
colors->add(c, *covers);
|
||||
}
|
||||
++colors;
|
||||
++covers;
|
||||
}
|
||||
while(--len);
|
||||
if(--num_spans == 0) break;
|
||||
++span_aa;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Arbitrary span generator
|
||||
//-----------------------
|
||||
for(;;)
|
||||
{
|
||||
len = span_aa->len;
|
||||
colors = mix_buffer + span_aa->x - min_x;
|
||||
cspan = color_span;
|
||||
sh.generate_span(cspan,
|
||||
span_aa->x,
|
||||
sl_aa.y(),
|
||||
len,
|
||||
style);
|
||||
covers = span_aa->covers;
|
||||
do
|
||||
{
|
||||
if(*covers == cover_full)
|
||||
{
|
||||
*colors = *cspan;
|
||||
}
|
||||
else
|
||||
{
|
||||
colors->add(*cspan, *covers);
|
||||
}
|
||||
++cspan;
|
||||
++colors;
|
||||
++covers;
|
||||
}
|
||||
while(--len);
|
||||
if(--num_spans == 0) break;
|
||||
++span_aa;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Emit the blended result as a color hspan
|
||||
//-------------------------
|
||||
span_bin = sl_bin.begin();
|
||||
num_spans = sl_bin.num_spans();
|
||||
for(;;)
|
||||
{
|
||||
ren.blend_color_hspan(span_bin->x,
|
||||
sl_bin.y(),
|
||||
span_bin->len,
|
||||
mix_buffer + span_bin->x - min_x,
|
||||
0,
|
||||
cover_full);
|
||||
if(--num_spans == 0) break;
|
||||
++span_bin;
|
||||
}
|
||||
} // if(ras.sweep_scanline(sl_bin, -1))
|
||||
} // if(num_styles == 1) ... else
|
||||
} // while((num_styles = ras.sweep_styles()) > 0)
|
||||
} // if(ras.rewind_scanlines())
|
||||
}
|
||||
|
||||
//=======================================render_scanlines_compound_layered
|
||||
template<class Rasterizer,
|
||||
class ScanlineAA,
|
||||
class BaseRenderer,
|
||||
class SpanAllocator,
|
||||
class StyleHandler>
|
||||
void render_scanlines_compound_layered(Rasterizer& ras,
|
||||
ScanlineAA& sl_aa,
|
||||
BaseRenderer& ren,
|
||||
SpanAllocator& alloc,
|
||||
StyleHandler& sh)
|
||||
{
|
||||
if(ras.rewind_scanlines())
|
||||
{
|
||||
int min_x = ras.min_x();
|
||||
int len = ras.max_x() - min_x + 2;
|
||||
sl_aa.reset(min_x, ras.max_x());
|
||||
|
||||
typedef typename BaseRenderer::color_type color_type;
|
||||
color_type* color_span = alloc.allocate(len * 2);
|
||||
color_type* mix_buffer = color_span + len;
|
||||
cover_type* cover_buffer = ras.allocate_cover_buffer(len);
|
||||
unsigned num_spans;
|
||||
|
||||
unsigned num_styles;
|
||||
unsigned style;
|
||||
bool solid;
|
||||
while((num_styles = ras.sweep_styles()) > 0)
|
||||
{
|
||||
typename ScanlineAA::const_iterator span_aa;
|
||||
if(num_styles == 1)
|
||||
{
|
||||
// Optimization for a single style. Happens often
|
||||
//-------------------------
|
||||
if(ras.sweep_scanline(sl_aa, 0))
|
||||
{
|
||||
style = ras.style(0);
|
||||
if(sh.is_solid(style))
|
||||
{
|
||||
// Just solid fill
|
||||
//-----------------------
|
||||
render_scanline_aa_solid(sl_aa, ren, sh.color(style));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Arbitrary span generator
|
||||
//-----------------------
|
||||
span_aa = sl_aa.begin();
|
||||
num_spans = sl_aa.num_spans();
|
||||
for(;;)
|
||||
{
|
||||
len = span_aa->len;
|
||||
sh.generate_span(color_span,
|
||||
span_aa->x,
|
||||
sl_aa.y(),
|
||||
len,
|
||||
style);
|
||||
|
||||
ren.blend_color_hspan(span_aa->x,
|
||||
sl_aa.y(),
|
||||
span_aa->len,
|
||||
color_span,
|
||||
span_aa->covers);
|
||||
if(--num_spans == 0) break;
|
||||
++span_aa;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int sl_start = ras.scanline_start();
|
||||
unsigned sl_len = ras.scanline_length();
|
||||
|
||||
if(sl_len)
|
||||
{
|
||||
memset(mix_buffer + sl_start - min_x,
|
||||
0,
|
||||
sl_len * sizeof(color_type));
|
||||
|
||||
memset(cover_buffer + sl_start - min_x,
|
||||
0,
|
||||
sl_len * sizeof(cover_type));
|
||||
|
||||
int sl_y = 0x7FFFFFFF;
|
||||
unsigned i;
|
||||
for(i = 0; i < num_styles; i++)
|
||||
{
|
||||
style = ras.style(i);
|
||||
solid = sh.is_solid(style);
|
||||
|
||||
if(ras.sweep_scanline(sl_aa, i))
|
||||
{
|
||||
unsigned cover;
|
||||
color_type* colors;
|
||||
color_type* cspan;
|
||||
cover_type* src_covers;
|
||||
cover_type* dst_covers;
|
||||
span_aa = sl_aa.begin();
|
||||
num_spans = sl_aa.num_spans();
|
||||
sl_y = sl_aa.y();
|
||||
if(solid)
|
||||
{
|
||||
// Just solid fill
|
||||
//-----------------------
|
||||
for(;;)
|
||||
{
|
||||
color_type c = sh.color(style);
|
||||
len = span_aa->len;
|
||||
colors = mix_buffer + span_aa->x - min_x;
|
||||
src_covers = span_aa->covers;
|
||||
dst_covers = cover_buffer + span_aa->x - min_x;
|
||||
do
|
||||
{
|
||||
cover = *src_covers;
|
||||
if(*dst_covers + cover > cover_full)
|
||||
{
|
||||
cover = cover_full - *dst_covers;
|
||||
}
|
||||
if(cover)
|
||||
{
|
||||
colors->add(c, cover);
|
||||
*dst_covers += cover;
|
||||
}
|
||||
++colors;
|
||||
++src_covers;
|
||||
++dst_covers;
|
||||
}
|
||||
while(--len);
|
||||
if(--num_spans == 0) break;
|
||||
++span_aa;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Arbitrary span generator
|
||||
//-----------------------
|
||||
for(;;)
|
||||
{
|
||||
len = span_aa->len;
|
||||
colors = mix_buffer + span_aa->x - min_x;
|
||||
cspan = color_span;
|
||||
sh.generate_span(cspan,
|
||||
span_aa->x,
|
||||
sl_aa.y(),
|
||||
len,
|
||||
style);
|
||||
src_covers = span_aa->covers;
|
||||
dst_covers = cover_buffer + span_aa->x - min_x;
|
||||
do
|
||||
{
|
||||
cover = *src_covers;
|
||||
if(*dst_covers + cover > cover_full)
|
||||
{
|
||||
cover = cover_full - *dst_covers;
|
||||
}
|
||||
if(cover)
|
||||
{
|
||||
colors->add(*cspan, cover);
|
||||
*dst_covers += cover;
|
||||
}
|
||||
++cspan;
|
||||
++colors;
|
||||
++src_covers;
|
||||
++dst_covers;
|
||||
}
|
||||
while(--len);
|
||||
if(--num_spans == 0) break;
|
||||
++span_aa;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ren.blend_color_hspan(sl_start,
|
||||
sl_y,
|
||||
sl_len,
|
||||
mix_buffer + sl_start - min_x,
|
||||
0,
|
||||
cover_full);
|
||||
} //if(sl_len)
|
||||
} //if(num_styles == 1) ... else
|
||||
} //while((num_styles = ras.sweep_styles()) > 0)
|
||||
} //if(ras.rewind_scanlines())
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,305 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RENDERING_BUFFER_INCLUDED
|
||||
#define AGG_RENDERING_BUFFER_INCLUDED
|
||||
|
||||
#include "agg_array.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//===========================================================row_accessor
|
||||
template<class T> class row_accessor
|
||||
{
|
||||
public:
|
||||
typedef const_row_info<T> row_data;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
row_accessor() :
|
||||
m_buf(0),
|
||||
m_start(0),
|
||||
m_width(0),
|
||||
m_height(0),
|
||||
m_stride(0)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_accessor(T* buf, unsigned width, unsigned height, int stride) :
|
||||
m_buf(0),
|
||||
m_start(0),
|
||||
m_width(0),
|
||||
m_height(0),
|
||||
m_stride(0)
|
||||
{
|
||||
attach(buf, width, height, stride);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void attach(T* buf, unsigned width, unsigned height, int stride)
|
||||
{
|
||||
m_buf = m_start = buf;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_stride = stride;
|
||||
if(stride < 0)
|
||||
{
|
||||
m_start = m_buf - int(height - 1) * stride;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE T* buf() { return m_buf; }
|
||||
AGG_INLINE const T* buf() const { return m_buf; }
|
||||
AGG_INLINE unsigned width() const { return m_width; }
|
||||
AGG_INLINE unsigned height() const { return m_height; }
|
||||
AGG_INLINE int stride() const { return m_stride; }
|
||||
AGG_INLINE unsigned stride_abs() const
|
||||
{
|
||||
return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE T* row_ptr(int, int y, unsigned)
|
||||
{
|
||||
return m_start + y * m_stride;
|
||||
}
|
||||
AGG_INLINE T* row_ptr(int y) { return m_start + y * m_stride; }
|
||||
AGG_INLINE const T* row_ptr(int y) const { return m_start + y * m_stride; }
|
||||
AGG_INLINE row_data row (int y) const
|
||||
{
|
||||
return row_data(0, m_width-1, row_ptr(y));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class RenBuf>
|
||||
void copy_from(const RenBuf& src)
|
||||
{
|
||||
unsigned h = height();
|
||||
if(src.height() < h) h = src.height();
|
||||
|
||||
unsigned l = stride_abs();
|
||||
if(src.stride_abs() < l) l = src.stride_abs();
|
||||
|
||||
l *= sizeof(T);
|
||||
|
||||
unsigned y;
|
||||
unsigned w = width();
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
memcpy(row_ptr(0, y, w), src.row_ptr(y), l);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clear(T value)
|
||||
{
|
||||
unsigned y;
|
||||
unsigned w = width();
|
||||
unsigned stride = stride_abs();
|
||||
for(y = 0; y < height(); y++)
|
||||
{
|
||||
T* p = row_ptr(0, y, w);
|
||||
unsigned x;
|
||||
for(x = 0; x < stride; x++)
|
||||
{
|
||||
*p++ = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
T* m_buf; // Pointer to renrdering buffer
|
||||
T* m_start; // Pointer to first pixel depending on stride
|
||||
unsigned m_width; // Width in pixels
|
||||
unsigned m_height; // Height in pixels
|
||||
int m_stride; // Number of bytes per row. Can be < 0
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//==========================================================row_ptr_cache
|
||||
template<class T> class row_ptr_cache
|
||||
{
|
||||
public:
|
||||
typedef const_row_info<T> row_data;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
row_ptr_cache() :
|
||||
m_buf(0),
|
||||
m_rows(),
|
||||
m_width(0),
|
||||
m_height(0),
|
||||
m_stride(0)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_ptr_cache(T* buf, unsigned width, unsigned height, int stride) :
|
||||
m_buf(0),
|
||||
m_rows(),
|
||||
m_width(0),
|
||||
m_height(0),
|
||||
m_stride(0)
|
||||
{
|
||||
attach(buf, width, height, stride);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void attach(T* buf, unsigned width, unsigned height, int stride)
|
||||
{
|
||||
m_buf = buf;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_stride = stride;
|
||||
if(height > m_rows.size())
|
||||
{
|
||||
m_rows.resize(height);
|
||||
}
|
||||
|
||||
T* row_ptr = m_buf;
|
||||
|
||||
if(stride < 0)
|
||||
{
|
||||
row_ptr = m_buf - int(height - 1) * stride;
|
||||
}
|
||||
|
||||
T** rows = &m_rows[0];
|
||||
|
||||
while(height--)
|
||||
{
|
||||
*rows++ = row_ptr;
|
||||
row_ptr += stride;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE T* buf() { return m_buf; }
|
||||
AGG_INLINE const T* buf() const { return m_buf; }
|
||||
AGG_INLINE unsigned width() const { return m_width; }
|
||||
AGG_INLINE unsigned height() const { return m_height; }
|
||||
AGG_INLINE int stride() const { return m_stride; }
|
||||
AGG_INLINE unsigned stride_abs() const
|
||||
{
|
||||
return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE T* row_ptr(int, int y, unsigned)
|
||||
{
|
||||
return m_rows[y];
|
||||
}
|
||||
AGG_INLINE T* row_ptr(int y) { return m_rows[y]; }
|
||||
AGG_INLINE const T* row_ptr(int y) const { return m_rows[y]; }
|
||||
AGG_INLINE row_data row (int y) const
|
||||
{
|
||||
return row_data(0, m_width-1, m_rows[y]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
T const* const* rows() const { return &m_rows[0]; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class RenBuf>
|
||||
void copy_from(const RenBuf& src)
|
||||
{
|
||||
unsigned h = height();
|
||||
if(src.height() < h) h = src.height();
|
||||
|
||||
unsigned l = stride_abs();
|
||||
if(src.stride_abs() < l) l = src.stride_abs();
|
||||
|
||||
l *= sizeof(T);
|
||||
|
||||
unsigned y;
|
||||
unsigned w = width();
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
memcpy(row_ptr(0, y, w), src.row_ptr(y), l);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clear(T value)
|
||||
{
|
||||
unsigned y;
|
||||
unsigned w = width();
|
||||
unsigned stride = stride_abs();
|
||||
for(y = 0; y < height(); y++)
|
||||
{
|
||||
T* p = row_ptr(0, y, w);
|
||||
unsigned x;
|
||||
for(x = 0; x < stride; x++)
|
||||
{
|
||||
*p++ = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
T* m_buf; // Pointer to renrdering buffer
|
||||
pod_array<T*> m_rows; // Pointers to each row of the buffer
|
||||
unsigned m_width; // Width in pixels
|
||||
unsigned m_height; // Height in pixels
|
||||
int m_stride; // Number of bytes per row. Can be < 0
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//========================================================rendering_buffer
|
||||
//
|
||||
// The definition of the main type for accessing the rows in the frame
|
||||
// buffer. It provides functionality to navigate to the rows in a
|
||||
// rectangular matrix, from top to bottom or from bottom to top depending
|
||||
// on stride.
|
||||
//
|
||||
// row_accessor is cheap to create/destroy, but performs one multiplication
|
||||
// when calling row_ptr().
|
||||
//
|
||||
// row_ptr_cache creates an array of pointers to rows, so, the access
|
||||
// via row_ptr() may be faster. But it requires memory allocation
|
||||
// when creating. For example, on typical Intel Pentium hardware
|
||||
// row_ptr_cache speeds span_image_filter_rgb_nn up to 10%
|
||||
//
|
||||
// It's used only in short hand typedefs like pixfmt_rgba32 and can be
|
||||
// redefined in agg_config.h
|
||||
// In real applications you can use both, depending on your needs
|
||||
//------------------------------------------------------------------------
|
||||
#ifdef AGG_RENDERING_BUFFER
|
||||
typedef AGG_RENDERING_BUFFER rendering_buffer;
|
||||
#else
|
||||
// typedef row_ptr_cache<int8u> rendering_buffer;
|
||||
typedef row_accessor<int8u> rendering_buffer;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,142 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RENDERING_BUFFER_DYNAROW_INCLUDED
|
||||
#define AGG_RENDERING_BUFFER_DYNAROW_INCLUDED
|
||||
|
||||
#include "agg_array.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//===============================================rendering_buffer_dynarow
|
||||
// Rendering buffer class with dynamic allocation of the rows.
|
||||
// The rows are allocated as needed when requesting for span_ptr().
|
||||
// The class automatically calculates min_x and max_x for each row.
|
||||
// Generally it's more efficient to use this class as a temporary buffer
|
||||
// for rendering a few lines and then to blend it with another buffer.
|
||||
//
|
||||
class rendering_buffer_dynarow
|
||||
{
|
||||
public:
|
||||
typedef row_info<int8u> row_data;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
~rendering_buffer_dynarow()
|
||||
{
|
||||
init(0,0,0);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
rendering_buffer_dynarow() :
|
||||
m_rows(),
|
||||
m_width(0),
|
||||
m_height(0),
|
||||
m_byte_width(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Allocate and clear the buffer
|
||||
//--------------------------------------------------------------------
|
||||
rendering_buffer_dynarow(unsigned width, unsigned height,
|
||||
unsigned byte_width) :
|
||||
m_rows(height),
|
||||
m_width(width),
|
||||
m_height(height),
|
||||
m_byte_width(byte_width)
|
||||
{
|
||||
memset(&m_rows[0], 0, sizeof(row_data) * height);
|
||||
}
|
||||
|
||||
// Allocate and clear the buffer
|
||||
//--------------------------------------------------------------------
|
||||
void init(unsigned width, unsigned height, unsigned byte_width)
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < m_height; ++i)
|
||||
{
|
||||
pod_allocator<int8u>::deallocate((int8u*)m_rows[i].ptr, m_byte_width);
|
||||
}
|
||||
if(width && height)
|
||||
{
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_byte_width = byte_width;
|
||||
m_rows.resize(height);
|
||||
memset(&m_rows[0], 0, sizeof(row_data) * height);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned width() const { return m_width; }
|
||||
unsigned height() const { return m_height; }
|
||||
unsigned byte_width() const { return m_byte_width; }
|
||||
|
||||
// The main function used for rendering. Returns pointer to the
|
||||
// pre-allocated span. Memory for the row is allocated as needed.
|
||||
//--------------------------------------------------------------------
|
||||
int8u* row_ptr(int x, int y, unsigned len)
|
||||
{
|
||||
row_data* r = &m_rows[y];
|
||||
int x2 = x + len - 1;
|
||||
if(r->ptr)
|
||||
{
|
||||
if(x < r->x1) { r->x1 = x; }
|
||||
if(x2 > r->x2) { r->x2 = x2; }
|
||||
}
|
||||
else
|
||||
{
|
||||
int8u* p = pod_allocator<int8u>::allocate(m_byte_width);
|
||||
r->ptr = p;
|
||||
r->x1 = x;
|
||||
r->x2 = x2;
|
||||
memset(p, 0, m_byte_width);
|
||||
}
|
||||
return (int8u*)r->ptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const int8u* row_ptr(int y) const { return m_rows[y].ptr; }
|
||||
int8u* row_ptr(int y) { return row_ptr(0, y, m_width); }
|
||||
row_data row (int y) const { return m_rows[y]; }
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
// Prohibit copying
|
||||
rendering_buffer_dynarow(const rendering_buffer_dynarow&);
|
||||
const rendering_buffer_dynarow& operator = (const rendering_buffer_dynarow&);
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
pod_array<row_data> m_rows; // Pointers to each row of the buffer
|
||||
unsigned m_width; // Width in pixels
|
||||
unsigned m_height; // Height in pixels
|
||||
unsigned m_byte_width; // Width in bytes
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,77 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_ROUNDED_RECT_INCLUDED
|
||||
#define AGG_ROUNDED_RECT_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_arc.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//------------------------------------------------------------rounded_rect
|
||||
//
|
||||
// See Implemantation agg_rounded_rect.cpp
|
||||
//
|
||||
class rounded_rect
|
||||
{
|
||||
public:
|
||||
rounded_rect() {}
|
||||
rounded_rect(double x1, double y1, double x2, double y2, double r);
|
||||
|
||||
void rect(double x1, double y1, double x2, double y2);
|
||||
void radius(double r);
|
||||
void radius(double rx, double ry);
|
||||
void radius(double rx_bottom, double ry_bottom, double rx_top, double ry_top);
|
||||
void radius(double rx1, double ry1, double rx2, double ry2,
|
||||
double rx3, double ry3, double rx4, double ry4);
|
||||
void normalize_radius();
|
||||
|
||||
void approximation_scale(double s) { m_arc.approximation_scale(s); }
|
||||
double approximation_scale() const { return m_arc.approximation_scale(); }
|
||||
|
||||
void rewind(unsigned);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
double m_x1;
|
||||
double m_y1;
|
||||
double m_x2;
|
||||
double m_y2;
|
||||
double m_rx1;
|
||||
double m_ry1;
|
||||
double m_rx2;
|
||||
double m_ry2;
|
||||
double m_rx3;
|
||||
double m_ry3;
|
||||
double m_rx4;
|
||||
double m_ry4;
|
||||
unsigned m_status;
|
||||
arc m_arc;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,269 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for 32-bit screen coordinates (scanline32_bin) has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_SCANLINE_BIN_INCLUDED
|
||||
#define AGG_SCANLINE_BIN_INCLUDED
|
||||
|
||||
#include "agg_array.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=============================================================scanline_bin
|
||||
//
|
||||
// This is binary scaline container which supports the interface
|
||||
// used in the rasterizer::render(). See description of agg_scanline_u8
|
||||
// for details.
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
class scanline_bin
|
||||
{
|
||||
public:
|
||||
typedef int32 coord_type;
|
||||
|
||||
struct span
|
||||
{
|
||||
int16 x;
|
||||
int16 len;
|
||||
};
|
||||
|
||||
typedef const span* const_iterator;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
scanline_bin() :
|
||||
m_last_x(0x7FFFFFF0),
|
||||
m_spans(),
|
||||
m_cur_span(0)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset(int min_x, int max_x)
|
||||
{
|
||||
unsigned max_len = max_x - min_x + 3;
|
||||
if(max_len > m_spans.size())
|
||||
{
|
||||
m_spans.resize(max_len);
|
||||
}
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_cur_span = &m_spans[0];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_cell(int x, unsigned)
|
||||
{
|
||||
if(x == m_last_x+1)
|
||||
{
|
||||
m_cur_span->len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
++m_cur_span;
|
||||
m_cur_span->x = (int16)x;
|
||||
m_cur_span->len = 1;
|
||||
}
|
||||
m_last_x = x;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_span(int x, unsigned len, unsigned)
|
||||
{
|
||||
if(x == m_last_x+1)
|
||||
{
|
||||
m_cur_span->len = (int16)(m_cur_span->len + len);
|
||||
}
|
||||
else
|
||||
{
|
||||
++m_cur_span;
|
||||
m_cur_span->x = (int16)x;
|
||||
m_cur_span->len = (int16)len;
|
||||
}
|
||||
m_last_x = x + len - 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_cells(int x, unsigned len, const void*)
|
||||
{
|
||||
add_span(x, len, 0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void finalize(int y)
|
||||
{
|
||||
m_y = y;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset_spans()
|
||||
{
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_cur_span = &m_spans[0];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int y() const { return m_y; }
|
||||
unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
|
||||
const_iterator begin() const { return &m_spans[1]; }
|
||||
|
||||
private:
|
||||
scanline_bin(const scanline_bin&);
|
||||
const scanline_bin operator = (const scanline_bin&);
|
||||
|
||||
int m_last_x;
|
||||
int m_y;
|
||||
pod_array<span> m_spans;
|
||||
span* m_cur_span;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===========================================================scanline32_bin
|
||||
class scanline32_bin
|
||||
{
|
||||
public:
|
||||
typedef int32 coord_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
struct span
|
||||
{
|
||||
span() {}
|
||||
span(coord_type x_, coord_type len_) : x(x_), len(len_) {}
|
||||
|
||||
coord_type x;
|
||||
coord_type len;
|
||||
};
|
||||
typedef pod_bvector<span, 4> span_array_type;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
class const_iterator
|
||||
{
|
||||
public:
|
||||
const_iterator(const span_array_type& spans) :
|
||||
m_spans(spans),
|
||||
m_span_idx(0)
|
||||
{}
|
||||
|
||||
const span& operator*() const { return m_spans[m_span_idx]; }
|
||||
const span* operator->() const { return &m_spans[m_span_idx]; }
|
||||
|
||||
void operator ++ () { ++m_span_idx; }
|
||||
|
||||
private:
|
||||
const span_array_type& m_spans;
|
||||
unsigned m_span_idx;
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
scanline32_bin() : m_max_len(0), m_last_x(0x7FFFFFF0) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset(int min_x, int max_x)
|
||||
{
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_spans.remove_all();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_cell(int x, unsigned)
|
||||
{
|
||||
if(x == m_last_x+1)
|
||||
{
|
||||
m_spans.last().len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_spans.add(span(coord_type(x), 1));
|
||||
}
|
||||
m_last_x = x;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_span(int x, unsigned len, unsigned)
|
||||
{
|
||||
if(x == m_last_x+1)
|
||||
{
|
||||
m_spans.last().len += coord_type(len);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_spans.add(span(coord_type(x), coord_type(len)));
|
||||
}
|
||||
m_last_x = x + len - 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_cells(int x, unsigned len, const void*)
|
||||
{
|
||||
add_span(x, len, 0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void finalize(int y)
|
||||
{
|
||||
m_y = y;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset_spans()
|
||||
{
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_spans.remove_all();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int y() const { return m_y; }
|
||||
unsigned num_spans() const { return m_spans.size(); }
|
||||
const_iterator begin() const { return const_iterator(m_spans); }
|
||||
|
||||
private:
|
||||
scanline32_bin(const scanline32_bin&);
|
||||
const scanline32_bin operator = (const scanline32_bin&);
|
||||
|
||||
unsigned m_max_len;
|
||||
int m_last_x;
|
||||
int m_y;
|
||||
span_array_type m_spans;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,334 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for 32-bit screen coordinates (scanline32_p) has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_SCANLINE_P_INCLUDED
|
||||
#define AGG_SCANLINE_P_INCLUDED
|
||||
|
||||
#include "agg_array.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=============================================================scanline_p8
|
||||
//
|
||||
// This is a general purpose scaline container which supports the interface
|
||||
// used in the rasterizer::render(). See description of scanline_u8
|
||||
// for details.
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
class scanline_p8
|
||||
{
|
||||
public:
|
||||
typedef scanline_p8 self_type;
|
||||
typedef int8u cover_type;
|
||||
typedef int16 coord_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
struct span
|
||||
{
|
||||
coord_type x;
|
||||
coord_type len; // If negative, it's a solid span, covers is valid
|
||||
const cover_type* covers;
|
||||
};
|
||||
|
||||
typedef span* iterator;
|
||||
typedef const span* const_iterator;
|
||||
|
||||
scanline_p8() :
|
||||
m_last_x(0x7FFFFFF0),
|
||||
m_covers(),
|
||||
m_cover_ptr(0),
|
||||
m_spans(),
|
||||
m_cur_span(0)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset(int min_x, int max_x)
|
||||
{
|
||||
unsigned max_len = max_x - min_x + 3;
|
||||
if(max_len > m_spans.size())
|
||||
{
|
||||
m_spans.resize(max_len);
|
||||
m_covers.resize(max_len);
|
||||
}
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_cover_ptr = &m_covers[0];
|
||||
m_cur_span = &m_spans[0];
|
||||
m_cur_span->len = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_cell(int x, unsigned cover)
|
||||
{
|
||||
*m_cover_ptr = (cover_type)cover;
|
||||
if(x == m_last_x+1 && m_cur_span->len > 0)
|
||||
{
|
||||
m_cur_span->len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cur_span++;
|
||||
m_cur_span->covers = m_cover_ptr;
|
||||
m_cur_span->x = (int16)x;
|
||||
m_cur_span->len = 1;
|
||||
}
|
||||
m_last_x = x;
|
||||
m_cover_ptr++;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_cells(int x, unsigned len, const cover_type* covers)
|
||||
{
|
||||
memcpy(m_cover_ptr, covers, len * sizeof(cover_type));
|
||||
if(x == m_last_x+1 && m_cur_span->len > 0)
|
||||
{
|
||||
m_cur_span->len += (int16)len;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cur_span++;
|
||||
m_cur_span->covers = m_cover_ptr;
|
||||
m_cur_span->x = (int16)x;
|
||||
m_cur_span->len = (int16)len;
|
||||
}
|
||||
m_cover_ptr += len;
|
||||
m_last_x = x + len - 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_span(int x, unsigned len, unsigned cover)
|
||||
{
|
||||
if(x == m_last_x+1 &&
|
||||
m_cur_span->len < 0 &&
|
||||
cover == *m_cur_span->covers)
|
||||
{
|
||||
m_cur_span->len -= (int16)len;
|
||||
}
|
||||
else
|
||||
{
|
||||
*m_cover_ptr = (cover_type)cover;
|
||||
m_cur_span++;
|
||||
m_cur_span->covers = m_cover_ptr++;
|
||||
m_cur_span->x = (int16)x;
|
||||
m_cur_span->len = (int16)(-int(len));
|
||||
}
|
||||
m_last_x = x + len - 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void finalize(int y)
|
||||
{
|
||||
m_y = y;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset_spans()
|
||||
{
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_cover_ptr = &m_covers[0];
|
||||
m_cur_span = &m_spans[0];
|
||||
m_cur_span->len = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int y() const { return m_y; }
|
||||
unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
|
||||
const_iterator begin() const { return &m_spans[1]; }
|
||||
|
||||
private:
|
||||
scanline_p8(const self_type&);
|
||||
const self_type& operator = (const self_type&);
|
||||
|
||||
int m_last_x;
|
||||
int m_y;
|
||||
pod_array<cover_type> m_covers;
|
||||
cover_type* m_cover_ptr;
|
||||
pod_array<span> m_spans;
|
||||
span* m_cur_span;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//==========================================================scanline32_p8
|
||||
class scanline32_p8
|
||||
{
|
||||
public:
|
||||
typedef scanline32_p8 self_type;
|
||||
typedef int8u cover_type;
|
||||
typedef int32 coord_type;
|
||||
|
||||
struct span
|
||||
{
|
||||
span() {}
|
||||
span(coord_type x_, coord_type len_, const cover_type* covers_) :
|
||||
x(x_), len(len_), covers(covers_) {}
|
||||
|
||||
coord_type x;
|
||||
coord_type len; // If negative, it's a solid span, covers is valid
|
||||
const cover_type* covers;
|
||||
};
|
||||
typedef pod_bvector<span, 4> span_array_type;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
class const_iterator
|
||||
{
|
||||
public:
|
||||
const_iterator(const span_array_type& spans) :
|
||||
m_spans(spans),
|
||||
m_span_idx(0)
|
||||
{}
|
||||
|
||||
const span& operator*() const { return m_spans[m_span_idx]; }
|
||||
const span* operator->() const { return &m_spans[m_span_idx]; }
|
||||
|
||||
void operator ++ () { ++m_span_idx; }
|
||||
|
||||
private:
|
||||
const span_array_type& m_spans;
|
||||
unsigned m_span_idx;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
scanline32_p8() :
|
||||
m_max_len(0),
|
||||
m_last_x(0x7FFFFFF0),
|
||||
m_covers(),
|
||||
m_cover_ptr(0)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset(int min_x, int max_x)
|
||||
{
|
||||
unsigned max_len = max_x - min_x + 3;
|
||||
if(max_len > m_covers.size())
|
||||
{
|
||||
m_covers.resize(max_len);
|
||||
}
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_cover_ptr = &m_covers[0];
|
||||
m_spans.remove_all();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_cell(int x, unsigned cover)
|
||||
{
|
||||
*m_cover_ptr = cover_type(cover);
|
||||
if(x == m_last_x+1 && m_spans.size() && m_spans.last().len > 0)
|
||||
{
|
||||
m_spans.last().len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_spans.add(span(coord_type(x), 1, m_cover_ptr));
|
||||
}
|
||||
m_last_x = x;
|
||||
m_cover_ptr++;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_cells(int x, unsigned len, const cover_type* covers)
|
||||
{
|
||||
memcpy(m_cover_ptr, covers, len * sizeof(cover_type));
|
||||
if(x == m_last_x+1 && m_spans.size() && m_spans.last().len > 0)
|
||||
{
|
||||
m_spans.last().len += coord_type(len);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_spans.add(span(coord_type(x), coord_type(len), m_cover_ptr));
|
||||
}
|
||||
m_cover_ptr += len;
|
||||
m_last_x = x + len - 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_span(int x, unsigned len, unsigned cover)
|
||||
{
|
||||
if(x == m_last_x+1 &&
|
||||
m_spans.size() &&
|
||||
m_spans.last().len < 0 &&
|
||||
cover == *m_spans.last().covers)
|
||||
{
|
||||
m_spans.last().len -= coord_type(len);
|
||||
}
|
||||
else
|
||||
{
|
||||
*m_cover_ptr = cover_type(cover);
|
||||
m_spans.add(span(coord_type(x), -coord_type(len), m_cover_ptr++));
|
||||
}
|
||||
m_last_x = x + len - 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void finalize(int y)
|
||||
{
|
||||
m_y = y;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset_spans()
|
||||
{
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_cover_ptr = &m_covers[0];
|
||||
m_spans.remove_all();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int y() const { return m_y; }
|
||||
unsigned num_spans() const { return m_spans.size(); }
|
||||
const_iterator begin() const { return const_iterator(m_spans); }
|
||||
|
||||
private:
|
||||
scanline32_p8(const self_type&);
|
||||
const self_type& operator = (const self_type&);
|
||||
|
||||
unsigned m_max_len;
|
||||
int m_last_x;
|
||||
int m_y;
|
||||
pod_array<cover_type> m_covers;
|
||||
cover_type* m_cover_ptr;
|
||||
span_array_type m_spans;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,824 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for 32-bit screen coordinates has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_SCANLINE_STORAGE_AA_INCLUDED
|
||||
#define AGG_SCANLINE_STORAGE_AA_INCLUDED
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "agg_array.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//----------------------------------------------scanline_cell_storage
|
||||
template<class T> class scanline_cell_storage
|
||||
{
|
||||
struct extra_span
|
||||
{
|
||||
unsigned len;
|
||||
T* ptr;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
//---------------------------------------------------------------
|
||||
~scanline_cell_storage()
|
||||
{
|
||||
remove_all();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
scanline_cell_storage() :
|
||||
m_cells(128-2),
|
||||
m_extra_storage()
|
||||
{}
|
||||
|
||||
|
||||
// Copying
|
||||
//---------------------------------------------------------------
|
||||
scanline_cell_storage(const scanline_cell_storage<T>& v) :
|
||||
m_cells(v.m_cells),
|
||||
m_extra_storage()
|
||||
{
|
||||
copy_extra_storage(v);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
const scanline_cell_storage<T>&
|
||||
operator = (const scanline_cell_storage<T>& v)
|
||||
{
|
||||
remove_all();
|
||||
m_cells = v.m_cells;
|
||||
copy_extra_storage(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
void remove_all()
|
||||
{
|
||||
int i;
|
||||
for(i = m_extra_storage.size()-1; i >= 0; --i)
|
||||
{
|
||||
pod_allocator<T>::deallocate(m_extra_storage[i].ptr,
|
||||
m_extra_storage[i].len);
|
||||
}
|
||||
m_extra_storage.remove_all();
|
||||
m_cells.remove_all();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
int add_cells(const T* cells, unsigned num_cells)
|
||||
{
|
||||
int idx = m_cells.allocate_continuous_block(num_cells);
|
||||
if(idx >= 0)
|
||||
{
|
||||
T* ptr = &m_cells[idx];
|
||||
memcpy(ptr, cells, sizeof(T) * num_cells);
|
||||
return idx;
|
||||
}
|
||||
extra_span s;
|
||||
s.len = num_cells;
|
||||
s.ptr = pod_allocator<T>::allocate(num_cells);
|
||||
memcpy(s.ptr, cells, sizeof(T) * num_cells);
|
||||
m_extra_storage.add(s);
|
||||
return -int(m_extra_storage.size());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
const T* operator [] (int idx) const
|
||||
{
|
||||
if(idx >= 0)
|
||||
{
|
||||
if((unsigned)idx >= m_cells.size()) return 0;
|
||||
return &m_cells[(unsigned)idx];
|
||||
}
|
||||
unsigned i = unsigned(-idx - 1);
|
||||
if(i >= m_extra_storage.size()) return 0;
|
||||
return m_extra_storage[i].ptr;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
T* operator [] (int idx)
|
||||
{
|
||||
if(idx >= 0)
|
||||
{
|
||||
if((unsigned)idx >= m_cells.size()) return 0;
|
||||
return &m_cells[(unsigned)idx];
|
||||
}
|
||||
unsigned i = unsigned(-idx - 1);
|
||||
if(i >= m_extra_storage.size()) return 0;
|
||||
return m_extra_storage[i].ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
void copy_extra_storage(const scanline_cell_storage<T>& v)
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < v.m_extra_storage.size(); ++i)
|
||||
{
|
||||
const extra_span& src = v.m_extra_storage[i];
|
||||
extra_span dst;
|
||||
dst.len = src.len;
|
||||
dst.ptr = pod_allocator<T>::allocate(dst.len);
|
||||
memcpy(dst.ptr, src.ptr, dst.len * sizeof(T));
|
||||
m_extra_storage.add(dst);
|
||||
}
|
||||
}
|
||||
|
||||
pod_bvector<T, 12> m_cells;
|
||||
pod_bvector<extra_span, 6> m_extra_storage;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------scanline_storage_aa
|
||||
template<class T> class scanline_storage_aa
|
||||
{
|
||||
public:
|
||||
typedef T cover_type;
|
||||
|
||||
//---------------------------------------------------------------
|
||||
struct span_data
|
||||
{
|
||||
int32 x;
|
||||
int32 len; // If negative, it's a solid span, covers is valid
|
||||
int covers_id; // The index of the cells in the scanline_cell_storage
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------
|
||||
struct scanline_data
|
||||
{
|
||||
int y;
|
||||
unsigned num_spans;
|
||||
unsigned start_span;
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
class embedded_scanline
|
||||
{
|
||||
public:
|
||||
|
||||
//-----------------------------------------------------------
|
||||
class const_iterator
|
||||
{
|
||||
public:
|
||||
struct span
|
||||
{
|
||||
int32 x;
|
||||
int32 len; // If negative, it's a solid span, covers is valid
|
||||
const T* covers;
|
||||
};
|
||||
|
||||
const_iterator() : m_storage(0) {}
|
||||
const_iterator(const embedded_scanline& sl) :
|
||||
m_storage(sl.m_storage),
|
||||
m_span_idx(sl.m_scanline.start_span)
|
||||
{
|
||||
init_span();
|
||||
}
|
||||
|
||||
const span& operator*() const { return m_span; }
|
||||
const span* operator->() const { return &m_span; }
|
||||
|
||||
void operator ++ ()
|
||||
{
|
||||
++m_span_idx;
|
||||
init_span();
|
||||
}
|
||||
|
||||
private:
|
||||
void init_span()
|
||||
{
|
||||
const span_data& s = m_storage->span_by_index(m_span_idx);
|
||||
m_span.x = s.x;
|
||||
m_span.len = s.len;
|
||||
m_span.covers = m_storage->covers_by_index(s.covers_id);
|
||||
}
|
||||
|
||||
const scanline_storage_aa* m_storage;
|
||||
unsigned m_span_idx;
|
||||
span m_span;
|
||||
};
|
||||
|
||||
friend class const_iterator;
|
||||
|
||||
|
||||
//-----------------------------------------------------------
|
||||
embedded_scanline(const scanline_storage_aa& storage) :
|
||||
m_storage(&storage)
|
||||
{
|
||||
init(0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------
|
||||
void reset(int, int) {}
|
||||
unsigned num_spans() const { return m_scanline.num_spans; }
|
||||
int y() const { return m_scanline.y; }
|
||||
const_iterator begin() const { return const_iterator(*this); }
|
||||
|
||||
//-----------------------------------------------------------
|
||||
void init(unsigned scanline_idx)
|
||||
{
|
||||
m_scanline_idx = scanline_idx;
|
||||
m_scanline = m_storage->scanline_by_index(m_scanline_idx);
|
||||
}
|
||||
|
||||
private:
|
||||
const scanline_storage_aa* m_storage;
|
||||
scanline_data m_scanline;
|
||||
unsigned m_scanline_idx;
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
scanline_storage_aa() :
|
||||
m_covers(),
|
||||
m_spans(256-2), // Block increment size
|
||||
m_scanlines(),
|
||||
m_min_x( 0x7FFFFFFF),
|
||||
m_min_y( 0x7FFFFFFF),
|
||||
m_max_x(-0x7FFFFFFF),
|
||||
m_max_y(-0x7FFFFFFF),
|
||||
m_cur_scanline(0)
|
||||
{
|
||||
m_fake_scanline.y = 0;
|
||||
m_fake_scanline.num_spans = 0;
|
||||
m_fake_scanline.start_span = 0;
|
||||
m_fake_span.x = 0;
|
||||
m_fake_span.len = 0;
|
||||
m_fake_span.covers_id = 0;
|
||||
}
|
||||
|
||||
// Renderer Interface
|
||||
//---------------------------------------------------------------
|
||||
void prepare()
|
||||
{
|
||||
m_covers.remove_all();
|
||||
m_scanlines.remove_all();
|
||||
m_spans.remove_all();
|
||||
m_min_x = 0x7FFFFFFF;
|
||||
m_min_y = 0x7FFFFFFF;
|
||||
m_max_x = -0x7FFFFFFF;
|
||||
m_max_y = -0x7FFFFFFF;
|
||||
m_cur_scanline = 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
template<class Scanline> void render(const Scanline& sl)
|
||||
{
|
||||
scanline_data sl_this;
|
||||
|
||||
int y = sl.y();
|
||||
if(y < m_min_y) m_min_y = y;
|
||||
if(y > m_max_y) m_max_y = y;
|
||||
|
||||
sl_this.y = y;
|
||||
sl_this.num_spans = sl.num_spans();
|
||||
sl_this.start_span = m_spans.size();
|
||||
typename Scanline::const_iterator span_iterator = sl.begin();
|
||||
|
||||
unsigned num_spans = sl_this.num_spans;
|
||||
for(;;)
|
||||
{
|
||||
span_data sp;
|
||||
|
||||
sp.x = span_iterator->x;
|
||||
sp.len = span_iterator->len;
|
||||
int len = abs(int(sp.len));
|
||||
sp.covers_id =
|
||||
m_covers.add_cells(span_iterator->covers,
|
||||
unsigned(len));
|
||||
m_spans.add(sp);
|
||||
int x1 = sp.x;
|
||||
int x2 = sp.x + len - 1;
|
||||
if(x1 < m_min_x) m_min_x = x1;
|
||||
if(x2 > m_max_x) m_max_x = x2;
|
||||
if(--num_spans == 0) break;
|
||||
++span_iterator;
|
||||
}
|
||||
m_scanlines.add(sl_this);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Iterate scanlines interface
|
||||
int min_x() const { return m_min_x; }
|
||||
int min_y() const { return m_min_y; }
|
||||
int max_x() const { return m_max_x; }
|
||||
int max_y() const { return m_max_y; }
|
||||
|
||||
//---------------------------------------------------------------
|
||||
bool rewind_scanlines()
|
||||
{
|
||||
m_cur_scanline = 0;
|
||||
return m_scanlines.size() > 0;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
template<class Scanline> bool sweep_scanline(Scanline& sl)
|
||||
{
|
||||
sl.reset_spans();
|
||||
for(;;)
|
||||
{
|
||||
if(m_cur_scanline >= m_scanlines.size()) return false;
|
||||
const scanline_data& sl_this = m_scanlines[m_cur_scanline];
|
||||
|
||||
unsigned num_spans = sl_this.num_spans;
|
||||
unsigned span_idx = sl_this.start_span;
|
||||
do
|
||||
{
|
||||
const span_data& sp = m_spans[span_idx++];
|
||||
const T* covers = covers_by_index(sp.covers_id);
|
||||
if(sp.len < 0)
|
||||
{
|
||||
sl.add_span(sp.x, unsigned(-sp.len), *covers);
|
||||
}
|
||||
else
|
||||
{
|
||||
sl.add_cells(sp.x, sp.len, covers);
|
||||
}
|
||||
}
|
||||
while(--num_spans);
|
||||
++m_cur_scanline;
|
||||
if(sl.num_spans())
|
||||
{
|
||||
sl.finalize(sl_this.y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Specialization for embedded_scanline
|
||||
bool sweep_scanline(embedded_scanline& sl)
|
||||
{
|
||||
do
|
||||
{
|
||||
if(m_cur_scanline >= m_scanlines.size()) return false;
|
||||
sl.init(m_cur_scanline);
|
||||
++m_cur_scanline;
|
||||
}
|
||||
while(sl.num_spans() == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
unsigned byte_size() const
|
||||
{
|
||||
unsigned i;
|
||||
unsigned size = sizeof(int32) * 4; // min_x, min_y, max_x, max_y
|
||||
|
||||
for(i = 0; i < m_scanlines.size(); ++i)
|
||||
{
|
||||
size += sizeof(int32) * 3; // scanline size in bytes, Y, num_spans
|
||||
|
||||
const scanline_data& sl_this = m_scanlines[i];
|
||||
|
||||
unsigned num_spans = sl_this.num_spans;
|
||||
unsigned span_idx = sl_this.start_span;
|
||||
do
|
||||
{
|
||||
const span_data& sp = m_spans[span_idx++];
|
||||
|
||||
size += sizeof(int32) * 2; // X, span_len
|
||||
if(sp.len < 0)
|
||||
{
|
||||
size += sizeof(T); // cover
|
||||
}
|
||||
else
|
||||
{
|
||||
size += sizeof(T) * unsigned(sp.len); // covers
|
||||
}
|
||||
}
|
||||
while(--num_spans);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
static void write_int32(int8u* dst, int32 val)
|
||||
{
|
||||
dst[0] = ((const int8u*)&val)[0];
|
||||
dst[1] = ((const int8u*)&val)[1];
|
||||
dst[2] = ((const int8u*)&val)[2];
|
||||
dst[3] = ((const int8u*)&val)[3];
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
void serialize(int8u* data) const
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
write_int32(data, min_x()); // min_x
|
||||
data += sizeof(int32);
|
||||
write_int32(data, min_y()); // min_y
|
||||
data += sizeof(int32);
|
||||
write_int32(data, max_x()); // max_x
|
||||
data += sizeof(int32);
|
||||
write_int32(data, max_y()); // max_y
|
||||
data += sizeof(int32);
|
||||
|
||||
for(i = 0; i < m_scanlines.size(); ++i)
|
||||
{
|
||||
const scanline_data& sl_this = m_scanlines[i];
|
||||
|
||||
int8u* size_ptr = data;
|
||||
data += sizeof(int32); // Reserve space for scanline size in bytes
|
||||
|
||||
write_int32(data, sl_this.y); // Y
|
||||
data += sizeof(int32);
|
||||
|
||||
write_int32(data, sl_this.num_spans); // num_spans
|
||||
data += sizeof(int32);
|
||||
|
||||
unsigned num_spans = sl_this.num_spans;
|
||||
unsigned span_idx = sl_this.start_span;
|
||||
do
|
||||
{
|
||||
const span_data& sp = m_spans[span_idx++];
|
||||
const T* covers = covers_by_index(sp.covers_id);
|
||||
|
||||
write_int32(data, sp.x); // X
|
||||
data += sizeof(int32);
|
||||
|
||||
write_int32(data, sp.len); // span_len
|
||||
data += sizeof(int32);
|
||||
|
||||
if(sp.len < 0)
|
||||
{
|
||||
memcpy(data, covers, sizeof(T));
|
||||
data += sizeof(T);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(data, covers, unsigned(sp.len) * sizeof(T));
|
||||
data += sizeof(T) * unsigned(sp.len);
|
||||
}
|
||||
}
|
||||
while(--num_spans);
|
||||
write_int32(size_ptr, int32(unsigned(data - size_ptr)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
const scanline_data& scanline_by_index(unsigned i) const
|
||||
{
|
||||
return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
const span_data& span_by_index(unsigned i) const
|
||||
{
|
||||
return (i < m_spans.size()) ? m_spans[i] : m_fake_span;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
const T* covers_by_index(int i) const
|
||||
{
|
||||
return m_covers[i];
|
||||
}
|
||||
|
||||
private:
|
||||
scanline_cell_storage<T> m_covers;
|
||||
pod_bvector<span_data, 10> m_spans;
|
||||
pod_bvector<scanline_data, 8> m_scanlines;
|
||||
span_data m_fake_span;
|
||||
scanline_data m_fake_scanline;
|
||||
int m_min_x;
|
||||
int m_min_y;
|
||||
int m_max_x;
|
||||
int m_max_y;
|
||||
unsigned m_cur_scanline;
|
||||
};
|
||||
|
||||
|
||||
typedef scanline_storage_aa<int8u> scanline_storage_aa8; //--------scanline_storage_aa8
|
||||
typedef scanline_storage_aa<int16u> scanline_storage_aa16; //--------scanline_storage_aa16
|
||||
typedef scanline_storage_aa<int32u> scanline_storage_aa32; //--------scanline_storage_aa32
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------serialized_scanlines_adaptor_aa
|
||||
template<class T> class serialized_scanlines_adaptor_aa
|
||||
{
|
||||
public:
|
||||
typedef T cover_type;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
class embedded_scanline
|
||||
{
|
||||
public:
|
||||
typedef T cover_type;
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
class const_iterator
|
||||
{
|
||||
public:
|
||||
struct span
|
||||
{
|
||||
int32 x;
|
||||
int32 len; // If negative, it's a solid span, "covers" is valid
|
||||
const T* covers;
|
||||
};
|
||||
|
||||
const_iterator() : m_ptr(0) {}
|
||||
const_iterator(const embedded_scanline& sl) :
|
||||
m_ptr(sl.m_ptr),
|
||||
m_dx(sl.m_dx)
|
||||
{
|
||||
init_span();
|
||||
}
|
||||
|
||||
const span& operator*() const { return m_span; }
|
||||
const span* operator->() const { return &m_span; }
|
||||
|
||||
void operator ++ ()
|
||||
{
|
||||
if(m_span.len < 0)
|
||||
{
|
||||
m_ptr += sizeof(T);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ptr += m_span.len * sizeof(T);
|
||||
}
|
||||
init_span();
|
||||
}
|
||||
|
||||
private:
|
||||
int read_int32()
|
||||
{
|
||||
int32 val;
|
||||
((int8u*)&val)[0] = *m_ptr++;
|
||||
((int8u*)&val)[1] = *m_ptr++;
|
||||
((int8u*)&val)[2] = *m_ptr++;
|
||||
((int8u*)&val)[3] = *m_ptr++;
|
||||
return val;
|
||||
}
|
||||
|
||||
void init_span()
|
||||
{
|
||||
m_span.x = read_int32() + m_dx;
|
||||
m_span.len = read_int32();
|
||||
m_span.covers = m_ptr;
|
||||
}
|
||||
|
||||
const int8u* m_ptr;
|
||||
span m_span;
|
||||
int m_dx;
|
||||
};
|
||||
|
||||
friend class const_iterator;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
void reset(int, int) {}
|
||||
unsigned num_spans() const { return m_num_spans; }
|
||||
int y() const { return m_y; }
|
||||
const_iterator begin() const { return const_iterator(*this); }
|
||||
|
||||
|
||||
private:
|
||||
//-----------------------------------------------------------------
|
||||
int read_int32()
|
||||
{
|
||||
int32 val;
|
||||
((int8u*)&val)[0] = *m_ptr++;
|
||||
((int8u*)&val)[1] = *m_ptr++;
|
||||
((int8u*)&val)[2] = *m_ptr++;
|
||||
((int8u*)&val)[3] = *m_ptr++;
|
||||
return val;
|
||||
}
|
||||
|
||||
public:
|
||||
//-----------------------------------------------------------------
|
||||
void init(const int8u* ptr, int dx, int dy)
|
||||
{
|
||||
m_ptr = ptr;
|
||||
m_y = read_int32() + dy;
|
||||
m_num_spans = unsigned(read_int32());
|
||||
m_dx = dx;
|
||||
}
|
||||
|
||||
private:
|
||||
const int8u* m_ptr;
|
||||
int m_y;
|
||||
unsigned m_num_spans;
|
||||
int m_dx;
|
||||
};
|
||||
|
||||
|
||||
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
serialized_scanlines_adaptor_aa() :
|
||||
m_data(0),
|
||||
m_end(0),
|
||||
m_ptr(0),
|
||||
m_dx(0),
|
||||
m_dy(0),
|
||||
m_min_x(0x7FFFFFFF),
|
||||
m_min_y(0x7FFFFFFF),
|
||||
m_max_x(-0x7FFFFFFF),
|
||||
m_max_y(-0x7FFFFFFF)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
serialized_scanlines_adaptor_aa(const int8u* data, unsigned size,
|
||||
double dx, double dy) :
|
||||
m_data(data),
|
||||
m_end(data + size),
|
||||
m_ptr(data),
|
||||
m_dx(iround(dx)),
|
||||
m_dy(iround(dy)),
|
||||
m_min_x(0x7FFFFFFF),
|
||||
m_min_y(0x7FFFFFFF),
|
||||
m_max_x(-0x7FFFFFFF),
|
||||
m_max_y(-0x7FFFFFFF)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void init(const int8u* data, unsigned size, double dx, double dy)
|
||||
{
|
||||
m_data = data;
|
||||
m_end = data + size;
|
||||
m_ptr = data;
|
||||
m_dx = iround(dx);
|
||||
m_dy = iround(dy);
|
||||
m_min_x = 0x7FFFFFFF;
|
||||
m_min_y = 0x7FFFFFFF;
|
||||
m_max_x = -0x7FFFFFFF;
|
||||
m_max_y = -0x7FFFFFFF;
|
||||
}
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
int read_int32()
|
||||
{
|
||||
int32 val;
|
||||
((int8u*)&val)[0] = *m_ptr++;
|
||||
((int8u*)&val)[1] = *m_ptr++;
|
||||
((int8u*)&val)[2] = *m_ptr++;
|
||||
((int8u*)&val)[3] = *m_ptr++;
|
||||
return val;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned read_int32u()
|
||||
{
|
||||
int32u val;
|
||||
((int8u*)&val)[0] = *m_ptr++;
|
||||
((int8u*)&val)[1] = *m_ptr++;
|
||||
((int8u*)&val)[2] = *m_ptr++;
|
||||
((int8u*)&val)[3] = *m_ptr++;
|
||||
return val;
|
||||
}
|
||||
|
||||
public:
|
||||
// Iterate scanlines interface
|
||||
//--------------------------------------------------------------------
|
||||
bool rewind_scanlines()
|
||||
{
|
||||
m_ptr = m_data;
|
||||
if(m_ptr < m_end)
|
||||
{
|
||||
m_min_x = read_int32() + m_dx;
|
||||
m_min_y = read_int32() + m_dy;
|
||||
m_max_x = read_int32() + m_dx;
|
||||
m_max_y = read_int32() + m_dy;
|
||||
}
|
||||
return m_ptr < m_end;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int min_x() const { return m_min_x; }
|
||||
int min_y() const { return m_min_y; }
|
||||
int max_x() const { return m_max_x; }
|
||||
int max_y() const { return m_max_y; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Scanline> bool sweep_scanline(Scanline& sl)
|
||||
{
|
||||
sl.reset_spans();
|
||||
for(;;)
|
||||
{
|
||||
if(m_ptr >= m_end) return false;
|
||||
|
||||
read_int32(); // Skip scanline size in bytes
|
||||
int y = read_int32() + m_dy;
|
||||
unsigned num_spans = read_int32();
|
||||
|
||||
do
|
||||
{
|
||||
int x = read_int32() + m_dx;
|
||||
int len = read_int32();
|
||||
|
||||
if(len < 0)
|
||||
{
|
||||
sl.add_span(x, unsigned(-len), *m_ptr);
|
||||
m_ptr += sizeof(T);
|
||||
}
|
||||
else
|
||||
{
|
||||
sl.add_cells(x, len, m_ptr);
|
||||
m_ptr += len * sizeof(T);
|
||||
}
|
||||
}
|
||||
while(--num_spans);
|
||||
|
||||
if(sl.num_spans())
|
||||
{
|
||||
sl.finalize(y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Specialization for embedded_scanline
|
||||
bool sweep_scanline(embedded_scanline& sl)
|
||||
{
|
||||
do
|
||||
{
|
||||
if(m_ptr >= m_end) return false;
|
||||
|
||||
unsigned byte_size = read_int32u();
|
||||
sl.init(m_ptr, m_dx, m_dy);
|
||||
m_ptr += byte_size - sizeof(int32);
|
||||
}
|
||||
while(sl.num_spans() == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
const int8u* m_data;
|
||||
const int8u* m_end;
|
||||
const int8u* m_ptr;
|
||||
int m_dx;
|
||||
int m_dy;
|
||||
int m_min_x;
|
||||
int m_min_y;
|
||||
int m_max_x;
|
||||
int m_max_y;
|
||||
};
|
||||
|
||||
|
||||
|
||||
typedef serialized_scanlines_adaptor_aa<int8u> serialized_scanlines_adaptor_aa8; //----serialized_scanlines_adaptor_aa8
|
||||
typedef serialized_scanlines_adaptor_aa<int16u> serialized_scanlines_adaptor_aa16; //----serialized_scanlines_adaptor_aa16
|
||||
typedef serialized_scanlines_adaptor_aa<int32u> serialized_scanlines_adaptor_aa32; //----serialized_scanlines_adaptor_aa32
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,595 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for 32-bit screen coordinates has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef AGG_SCANLINE_STORAGE_BIN_INCLUDED
|
||||
#define AGG_SCANLINE_STORAGE_BIN_INCLUDED
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "agg_array.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-----------------------------------------------scanline_storage_bin
|
||||
class scanline_storage_bin
|
||||
{
|
||||
public:
|
||||
//---------------------------------------------------------------
|
||||
struct span_data
|
||||
{
|
||||
int32 x;
|
||||
int32 len;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------
|
||||
struct scanline_data
|
||||
{
|
||||
int y;
|
||||
unsigned num_spans;
|
||||
unsigned start_span;
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
class embedded_scanline
|
||||
{
|
||||
public:
|
||||
|
||||
//-----------------------------------------------------------
|
||||
class const_iterator
|
||||
{
|
||||
public:
|
||||
const_iterator() : m_storage(0) {}
|
||||
const_iterator(const embedded_scanline& sl) :
|
||||
m_storage(sl.m_storage),
|
||||
m_span_idx(sl.m_scanline.start_span)
|
||||
{
|
||||
m_span = m_storage->span_by_index(m_span_idx);
|
||||
}
|
||||
|
||||
const span_data& operator*() const { return m_span; }
|
||||
const span_data* operator->() const { return &m_span; }
|
||||
|
||||
void operator ++ ()
|
||||
{
|
||||
++m_span_idx;
|
||||
m_span = m_storage->span_by_index(m_span_idx);
|
||||
}
|
||||
|
||||
private:
|
||||
const scanline_storage_bin* m_storage;
|
||||
unsigned m_span_idx;
|
||||
span_data m_span;
|
||||
};
|
||||
|
||||
friend class const_iterator;
|
||||
|
||||
|
||||
//-----------------------------------------------------------
|
||||
embedded_scanline(const scanline_storage_bin& storage) :
|
||||
m_storage(&storage)
|
||||
{
|
||||
setup(0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------
|
||||
void reset(int, int) {}
|
||||
unsigned num_spans() const { return m_scanline.num_spans; }
|
||||
int y() const { return m_scanline.y; }
|
||||
const_iterator begin() const { return const_iterator(*this); }
|
||||
|
||||
//-----------------------------------------------------------
|
||||
void setup(unsigned scanline_idx)
|
||||
{
|
||||
m_scanline_idx = scanline_idx;
|
||||
m_scanline = m_storage->scanline_by_index(m_scanline_idx);
|
||||
}
|
||||
|
||||
private:
|
||||
const scanline_storage_bin* m_storage;
|
||||
scanline_data m_scanline;
|
||||
unsigned m_scanline_idx;
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
scanline_storage_bin() :
|
||||
m_spans(256-2), // Block increment size
|
||||
m_scanlines(),
|
||||
m_min_x( 0x7FFFFFFF),
|
||||
m_min_y( 0x7FFFFFFF),
|
||||
m_max_x(-0x7FFFFFFF),
|
||||
m_max_y(-0x7FFFFFFF),
|
||||
m_cur_scanline(0)
|
||||
{
|
||||
m_fake_scanline.y = 0;
|
||||
m_fake_scanline.num_spans = 0;
|
||||
m_fake_scanline.start_span = 0;
|
||||
m_fake_span.x = 0;
|
||||
m_fake_span.len = 0;
|
||||
}
|
||||
|
||||
// Renderer Interface
|
||||
//---------------------------------------------------------------
|
||||
void prepare()
|
||||
{
|
||||
m_scanlines.remove_all();
|
||||
m_spans.remove_all();
|
||||
m_min_x = 0x7FFFFFFF;
|
||||
m_min_y = 0x7FFFFFFF;
|
||||
m_max_x = -0x7FFFFFFF;
|
||||
m_max_y = -0x7FFFFFFF;
|
||||
m_cur_scanline = 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
template<class Scanline> void render(const Scanline& sl)
|
||||
{
|
||||
scanline_data sl_this;
|
||||
|
||||
int y = sl.y();
|
||||
if(y < m_min_y) m_min_y = y;
|
||||
if(y > m_max_y) m_max_y = y;
|
||||
|
||||
sl_this.y = y;
|
||||
sl_this.num_spans = sl.num_spans();
|
||||
sl_this.start_span = m_spans.size();
|
||||
typename Scanline::const_iterator span_iterator = sl.begin();
|
||||
|
||||
unsigned num_spans = sl_this.num_spans;
|
||||
for(;;)
|
||||
{
|
||||
span_data sp;
|
||||
sp.x = span_iterator->x;
|
||||
sp.len = (int32)abs((int)(span_iterator->len));
|
||||
m_spans.add(sp);
|
||||
int x1 = sp.x;
|
||||
int x2 = sp.x + sp.len - 1;
|
||||
if(x1 < m_min_x) m_min_x = x1;
|
||||
if(x2 > m_max_x) m_max_x = x2;
|
||||
if(--num_spans == 0) break;
|
||||
++span_iterator;
|
||||
}
|
||||
m_scanlines.add(sl_this);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Iterate scanlines interface
|
||||
int min_x() const { return m_min_x; }
|
||||
int min_y() const { return m_min_y; }
|
||||
int max_x() const { return m_max_x; }
|
||||
int max_y() const { return m_max_y; }
|
||||
|
||||
//---------------------------------------------------------------
|
||||
bool rewind_scanlines()
|
||||
{
|
||||
m_cur_scanline = 0;
|
||||
return m_scanlines.size() > 0;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
template<class Scanline> bool sweep_scanline(Scanline& sl)
|
||||
{
|
||||
sl.reset_spans();
|
||||
for(;;)
|
||||
{
|
||||
if(m_cur_scanline >= m_scanlines.size()) return false;
|
||||
const scanline_data& sl_this = m_scanlines[m_cur_scanline];
|
||||
|
||||
unsigned num_spans = sl_this.num_spans;
|
||||
unsigned span_idx = sl_this.start_span;
|
||||
do
|
||||
{
|
||||
const span_data& sp = m_spans[span_idx++];
|
||||
sl.add_span(sp.x, sp.len, cover_full);
|
||||
}
|
||||
while(--num_spans);
|
||||
|
||||
++m_cur_scanline;
|
||||
if(sl.num_spans())
|
||||
{
|
||||
sl.finalize(sl_this.y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Specialization for embedded_scanline
|
||||
bool sweep_scanline(embedded_scanline& sl)
|
||||
{
|
||||
do
|
||||
{
|
||||
if(m_cur_scanline >= m_scanlines.size()) return false;
|
||||
sl.setup(m_cur_scanline);
|
||||
++m_cur_scanline;
|
||||
}
|
||||
while(sl.num_spans() == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
unsigned byte_size() const
|
||||
{
|
||||
unsigned i;
|
||||
unsigned size = sizeof(int32) * 4; // min_x, min_y, max_x, max_y
|
||||
|
||||
for(i = 0; i < m_scanlines.size(); ++i)
|
||||
{
|
||||
size += sizeof(int32) * 2 + // Y, num_spans
|
||||
unsigned(m_scanlines[i].num_spans) * sizeof(int32) * 2; // X, span_len
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
static void write_int32(int8u* dst, int32 val)
|
||||
{
|
||||
dst[0] = ((const int8u*)&val)[0];
|
||||
dst[1] = ((const int8u*)&val)[1];
|
||||
dst[2] = ((const int8u*)&val)[2];
|
||||
dst[3] = ((const int8u*)&val)[3];
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
void serialize(int8u* data) const
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
write_int32(data, min_x()); // min_x
|
||||
data += sizeof(int32);
|
||||
write_int32(data, min_y()); // min_y
|
||||
data += sizeof(int32);
|
||||
write_int32(data, max_x()); // max_x
|
||||
data += sizeof(int32);
|
||||
write_int32(data, max_y()); // max_y
|
||||
data += sizeof(int32);
|
||||
|
||||
for(i = 0; i < m_scanlines.size(); ++i)
|
||||
{
|
||||
const scanline_data& sl_this = m_scanlines[i];
|
||||
|
||||
write_int32(data, sl_this.y); // Y
|
||||
data += sizeof(int32);
|
||||
|
||||
write_int32(data, sl_this.num_spans); // num_spans
|
||||
data += sizeof(int32);
|
||||
|
||||
unsigned num_spans = sl_this.num_spans;
|
||||
unsigned span_idx = sl_this.start_span;
|
||||
do
|
||||
{
|
||||
const span_data& sp = m_spans[span_idx++];
|
||||
|
||||
write_int32(data, sp.x); // X
|
||||
data += sizeof(int32);
|
||||
|
||||
write_int32(data, sp.len); // len
|
||||
data += sizeof(int32);
|
||||
}
|
||||
while(--num_spans);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
const scanline_data& scanline_by_index(unsigned i) const
|
||||
{
|
||||
return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
const span_data& span_by_index(unsigned i) const
|
||||
{
|
||||
return (i < m_spans.size()) ? m_spans[i] : m_fake_span;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
pod_bvector<span_data, 10> m_spans;
|
||||
pod_bvector<scanline_data, 8> m_scanlines;
|
||||
span_data m_fake_span;
|
||||
scanline_data m_fake_scanline;
|
||||
int m_min_x;
|
||||
int m_min_y;
|
||||
int m_max_x;
|
||||
int m_max_y;
|
||||
unsigned m_cur_scanline;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//---------------------------------------serialized_scanlines_adaptor_bin
|
||||
class serialized_scanlines_adaptor_bin
|
||||
{
|
||||
public:
|
||||
typedef bool cover_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
class embedded_scanline
|
||||
{
|
||||
public:
|
||||
|
||||
//----------------------------------------------------------------
|
||||
class const_iterator
|
||||
{
|
||||
public:
|
||||
struct span
|
||||
{
|
||||
int32 x;
|
||||
int32 len;
|
||||
};
|
||||
|
||||
const_iterator() : m_ptr(0) {}
|
||||
const_iterator(const embedded_scanline& sl) :
|
||||
m_ptr(sl.m_ptr),
|
||||
m_dx(sl.m_dx)
|
||||
{
|
||||
m_span.x = read_int32() + m_dx;
|
||||
m_span.len = read_int32();
|
||||
}
|
||||
|
||||
const span& operator*() const { return m_span; }
|
||||
const span* operator->() const { return &m_span; }
|
||||
|
||||
void operator ++ ()
|
||||
{
|
||||
m_span.x = read_int32() + m_dx;
|
||||
m_span.len = read_int32();
|
||||
}
|
||||
|
||||
private:
|
||||
int read_int32()
|
||||
{
|
||||
int32 val;
|
||||
((int8u*)&val)[0] = *m_ptr++;
|
||||
((int8u*)&val)[1] = *m_ptr++;
|
||||
((int8u*)&val)[2] = *m_ptr++;
|
||||
((int8u*)&val)[3] = *m_ptr++;
|
||||
return val;
|
||||
}
|
||||
|
||||
const int8u* m_ptr;
|
||||
span m_span;
|
||||
int m_dx;
|
||||
};
|
||||
|
||||
friend class const_iterator;
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void reset(int, int) {}
|
||||
unsigned num_spans() const { return m_num_spans; }
|
||||
int y() const { return m_y; }
|
||||
const_iterator begin() const { return const_iterator(*this); }
|
||||
|
||||
|
||||
private:
|
||||
//----------------------------------------------------------------
|
||||
int read_int32()
|
||||
{
|
||||
int32 val;
|
||||
((int8u*)&val)[0] = *m_ptr++;
|
||||
((int8u*)&val)[1] = *m_ptr++;
|
||||
((int8u*)&val)[2] = *m_ptr++;
|
||||
((int8u*)&val)[3] = *m_ptr++;
|
||||
return val;
|
||||
}
|
||||
|
||||
public:
|
||||
//----------------------------------------------------------------
|
||||
void init(const int8u* ptr, int dx, int dy)
|
||||
{
|
||||
m_ptr = ptr;
|
||||
m_y = read_int32() + dy;
|
||||
m_num_spans = unsigned(read_int32());
|
||||
m_dx = dx;
|
||||
}
|
||||
|
||||
private:
|
||||
const int8u* m_ptr;
|
||||
int m_y;
|
||||
unsigned m_num_spans;
|
||||
int m_dx;
|
||||
};
|
||||
|
||||
|
||||
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
serialized_scanlines_adaptor_bin() :
|
||||
m_data(0),
|
||||
m_end(0),
|
||||
m_ptr(0),
|
||||
m_dx(0),
|
||||
m_dy(0),
|
||||
m_min_x(0x7FFFFFFF),
|
||||
m_min_y(0x7FFFFFFF),
|
||||
m_max_x(-0x7FFFFFFF),
|
||||
m_max_y(-0x7FFFFFFF)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
serialized_scanlines_adaptor_bin(const int8u* data, unsigned size,
|
||||
double dx, double dy) :
|
||||
m_data(data),
|
||||
m_end(data + size),
|
||||
m_ptr(data),
|
||||
m_dx(iround(dx)),
|
||||
m_dy(iround(dy)),
|
||||
m_min_x(0x7FFFFFFF),
|
||||
m_min_y(0x7FFFFFFF),
|
||||
m_max_x(-0x7FFFFFFF),
|
||||
m_max_y(-0x7FFFFFFF)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void init(const int8u* data, unsigned size, double dx, double dy)
|
||||
{
|
||||
m_data = data;
|
||||
m_end = data + size;
|
||||
m_ptr = data;
|
||||
m_dx = iround(dx);
|
||||
m_dy = iround(dy);
|
||||
m_min_x = 0x7FFFFFFF;
|
||||
m_min_y = 0x7FFFFFFF;
|
||||
m_max_x = -0x7FFFFFFF;
|
||||
m_max_y = -0x7FFFFFFF;
|
||||
}
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
int read_int32()
|
||||
{
|
||||
int32 val;
|
||||
((int8u*)&val)[0] = *m_ptr++;
|
||||
((int8u*)&val)[1] = *m_ptr++;
|
||||
((int8u*)&val)[2] = *m_ptr++;
|
||||
((int8u*)&val)[3] = *m_ptr++;
|
||||
return val;
|
||||
}
|
||||
|
||||
public:
|
||||
// Iterate scanlines interface
|
||||
//--------------------------------------------------------------------
|
||||
bool rewind_scanlines()
|
||||
{
|
||||
m_ptr = m_data;
|
||||
if(m_ptr < m_end)
|
||||
{
|
||||
m_min_x = read_int32() + m_dx;
|
||||
m_min_y = read_int32() + m_dy;
|
||||
m_max_x = read_int32() + m_dx;
|
||||
m_max_y = read_int32() + m_dy;
|
||||
}
|
||||
return m_ptr < m_end;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int min_x() const { return m_min_x; }
|
||||
int min_y() const { return m_min_y; }
|
||||
int max_x() const { return m_max_x; }
|
||||
int max_y() const { return m_max_y; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Scanline> bool sweep_scanline(Scanline& sl)
|
||||
{
|
||||
sl.reset_spans();
|
||||
for(;;)
|
||||
{
|
||||
if(m_ptr >= m_end) return false;
|
||||
|
||||
int y = read_int32() + m_dy;
|
||||
unsigned num_spans = read_int32();
|
||||
|
||||
do
|
||||
{
|
||||
int x = read_int32() + m_dx;
|
||||
int len = read_int32();
|
||||
|
||||
if(len < 0) len = -len;
|
||||
sl.add_span(x, unsigned(len), cover_full);
|
||||
}
|
||||
while(--num_spans);
|
||||
|
||||
if(sl.num_spans())
|
||||
{
|
||||
sl.finalize(y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Specialization for embedded_scanline
|
||||
bool sweep_scanline(embedded_scanline& sl)
|
||||
{
|
||||
do
|
||||
{
|
||||
if(m_ptr >= m_end) return false;
|
||||
|
||||
sl.init(m_ptr, m_dx, m_dy);
|
||||
|
||||
// Jump to the next scanline
|
||||
//--------------------------
|
||||
read_int32(); // Y
|
||||
int num_spans = read_int32(); // num_spans
|
||||
m_ptr += num_spans * sizeof(int32) * 2;
|
||||
}
|
||||
while(sl.num_spans() == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
const int8u* m_data;
|
||||
const int8u* m_end;
|
||||
const int8u* m_ptr;
|
||||
int m_dx;
|
||||
int m_dy;
|
||||
int m_min_x;
|
||||
int m_min_y;
|
||||
int m_max_x;
|
||||
int m_max_y;
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,508 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for 32-bit screen coordinates (scanline32_u) has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_SCANLINE_U_INCLUDED
|
||||
#define AGG_SCANLINE_U_INCLUDED
|
||||
|
||||
#include "agg_array.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//=============================================================scanline_u8
|
||||
//
|
||||
// Unpacked scanline container class
|
||||
//
|
||||
// This class is used to transfer data from a scanline rasterizer
|
||||
// to the rendering buffer. It's organized very simple. The class stores
|
||||
// information of horizontal spans to render it into a pixel-map buffer.
|
||||
// Each span has staring X, length, and an array of bytes that determine the
|
||||
// cover-values for each pixel.
|
||||
// Before using this class you should know the minimal and maximal pixel
|
||||
// coordinates of your scanline. The protocol of using is:
|
||||
// 1. reset(min_x, max_x)
|
||||
// 2. add_cell() / add_span() - accumulate scanline.
|
||||
// When forming one scanline the next X coordinate must be always greater
|
||||
// than the last stored one, i.e. it works only with ordered coordinates.
|
||||
// 3. Call finalize(y) and render the scanline.
|
||||
// 3. Call reset_spans() to prepare for the new scanline.
|
||||
//
|
||||
// 4. Rendering:
|
||||
//
|
||||
// Scanline provides an iterator class that allows you to extract
|
||||
// the spans and the cover values for each pixel. Be aware that clipping
|
||||
// has not been done yet, so you should perform it yourself.
|
||||
// Use scanline_u8::iterator to render spans:
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// int y = sl.y(); // Y-coordinate of the scanline
|
||||
//
|
||||
// ************************************
|
||||
// ...Perform vertical clipping here...
|
||||
// ************************************
|
||||
//
|
||||
// scanline_u8::const_iterator span = sl.begin();
|
||||
//
|
||||
// unsigned char* row = m_rbuf->row(y); // The the address of the beginning
|
||||
// // of the current row
|
||||
//
|
||||
// unsigned num_spans = sl.num_spans(); // Number of spans. It's guaranteed that
|
||||
// // num_spans is always greater than 0.
|
||||
//
|
||||
// do
|
||||
// {
|
||||
// const scanline_u8::cover_type* covers =
|
||||
// span->covers; // The array of the cover values
|
||||
//
|
||||
// int num_pix = span->len; // Number of pixels of the span.
|
||||
// // Always greater than 0, still it's
|
||||
// // better to use "int" instead of
|
||||
// // "unsigned" because it's more
|
||||
// // convenient for clipping
|
||||
// int x = span->x;
|
||||
//
|
||||
// **************************************
|
||||
// ...Perform horizontal clipping here...
|
||||
// ...you have x, covers, and pix_count..
|
||||
// **************************************
|
||||
//
|
||||
// unsigned char* dst = row + x; // Calculate the start address of the row.
|
||||
// // In this case we assume a simple
|
||||
// // grayscale image 1-byte per pixel.
|
||||
// do
|
||||
// {
|
||||
// *dst++ = *covers++; // Hypotetical rendering.
|
||||
// }
|
||||
// while(--num_pix);
|
||||
//
|
||||
// ++span;
|
||||
// }
|
||||
// while(--num_spans); // num_spans cannot be 0, so this loop is quite safe
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// The question is: why should we accumulate the whole scanline when we
|
||||
// could render just separate spans when they're ready?
|
||||
// That's because using the scanline is generally faster. When is consists
|
||||
// of more than one span the conditions for the processor cash system
|
||||
// are better, because switching between two different areas of memory
|
||||
// (that can be very large) occurs less frequently.
|
||||
//------------------------------------------------------------------------
|
||||
class scanline_u8
|
||||
{
|
||||
public:
|
||||
typedef scanline_u8 self_type;
|
||||
typedef int8u cover_type;
|
||||
typedef int16 coord_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
struct span
|
||||
{
|
||||
coord_type x;
|
||||
coord_type len;
|
||||
cover_type* covers;
|
||||
};
|
||||
|
||||
typedef span* iterator;
|
||||
typedef const span* const_iterator;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
scanline_u8() :
|
||||
m_min_x(0),
|
||||
m_last_x(0x7FFFFFF0),
|
||||
m_cur_span(0)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset(int min_x, int max_x)
|
||||
{
|
||||
unsigned max_len = max_x - min_x + 2;
|
||||
if(max_len > m_spans.size())
|
||||
{
|
||||
m_spans.resize(max_len);
|
||||
m_covers.resize(max_len);
|
||||
}
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_min_x = min_x;
|
||||
m_cur_span = &m_spans[0];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_cell(int x, unsigned cover)
|
||||
{
|
||||
x -= m_min_x;
|
||||
m_covers[x] = (cover_type)cover;
|
||||
if(x == m_last_x+1)
|
||||
{
|
||||
m_cur_span->len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cur_span++;
|
||||
m_cur_span->x = (coord_type)(x + m_min_x);
|
||||
m_cur_span->len = 1;
|
||||
m_cur_span->covers = &m_covers[x];
|
||||
}
|
||||
m_last_x = x;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_cells(int x, unsigned len, const cover_type* covers)
|
||||
{
|
||||
x -= m_min_x;
|
||||
memcpy(&m_covers[x], covers, len * sizeof(cover_type));
|
||||
if(x == m_last_x+1)
|
||||
{
|
||||
m_cur_span->len += (coord_type)len;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cur_span++;
|
||||
m_cur_span->x = (coord_type)(x + m_min_x);
|
||||
m_cur_span->len = (coord_type)len;
|
||||
m_cur_span->covers = &m_covers[x];
|
||||
}
|
||||
m_last_x = x + len - 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_span(int x, unsigned len, unsigned cover)
|
||||
{
|
||||
x -= m_min_x;
|
||||
memset(&m_covers[x], cover, len);
|
||||
if(x == m_last_x+1)
|
||||
{
|
||||
m_cur_span->len += (coord_type)len;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cur_span++;
|
||||
m_cur_span->x = (coord_type)(x + m_min_x);
|
||||
m_cur_span->len = (coord_type)len;
|
||||
m_cur_span->covers = &m_covers[x];
|
||||
}
|
||||
m_last_x = x + len - 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void finalize(int y)
|
||||
{
|
||||
m_y = y;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset_spans()
|
||||
{
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_cur_span = &m_spans[0];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int y() const { return m_y; }
|
||||
unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
|
||||
const_iterator begin() const { return &m_spans[1]; }
|
||||
iterator begin() { return &m_spans[1]; }
|
||||
|
||||
private:
|
||||
scanline_u8(const self_type&);
|
||||
const self_type& operator = (const self_type&);
|
||||
|
||||
private:
|
||||
int m_min_x;
|
||||
int m_last_x;
|
||||
int m_y;
|
||||
pod_array<cover_type> m_covers;
|
||||
pod_array<span> m_spans;
|
||||
span* m_cur_span;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//==========================================================scanline_u8_am
|
||||
//
|
||||
// The scanline container with alpha-masking
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
template<class AlphaMask>
|
||||
class scanline_u8_am : public scanline_u8
|
||||
{
|
||||
public:
|
||||
typedef scanline_u8 base_type;
|
||||
typedef AlphaMask alpha_mask_type;
|
||||
typedef base_type::cover_type cover_type;
|
||||
typedef base_type::coord_type coord_type;
|
||||
|
||||
scanline_u8_am() : base_type(), m_alpha_mask(0) {}
|
||||
scanline_u8_am(const AlphaMask& am) : base_type(), m_alpha_mask(&am) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void finalize(int span_y)
|
||||
{
|
||||
base_type::finalize(span_y);
|
||||
if(m_alpha_mask)
|
||||
{
|
||||
typename base_type::iterator span = base_type::begin();
|
||||
unsigned count = base_type::num_spans();
|
||||
do
|
||||
{
|
||||
m_alpha_mask->combine_hspan(span->x,
|
||||
base_type::y(),
|
||||
span->covers,
|
||||
span->len);
|
||||
++span;
|
||||
}
|
||||
while(--count);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const AlphaMask* m_alpha_mask;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//===========================================================scanline32_u8
|
||||
class scanline32_u8
|
||||
{
|
||||
public:
|
||||
typedef scanline32_u8 self_type;
|
||||
typedef int8u cover_type;
|
||||
typedef int32 coord_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
struct span
|
||||
{
|
||||
span() {}
|
||||
span(coord_type x_, coord_type len_, cover_type* covers_) :
|
||||
x(x_), len(len_), covers(covers_) {}
|
||||
|
||||
coord_type x;
|
||||
coord_type len;
|
||||
cover_type* covers;
|
||||
};
|
||||
|
||||
typedef pod_bvector<span, 4> span_array_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
class const_iterator
|
||||
{
|
||||
public:
|
||||
const_iterator(const span_array_type& spans) :
|
||||
m_spans(spans),
|
||||
m_span_idx(0)
|
||||
{}
|
||||
|
||||
const span& operator*() const { return m_spans[m_span_idx]; }
|
||||
const span* operator->() const { return &m_spans[m_span_idx]; }
|
||||
|
||||
void operator ++ () { ++m_span_idx; }
|
||||
|
||||
private:
|
||||
const span_array_type& m_spans;
|
||||
unsigned m_span_idx;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
class iterator
|
||||
{
|
||||
public:
|
||||
iterator(span_array_type& spans) :
|
||||
m_spans(spans),
|
||||
m_span_idx(0)
|
||||
{}
|
||||
|
||||
span& operator*() { return m_spans[m_span_idx]; }
|
||||
span* operator->() { return &m_spans[m_span_idx]; }
|
||||
|
||||
void operator ++ () { ++m_span_idx; }
|
||||
|
||||
private:
|
||||
span_array_type& m_spans;
|
||||
unsigned m_span_idx;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
scanline32_u8() :
|
||||
m_min_x(0),
|
||||
m_last_x(0x7FFFFFF0),
|
||||
m_covers()
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset(int min_x, int max_x)
|
||||
{
|
||||
unsigned max_len = max_x - min_x + 2;
|
||||
if(max_len > m_covers.size())
|
||||
{
|
||||
m_covers.resize(max_len);
|
||||
}
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_min_x = min_x;
|
||||
m_spans.remove_all();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_cell(int x, unsigned cover)
|
||||
{
|
||||
x -= m_min_x;
|
||||
m_covers[x] = cover_type(cover);
|
||||
if(x == m_last_x+1)
|
||||
{
|
||||
m_spans.last().len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_spans.add(span(coord_type(x + m_min_x), 1, &m_covers[x]));
|
||||
}
|
||||
m_last_x = x;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_cells(int x, unsigned len, const cover_type* covers)
|
||||
{
|
||||
x -= m_min_x;
|
||||
memcpy(&m_covers[x], covers, len * sizeof(cover_type));
|
||||
if(x == m_last_x+1)
|
||||
{
|
||||
m_spans.last().len += coord_type(len);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_spans.add(span(coord_type(x + m_min_x),
|
||||
coord_type(len),
|
||||
&m_covers[x]));
|
||||
}
|
||||
m_last_x = x + len - 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void add_span(int x, unsigned len, unsigned cover)
|
||||
{
|
||||
x -= m_min_x;
|
||||
memset(&m_covers[x], cover, len);
|
||||
if(x == m_last_x+1)
|
||||
{
|
||||
m_spans.last().len += coord_type(len);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_spans.add(span(coord_type(x + m_min_x),
|
||||
coord_type(len),
|
||||
&m_covers[x]));
|
||||
}
|
||||
m_last_x = x + len - 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void finalize(int y)
|
||||
{
|
||||
m_y = y;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset_spans()
|
||||
{
|
||||
m_last_x = 0x7FFFFFF0;
|
||||
m_spans.remove_all();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int y() const { return m_y; }
|
||||
unsigned num_spans() const { return m_spans.size(); }
|
||||
const_iterator begin() const { return const_iterator(m_spans); }
|
||||
iterator begin() { return iterator(m_spans); }
|
||||
|
||||
private:
|
||||
scanline32_u8(const self_type&);
|
||||
const self_type& operator = (const self_type&);
|
||||
|
||||
private:
|
||||
int m_min_x;
|
||||
int m_last_x;
|
||||
int m_y;
|
||||
pod_array<cover_type> m_covers;
|
||||
span_array_type m_spans;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//========================================================scanline32_u8_am
|
||||
//
|
||||
// The scanline container with alpha-masking
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
template<class AlphaMask>
|
||||
class scanline32_u8_am : public scanline32_u8
|
||||
{
|
||||
public:
|
||||
typedef scanline32_u8 base_type;
|
||||
typedef AlphaMask alpha_mask_type;
|
||||
typedef base_type::cover_type cover_type;
|
||||
typedef base_type::coord_type coord_type;
|
||||
|
||||
|
||||
scanline32_u8_am() : base_type(), m_alpha_mask(0) {}
|
||||
scanline32_u8_am(const AlphaMask& am) : base_type(), m_alpha_mask(&am) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void finalize(int span_y)
|
||||
{
|
||||
base_type::finalize(span_y);
|
||||
if(m_alpha_mask)
|
||||
{
|
||||
typename base_type::iterator span = base_type::begin();
|
||||
unsigned count = base_type::num_spans();
|
||||
do
|
||||
{
|
||||
m_alpha_mask->combine_hspan(span->x,
|
||||
base_type::y(),
|
||||
span->covers,
|
||||
span->len);
|
||||
++span;
|
||||
}
|
||||
while(--count);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const AlphaMask* m_alpha_mask;
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_SHORTEN_PATH_INCLUDED
|
||||
#define AGG_SHORTEN_PATH_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_vertex_sequence.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//===========================================================shorten_path
|
||||
template<class VertexSequence>
|
||||
void shorten_path(VertexSequence& vs, double s, unsigned closed = 0)
|
||||
{
|
||||
typedef typename VertexSequence::value_type vertex_type;
|
||||
|
||||
if(s > 0.0 && vs.size() > 1)
|
||||
{
|
||||
double d;
|
||||
int n = int(vs.size() - 2);
|
||||
while(n)
|
||||
{
|
||||
d = vs[n].dist;
|
||||
if(d > s) break;
|
||||
vs.remove_last();
|
||||
s -= d;
|
||||
--n;
|
||||
}
|
||||
if(vs.size() < 2)
|
||||
{
|
||||
vs.remove_all();
|
||||
}
|
||||
else
|
||||
{
|
||||
n = vs.size() - 1;
|
||||
vertex_type& prev = vs[n-1];
|
||||
vertex_type& last = vs[n];
|
||||
d = (prev.dist - s) / prev.dist;
|
||||
double x = prev.x + (last.x - prev.x) * d;
|
||||
double y = prev.y + (last.y - prev.y) * d;
|
||||
last.x = x;
|
||||
last.y = y;
|
||||
if(!prev(last)) vs.remove_last();
|
||||
vs.close(closed != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,153 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_SIMUL_EQ_INCLUDED
|
||||
#define AGG_SIMUL_EQ_INCLUDED
|
||||
|
||||
#include <math.h>
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=============================================================swap_arrays
|
||||
template<class T> void swap_arrays(T* a1, T* a2, unsigned n)
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < n; i++)
|
||||
{
|
||||
T tmp = *a1;
|
||||
*a1++ = *a2;
|
||||
*a2++ = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================matrix_pivot
|
||||
template<unsigned Rows, unsigned Cols>
|
||||
struct matrix_pivot
|
||||
{
|
||||
static int pivot(double m[Rows][Cols], unsigned row)
|
||||
{
|
||||
int k = int(row);
|
||||
double max_val, tmp;
|
||||
|
||||
max_val = -1.0;
|
||||
unsigned i;
|
||||
for(i = row; i < Rows; i++)
|
||||
{
|
||||
if((tmp = fabs(m[i][row])) > max_val && tmp != 0.0)
|
||||
{
|
||||
max_val = tmp;
|
||||
k = i;
|
||||
}
|
||||
}
|
||||
|
||||
if(m[k][row] == 0.0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(k != int(row))
|
||||
{
|
||||
swap_arrays(m[k], m[row], Cols);
|
||||
return k;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//===============================================================simul_eq
|
||||
template<unsigned Size, unsigned RightCols>
|
||||
struct simul_eq
|
||||
{
|
||||
static bool solve(const double left[Size][Size],
|
||||
const double right[Size][RightCols],
|
||||
double result[Size][RightCols])
|
||||
{
|
||||
unsigned i, j, k;
|
||||
double a1;
|
||||
|
||||
double tmp[Size][Size + RightCols];
|
||||
|
||||
for(i = 0; i < Size; i++)
|
||||
{
|
||||
for(j = 0; j < Size; j++)
|
||||
{
|
||||
tmp[i][j] = left[i][j];
|
||||
}
|
||||
for(j = 0; j < RightCols; j++)
|
||||
{
|
||||
tmp[i][Size + j] = right[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
for(k = 0; k < Size; k++)
|
||||
{
|
||||
if(matrix_pivot<Size, Size + RightCols>::pivot(tmp, k) < 0)
|
||||
{
|
||||
return false; // Singularity....
|
||||
}
|
||||
|
||||
a1 = tmp[k][k];
|
||||
|
||||
for(j = k; j < Size + RightCols; j++)
|
||||
{
|
||||
tmp[k][j] /= a1;
|
||||
}
|
||||
|
||||
for(i = k + 1; i < Size; i++)
|
||||
{
|
||||
a1 = tmp[i][k];
|
||||
for (j = k; j < Size + RightCols; j++)
|
||||
{
|
||||
tmp[i][j] -= a1 * tmp[k][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for(k = 0; k < RightCols; k++)
|
||||
{
|
||||
int m;
|
||||
for(m = int(Size - 1); m >= 0; m--)
|
||||
{
|
||||
result[m][k] = tmp[m][Size + k];
|
||||
for(j = m + 1; j < Size; j++)
|
||||
{
|
||||
result[m][k] -= tmp[m][j] * result[j][k];
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,63 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_SPAN_ALLOCATOR_INCLUDED
|
||||
#define AGG_SPAN_ALLOCATOR_INCLUDED
|
||||
|
||||
#include "agg_array.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//----------------------------------------------------------span_allocator
|
||||
template<class ColorT> class span_allocator
|
||||
{
|
||||
public:
|
||||
typedef ColorT color_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE color_type* allocate(unsigned span_len)
|
||||
{
|
||||
if(span_len > m_span.size())
|
||||
{
|
||||
// To reduce the number of reallocs we align the
|
||||
// span_len to 256 color elements.
|
||||
// Well, I just like this number and it looks reasonable.
|
||||
//-----------------------
|
||||
m_span.resize(((span_len + 255) >> 8) << 8);
|
||||
}
|
||||
return &m_span[0];
|
||||
}
|
||||
|
||||
AGG_INLINE color_type* span() { return &m_span[0]; }
|
||||
AGG_INLINE unsigned max_span_len() const { return m_span.size(); }
|
||||
|
||||
private:
|
||||
pod_array<color_type> m_span;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue