precommit

This commit is contained in:
Mathis Logemann 2022-08-17 17:19:59 +02:00
parent f6bcdac258
commit f48589738f
234 changed files with 58907 additions and 58207 deletions

16
.pre-commit-config.yaml Normal file
View file

@ -0,0 +1,16 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
hooks:
- id: trailing-whitespace
files: ^.*\.cmake|CMakeLists\.txt$
- id: end-of-file-fixer
files: ^.*\.cmake|CMakeLists\.txt$
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v14.0.6
hooks:
- id: clang-format
types_or: [c++, c]

View file

@ -5,11 +5,11 @@ cmake_minimum_required(VERSION 3.15)
include(cmake/GetVersion.cmake)
get_mapnik_version()
project(mapnik
project(mapnik
VERSION ${MAPNIK_MAJOR_VERSION}.${MAPNIK_MINOR_VERSION}.${MAPNIK_PATCH_VERSION}
HOMEPAGE_URL "https://mapnik.org/"
DESCRIPTION "Mapnik is an open source toolkit for developing mapping applications"
LANGUAGES CXX
HOMEPAGE_URL "https://mapnik.org/"
DESCRIPTION "Mapnik is an open source toolkit for developing mapping applications"
LANGUAGES CXX
)
message(STATUS "mapnik version: ${PROJECT_VERSION}")
@ -167,7 +167,7 @@ if(harfbuzz_FOUND)
message(STATUS "Found harfbuzz native cmake")
list(APPEND MAPNIK_OPTIONAL_LIBS harfbuzz::harfbuzz)
else()
# Use pkg-config when harfbuzz is not found.
# Use pkg-config when harfbuzz is not found.
# It might be possible that in future version harfbuzz could only be found via pkg-config.
# harfbuzz related discussion: https://github.com/harfbuzz/harfbuzz/issues/2653
message(STATUS "harfbuzz not found via cmake. Searching via pkg-config...")
@ -182,13 +182,13 @@ if(USE_EXTERNAL_MAPBOX_GEOMETRY)
find_path(MAPBOX_GEOMETRY_INCLUDE_DIRS "mapbox/geometry.hpp" REQUIRED)
endif()
else()
set(MAPBOX_GEOMETRY_INCLUDE_DIRS
set(MAPBOX_GEOMETRY_INCLUDE_DIRS
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/deps/mapbox/geometry/include>
$<INSTALL_INTERFACE:include>
)
endif()
if(NOT MAPBOX_GEOMETRY_INCLUDE_DIRS)
message(FATAL_ERROR "Set -DMAPBOX_GEOMETRY_INCLUDE_DIRS to the mapbox/geometry.hpp include dir")
message(FATAL_ERROR "Set -DMAPBOX_GEOMETRY_INCLUDE_DIRS to the mapbox/geometry.hpp include dir")
endif()
if(USE_EXTERNAL_MAPBOX_POLYLABEL)
@ -197,13 +197,13 @@ if(USE_EXTERNAL_MAPBOX_POLYLABEL)
find_path(MAPBOX_POLYLABEL_INCLUDE_DIRS "mapbox/polylabel.hpp")
endif()
else()
set(MAPBOX_POLYLABEL_INCLUDE_DIRS
set(MAPBOX_POLYLABEL_INCLUDE_DIRS
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/deps/mapbox/polylabel/include>
$<INSTALL_INTERFACE:include>
)
endif()
if(NOT MAPBOX_POLYLABEL_INCLUDE_DIRS)
message(FATAL_ERROR "Set MAPBOX_POLYLABEL_INCLUDE_DIRS to the mapbox/geometry include dir")
message(FATAL_ERROR "Set MAPBOX_POLYLABEL_INCLUDE_DIRS to the mapbox/geometry include dir")
endif()
if(USE_EXTERNAL_MAPBOX_PROTOZERO)
@ -212,13 +212,13 @@ if(USE_EXTERNAL_MAPBOX_PROTOZERO)
find_path(MAPBOX_PROTOZERO_INCLUDE_DIRS "protozero/pbf_message.hpp")
endif()
else()
set(MAPBOX_PROTOZERO_INCLUDE_DIRS
set(MAPBOX_PROTOZERO_INCLUDE_DIRS
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/deps/mapbox/protozero/include>
$<INSTALL_INTERFACE:include>
)
endif()
if(NOT MAPBOX_PROTOZERO_INCLUDE_DIRS)
message(FATAL_ERROR "Set MAPBOX_PROTOZERO_INCLUDE_DIRS to the mapbox/protozero include dir")
message(FATAL_ERROR "Set MAPBOX_PROTOZERO_INCLUDE_DIRS to the mapbox/protozero include dir")
endif()
if(USE_EXTERNAL_MAPBOX_VARIANT)
@ -227,13 +227,13 @@ if(USE_EXTERNAL_MAPBOX_VARIANT)
find_path(MAPBOX_VARIANT_INCLUDE_DIRS "mapbox/variant.hpp")
endif()
else()
set(MAPBOX_VARIANT_INCLUDE_DIRS
set(MAPBOX_VARIANT_INCLUDE_DIRS
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/deps/mapbox/variant/include>
$<INSTALL_INTERFACE:include>
)
endif()
if(NOT MAPBOX_VARIANT_INCLUDE_DIRS)
message(FATAL_ERROR "Set MAPBOX_VARIANT_INCLUDE_DIRS to the mapbox/variant include dir")
message(FATAL_ERROR "Set MAPBOX_VARIANT_INCLUDE_DIRS to the mapbox/variant include dir")
endif()
# (used by MapnikInstall.cmake. properties are needed since "set(...)" will be out of scope
@ -245,7 +245,7 @@ if(USE_GLIBC_WORKAROUND)
list(APPEND MAPNIK_COMPILE_DEFS MAPNIK_ENABLE_GLIBC_WORKAROUND)
endif()
if(USE_BIGINT)
if(USE_BIGINT)
list(APPEND MAPNIK_COMPILE_DEFS BIGINT)
endif()
@ -341,7 +341,7 @@ if(USE_SVG_RENDERER)
list(APPEND MAPNIK_COMPILE_DEFS SVG_RENDERER)
endif()
if(NOT WIN32)
if(NOT WIN32)
message(STATUS "Compiling with -DMAPNIK_HAS_DLCFN")
list(APPEND MAPNIK_COMPILE_DEFS MAPNIK_HAS_DLCFN)
list(APPEND MAPNIK_OPTIONAL_LIBS ${CMAKE_DL_LIBS})
@ -365,8 +365,8 @@ add_compile_options(
add_library(core INTERFACE)
add_library(mapnik::core ALIAS core)
target_include_directories(core INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
target_include_directories(core INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${MAPBOX_GEOMETRY_INCLUDE_DIRS}>
$<BUILD_INTERFACE:${MAPBOX_POLYLABEL_INCLUDE_DIRS}>
$<BUILD_INTERFACE:${MAPBOX_VARIANT_INCLUDE_DIRS}>
@ -375,7 +375,7 @@ target_include_directories(core INTERFACE
$<INSTALL_INTERFACE:include>
${MAPNIK_OPTIONAL_LIBS_INCLUDE}
)
target_link_libraries(core INTERFACE
target_link_libraries(core INTERFACE
Threads::Threads
ICU::uc
ICU::data

View file

@ -1,6 +1,6 @@
project(mapnik-benchmark)
set(BENCHMARK_SRCS
set(BENCHMARK_SRCS
src/normalize_angle.cpp
src/test_array_allocation.cpp
src/test_expression_parse.cpp
@ -32,7 +32,7 @@ function(mapnik_create_benchmark)
add_executable(${TARGET_NAME} ${ARGV0})
target_include_directories(${TARGET_NAME} PRIVATE include)
target_link_libraries(${TARGET_NAME} PRIVATE mapnik::agg mapnik::mapnik)
set_target_properties(${TARGET_NAME} PROPERTIES
set_target_properties(${TARGET_NAME} PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${MAPNIK_OUTPUT_DIR}"
RUNTIME_OUTPUT_DIRECTORY "${MAPNIK_OUTPUT_DIR}"
ARCHIVE_OUTPUT_DIRECTORY "${MAPNIK_OUTPUT_DIR}/lib"
@ -46,7 +46,7 @@ foreach(benchmark ${BENCHMARK_SRCS})
endforeach()
file(COPY data DESTINATION "${MAPNIK_OUTPUT_DIR}/benchmark")
file(COPY run_benchmarks
DESTINATION "${MAPNIK_OUTPUT_DIR}"
file(COPY run_benchmarks
DESTINATION "${MAPNIK_OUTPUT_DIR}"
FILE_PERMISSIONS OWNER_READ OWNER_EXECUTE OWNER_WRITE GROUP_WRITE GROUP_READ GROUP_EXECUTE WORLD_READ
)

View file

@ -9,7 +9,7 @@ Name: @_lib_name@
Description: @_description@
Version: @MAPNIK_VERSION@
Libs: -L"${libdir}" -l$<TARGET_FILE_BASE_NAME:@_target@>$<TARGET_PROPERTY:@_target@,$<CONFIG>_POSTFIX>
Cflags: -I"${includedir}" ]]
Cflags: -I"${includedir}" ]]
_contents @ONLY)
file(GENERATE
@ -26,11 +26,11 @@ endfunction()
function(create_pkg_config_file_mapnik _lib_name _description)
get_target_property(m_compile_defs core INTERFACE_COMPILE_DEFINITIONS)
string(JOIN " -D" m_str_compile_defs ${m_compile_defs})
if(m_str_compile_defs)
if(m_str_compile_defs)
set(m_str_compile_defs "-D${m_str_compile_defs}")
endif()
set(m_requires
set(m_requires
libmapnikwkt
libmapnikjson
icu-uc
@ -71,7 +71,7 @@ Description: @_description@
Version: @MAPNIK_VERSION@
Requires: @m_requires@
Libs: -L"${libdir}" -l$<TARGET_FILE_BASE_NAME:mapnik>$<TARGET_PROPERTY:mapnik,$<CONFIG>_POSTFIX>
Cflags: -I"${includedir}" @m_str_compile_defs@]]
Cflags: -I"${includedir}" @m_str_compile_defs@]]
_contents @ONLY)
file(GENERATE
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_lib_name}-$<CONFIG>.pc

View file

@ -90,7 +90,7 @@ function(mapnik_install_targets)
message(STATUS \"internal_executables: ${_internal_executables}\")
message(STATUS \"internal_libraries: ${_internal_libraries}\")
message(STATUS \"ADDITIONAL_LIBARIES_PATHS: ${ADDITIONAL_LIBARIES_PATHS}\")
include(BundleUtilities)
fixup_bundle(\"${_internal_executables}\" \"${_internal_libraries}\" \"${ADDITIONAL_LIBARIES_PATHS}\")
" COMPONENT MapnikRuntime)

View file

@ -1,5 +1,5 @@
function(format_dir dir)
file(GLOB_RECURSE sources
file(GLOB_RECURSE sources
"${dir}/*.cpp"
"${dir}/*.hpp"
)

View file

@ -32,14 +32,14 @@ function(mapnik_find_plugin_dir PLUGIN_DIR)
string(TOUPPER "${CMAKE_BUILD_TYPE}" _build_type_l)
set(_plugin_dir "${MAPNIK_PLUGINS_DIR_${_build_type_l}}")
# only release has more then one configuration
if(NOT _plugin_dir)
if(NOT _plugin_dir)
set(_all_rel_cfgs RELEASE RELWITHDEBINFO MINSIZEREL)
list(FIND _all_rel_cfgs ${_build_type_l} _is_rel_cfg)
# check if the current configuration is a known release configuration
if(${_is_rel_cfg} GREATER_EQUAL 0)
foreach(_rel_cfg IN LISTS _all_rel_cfgs)
set(_plugin_dir "${MAPNIK_PLUGINS_DIR_${_rel_cfg}}")
if(_plugin_dir)
if(_plugin_dir)
break()
endif()
endforeach()
@ -49,4 +49,4 @@ function(mapnik_find_plugin_dir PLUGIN_DIR)
message(WARNING "Could not find a plugin install dir for configuration ${_build_type_l}")
endif()
set(${PLUGIN_DIR} ${_plugin_dir} PARENT_SCOPE)
endfunction()
endfunction()

View file

@ -1,5 +1,5 @@
add_executable(mapnik-demo rundemo.cpp)
set_target_properties(mapnik-demo PROPERTIES
set_target_properties(mapnik-demo PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${MAPNIK_OUTPUT_DIR}"
RUNTIME_OUTPUT_DIRECTORY "${MAPNIK_OUTPUT_DIR}"
ARCHIVE_OUTPUT_DIRECTORY "${MAPNIK_OUTPUT_DIR}/lib"

View file

@ -14,7 +14,7 @@ set(PROJECT_SOURCES
styles_model.cpp
forms/about.ui
forms/info.ui
forms/layer_info.ui
forms/layer_info.ui
mapnik_viewer.qrc
)
@ -37,7 +37,7 @@ endif()
set_target_properties(mapnik-viewer PROPERTIES
AUTOUIC_SEARCH_PATHS forms
AUTORCC ON
AUTORCC ON
AUTOUIC ON
AUTOMOC ON
LIBRARY_OUTPUT_DIRECTORY "${MAPNIK_OUTPUT_DIR}"
@ -46,13 +46,13 @@ set_target_properties(mapnik-viewer PROPERTIES
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>$<$<BOOL:${BUILD_SHARED_CRT}>:DLL>"
)
target_link_libraries(mapnik-viewer PRIVATE
target_link_libraries(mapnik-viewer PRIVATE
Qt${QT_VERSION_MAJOR}::Widgets
mapnik::agg
mapnik::mapnik
)
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/viewer.ini
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/viewer.ini
"[mapnik]
plugins_dir=${PLUGINS_INSTALL_DIR}
fonts/1/dir=${FONTS_INSTALL_DIR}"

View file

@ -3,8 +3,8 @@ project(agg)
add_library(agg INTERFACE)
add_library(mapnik::agg ALIAS agg)
target_include_directories(agg INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
target_include_directories(agg INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
target_link_libraries(agg INTERFACE mapnik::core)

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -23,477 +23,427 @@
#include "agg_basics.h"
#include "agg_rendering_buffer.h"
namespace agg
namespace agg {
//===================================================one_component_mask_u8
struct one_component_mask_u8
{
//===================================================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
{
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())
{
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;
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;
}
//--------------------------------------------------------------------
cover_type combine_pixel(int x, int y, cover_type val) const
if (x < 0)
{
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)
count += x;
if (count <= 0)
{
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);
memset(covers, 0, -x * sizeof(cover_type));
covers -= x;
x = 0;
}
//--------------------------------------------------------------------
void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
if (x + count > xmax)
{
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)
int rest = x + count - xmax - 1;
count -= rest;
if (count <= 0)
{
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);
memset(covers + count, 0, rest * sizeof(cover_type));
}
//--------------------------------------------------------------------
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
{
int xmax = m_rbuf->width() - 1;
int ymax = m_rbuf->height() - 1;
*covers++ = (cover_type)m_mask_function.calculate(mask);
mask += Step;
} while (--count);
}
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
//--------------------------------------------------------------------
void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
{
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
};
int xmax = m_rbuf->width() - 1;
int ymax = m_rbuf->height() - 1;
amask_no_clip_u8() : m_rbuf(0) {}
explicit amask_no_clip_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
int count = num_pix;
cover_type* covers = dst;
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 (y < 0 || y > ymax)
{
return (cover_type)m_mask_function.calculate(
m_rbuf->row_ptr(y) + x * Step + Offset);
memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
//--------------------------------------------------------------------
cover_type combine_pixel(int x, int y, cover_type val) const
if (x < 0)
{
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
count += x;
if (count <= 0)
{
*dst++ = (cover_type)m_mask_function.calculate(mask);
mask += Step;
memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
while(--num_pix);
memset(covers, 0, -x * sizeof(cover_type));
covers -= x;
x = 0;
}
//--------------------------------------------------------------------
void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
if (x + count > xmax)
{
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
do
int rest = x + count - xmax - 1;
count -= rest;
if (count <= 0)
{
*dst = (cover_type)((cover_full + (*dst) *
m_mask_function.calculate(mask)) >>
cover_shift);
++dst;
mask += Step;
memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
while(--num_pix);
memset(covers + count, 0, rest * sizeof(cover_type));
}
//--------------------------------------------------------------------
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
{
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);
}
*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;
//--------------------------------------------------------------------
void combine_vspan(int x, int y, cover_type* dst, int num_pix) const
int count = num_pix;
cover_type* covers = dst;
if (x < 0 || x > xmax)
{
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);
memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
private:
amask_no_clip_u8(const self_type&);
const self_type& operator = (const self_type&);
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;
}
rendering_buffer* m_rbuf;
MaskF m_mask_function;
};
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));
}
typedef amask_no_clip_u8<1, 0> amask_no_clip_gray8; //----amask_no_clip_gray8
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);
}
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
//--------------------------------------------------------------------
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;
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
int count = num_pix;
cover_type* covers = dst;
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
if (x < 0 || x > xmax)
{
memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
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
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;
}
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
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));
}
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
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);
}
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
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
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -23,52 +23,46 @@
#include <cmath>
#include "agg_basics.h"
namespace agg
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);
//=====================================================================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 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 approximation_scale(double s);
double approximation_scale() const { return m_scale; }
void rewind(unsigned);
unsigned vertex(double* x, double* y);
void rewind(unsigned);
unsigned vertex(double* x, double* y);
private:
void normalize(double a1, double a2, bool ccw);
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;
};
}
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;
};
} // namespace agg
#endif

File diff suppressed because it is too large Load diff

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -13,7 +13,7 @@
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Simple arrowhead/arrowtail generator
// Simple arrowhead/arrowtail generator
//
//----------------------------------------------------------------------------
#ifndef AGG_ARROWHEAD_INCLUDED
@ -21,62 +21,61 @@
#include "agg_basics.h"
namespace agg
namespace agg {
//===============================================================arrowhead
//
// See implementation agg_arrowhead.cpp
//
class arrowhead
{
public:
arrowhead();
//===============================================================arrowhead
//
// See implementation agg_arrowhead.cpp
//
class arrowhead
void head(double d1, double d2, double d3, double d4)
{
public:
arrowhead();
m_head_d1 = d1;
m_head_d2 = d2;
m_head_d3 = d3;
m_head_d4 = d4;
m_head_flag = true;
}
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 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(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 tail() { m_tail_flag = true; }
void no_tail() { m_tail_flag = false; }
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
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;
};
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;
};
}
} // namespace agg
#endif

View file

@ -23,41 +23,41 @@
#ifdef AGG_CUSTOM_ALLOCATOR
#include "agg_allocator.h"
#else
namespace agg
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
{
// 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 static_cast<T*>(::operator new(sizeof(T)*num));}
//static void deallocate(T* ptr, unsigned) { ::operator delete(ptr) ;}
static T* allocate(unsigned num) { return new T [num]; }
static void deallocate(T* ptr, unsigned) { delete [] ptr; }
};
// static T* allocate(unsigned num) { return static_cast<T*>(::operator new(sizeof(T)*num));}
// static void deallocate(T* ptr, unsigned) { ::operator delete(ptr) ;}
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; }
};
}
// 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; }
};
} // namespace agg
#endif
//-------------------------------------------------------- Default basic types
//
// If the compiler has different capacity of the basic types you can redefine
@ -98,7 +98,7 @@ namespace agg
//------------------------------------------------ Some fixes for MS Visual C++
#if defined(_MSC_VER)
#pragma warning(disable:4786) // Identifier was truncated...
#pragma warning(disable: 4786) // Identifier was truncated...
#endif
#if defined(_MSC_VER)
@ -107,372 +107,407 @@ namespace agg
#define AGG_INLINE inline
#endif
namespace agg
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
AGG_INLINE int iround(double v)
{
//-------------------------------------------------------------------------
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
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(std::ceil(v));
}
//---------------------------------------------------------------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)
{
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 std::fabs(v1 - v2) <= double(epsilon);
}
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(std::ceil(v));
}
//---------------------------------------------------------------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)
{
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 std::fabs(v1 - v2) <= double(epsilon);
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -13,7 +13,7 @@
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Arc generator. Produces at most 4 consecutive cubic bezier curves, i.e.,
// Arc generator. Produces at most 4 consecutive cubic bezier curves, i.e.,
// 4, 7, 10, or 13 vertices.
//
//----------------------------------------------------------------------------
@ -23,137 +23,127 @@
#include "agg_conv_transform.h"
namespace agg
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
{
//-----------------------------------------------------------------------
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)
{
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);
}
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 init(double x, double y, double rx, double ry, double start_angle, double sweep_angle);
//--------------------------------------------------------------------
void rewind(unsigned)
{
m_vertex = 0;
}
//--------------------------------------------------------------------
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) ? (unsigned)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
//--------------------------------------------------------------------
unsigned vertex(double* x, double* y)
{
public:
//--------------------------------------------------------------------
bezier_arc_svg() : m_arc(), m_radii_ok(false) {}
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) ? (unsigned)path_cmd_move_to : m_cmd;
}
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);
}
// 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; }
//--------------------------------------------------------------------
void init(double x1, double y1,
double rx, double ry,
double angle,
bool large_arc_flag,
bool sweep_flag,
double x2, double y2);
private:
unsigned m_vertex;
unsigned m_num_vertices;
double m_vertices[26];
unsigned m_cmd;
};
//--------------------------------------------------------------------
bool radii_ok() const { return m_radii_ok; }
//==========================================================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)
{}
//--------------------------------------------------------------------
void rewind(unsigned)
{
m_arc.rewind(0);
}
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);
}
//--------------------------------------------------------------------
unsigned vertex(double* x, double* y)
{
return m_arc.vertex(x, y);
}
//--------------------------------------------------------------------
void init(double x1,
double y1,
double rx,
double ry,
double angle,
bool large_arc_flag,
bool sweep_flag,
double x2,
double y2);
// 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(); }
//--------------------------------------------------------------------
bool radii_ok() const { return m_radii_ok; }
private:
bezier_arc m_arc;
bool 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;
};
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -18,37 +18,33 @@
#include "agg_basics.h"
namespace agg
namespace agg {
class bitset_iterator
{
class bitset_iterator
public:
bitset_iterator(const int8u* bits, unsigned offset = 0)
: m_bits(bits + (offset >> 3))
, m_mask(0x80 >> (offset & 7))
{}
void operator++()
{
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_mask >>= 1;
if(m_mask == 0)
{
++m_bits;
m_mask = 0x80;
}
++m_bits;
m_mask = 0x80;
}
}
unsigned bit() const
{
return (*m_bits) & m_mask;
}
unsigned bit() const { return (*m_bits) & m_mask; }
private:
const int8u* m_bits;
int8u m_mask;
};
private:
const int8u* m_bits;
int8u m_mask;
};
}
} // namespace agg
#endif

File diff suppressed because it is too large Load diff

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -21,76 +21,38 @@
#include "agg_basics.h"
namespace agg
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;
//-----------------------------------------------------------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)
*x1 = CoordT(1);
*y1 = CoordT(1);
*x2 = CoordT(0);
*y2 = CoordT(0);
for (i = 0; i < num; i++)
{
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);
vs.rewind(gi[start + i]);
unsigned cmd;
while(!is_stop(cmd = vs.vertex(&x, &y)))
while (!is_stop(cmd = vs.vertex(&x, &y)))
{
if(is_vertex(cmd))
if (is_vertex(cmd))
{
if(first)
if (first)
{
*x1 = CoordT(x);
*y1 = CoordT(y);
@ -100,17 +62,64 @@ namespace agg
}
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);
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;
}
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;
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -22,55 +22,53 @@
#include "agg_array.h"
namespace agg
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
{
//----------------------------------------------------------------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);
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);
void add_point(double x, double y);
void prepare();
void init(int num, const double* x, const double* y);
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&);
double get(double x) const;
double get_stateful(double x) const;
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;
private:
bspline(const bspline&);
const bspline& operator=(const bspline&);
int m_max;
int m_num;
double* m_x;
double* m_y;
pod_array<double> m_am;
mutable int m_last_idx;
};
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;
};
}
} // namespace agg
#endif

View file

@ -21,313 +21,296 @@
#include "agg_basics.h"
namespace agg
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);
}
//------------------------------------------------------------------------
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_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
// 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)
//--------------------------------------------------------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)
{
return (x > clip_box.x2) |
((y > clip_box.y2) << 1) |
((x < clip_box.x1) << 2) |
((y < clip_box.y1) << 3);
// bump off of the vertical
deltax = (x1 > clip_box.x1) ? -nearzero : nearzero;
}
//--------------------------------------------------------clipping_flags_x
template<class T>
inline unsigned clipping_flags_x(T x, const rect_base<T>& clip_box)
if (deltay == 0.0)
{
return (x > clip_box.x2) | ((x < clip_box.x1) << 2);
// bump off of the horizontal
deltay = (y1 > clip_box.y1) ? -nearzero : nearzero;
}
//--------------------------------------------------------clipping_flags_y
template<class T>
inline unsigned clipping_flags_y(T y, const rect_base<T>& clip_box)
if (deltax > 0.0)
{
return ((y > clip_box.y2) << 1) | ((y < clip_box.y1) << 3);
// points to right
xin = clip_box.x1;
xout = clip_box.x2;
}
else
{
xin = clip_box.x2;
xout = clip_box.x1;
}
//-------------------------------------------------------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)
if (deltay > 0.0)
{
const double nearzero = 1e-30;
// points up
yin = clip_box.y1;
yout = clip_box.y2;
}
else
{
yin = clip_box.y2;
yout = clip_box.y1;
}
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;
tinx = (xin - x1) / deltax;
tiny = (yin - y1) / deltay;
if(deltax == 0.0)
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)
{
// bump off of the vertical
deltax = (x1 > clip_box.x1) ? -nearzero : nearzero;
*x++ = (T)xin;
*y++ = (T)yin;
++np;
}
if(deltay == 0.0)
if (tin2 <= 1.0)
{
// bump off of the horizontal
deltay = (y1 > clip_box.y1) ? -nearzero : nearzero;
}
toutx = (xout - x1) / deltax;
touty = (yout - y1) / deltay;
if(deltax > 0.0)
{
// points to right
xin = clip_box.x1;
xout = clip_box.x2;
}
else
{
xin = clip_box.x2;
xout = clip_box.x1;
}
tout1 = (toutx < touty) ? toutx : touty;
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)
if (tin2 > 0.0 || tout1 > 0.0)
{
*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 <= tout1)
if (tin2 > 0.0)
{
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)
if (tinx > tiny)
{
*x++ = (T)xin;
*y++ = (T)yout;
*y++ = (T)(y1 + tinx * deltay);
}
else
{
*x++ = (T)xout;
*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;
}
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;
}
} // namespace agg
#endif

View file

@ -31,21 +31,19 @@
#include "agg_basics.h"
#include "agg_color_rgba.h"
namespace agg
{
namespace agg {
//===================================================================gray8
template<class Colorspace>
struct gray8T
{
typedef int8u value_type;
typedef int8u value_type;
typedef int32u calc_type;
typedef int32 long_type;
enum base_scale_e
{
typedef int32 long_type;
enum base_scale_e {
base_shift = 8,
base_scale = 1 << base_shift,
base_mask = base_scale - 1,
base_mask = base_scale - 1,
base_MSB = 1 << (base_shift - 1)
};
typedef gray8T self_type;
@ -105,17 +103,22 @@ struct gray8T
gray8T() {}
//--------------------------------------------------------------------
gray8T(unsigned v_, unsigned a_=base_mask) :
v(int8u(v_)), a(int8u(a_)) {}
gray8T(unsigned v_, unsigned a_ = base_mask)
: v(int8u(v_))
, a(int8u(a_))
{}
//--------------------------------------------------------------------
gray8T(const self_type& c, unsigned a_) :
v(c.v), a(value_type(a_)) {}
gray8T(const self_type& c, unsigned a_)
: v(c.v)
, a(value_type(a_))
{}
//--------------------------------------------------------------------
gray8T(const rgba& c) :
v(luminance(c)),
a(value_type(uround(c.a * base_mask))) {}
gray8T(const rgba& c)
: v(luminance(c))
, a(value_type(uround(c.a * base_mask)))
{}
//--------------------------------------------------------------------
template<class T>
@ -147,36 +150,18 @@ struct gray8T
}
//--------------------------------------------------------------------
rgba8 make_rgba8(const linear&) const
{
return rgba8(v, v, v, a);
}
rgba8 make_rgba8(const linear&) const { return rgba8(v, v, v, a); }
rgba8 make_rgba8(const sRGB&) const
{
return convert_from_sRGB<srgba8>();
}
rgba8 make_rgba8(const sRGB&) const { return convert_from_sRGB<srgba8>(); }
operator rgba8() const
{
return make_rgba8(Colorspace());
}
operator rgba8() const { return make_rgba8(Colorspace()); }
//--------------------------------------------------------------------
srgba8 make_srgba8(const linear&) const
{
return convert_to_sRGB<rgba8>();
}
srgba8 make_srgba8(const linear&) const { return convert_to_sRGB<rgba8>(); }
srgba8 make_srgba8(const sRGB&) const
{
return srgba8(v, v, v, a);
}
srgba8 make_srgba8(const sRGB&) const { return srgba8(v, v, v, a); }
operator srgba8() const
{
return make_rgba8(Colorspace());
}
operator srgba8() const { return make_rgba8(Colorspace()); }
//--------------------------------------------------------------------
rgba16 make_rgba16(const linear&) const
@ -185,15 +170,9 @@ struct gray8T
return rgba16(rgb, rgb, rgb, (a << 8) | a);
}
rgba16 make_rgba16(const sRGB&) const
{
return convert_from_sRGB<rgba16>();
}
rgba16 make_rgba16(const sRGB&) const { return convert_from_sRGB<rgba16>(); }
operator rgba16() const
{
return make_rgba16(Colorspace());
}
operator rgba16() const { return make_rgba16(Colorspace()); }
//--------------------------------------------------------------------
rgba32 make_rgba32(const linear&) const
@ -202,51 +181,27 @@ struct gray8T
return rgba32(v32, v32, v32, a / 255.0);
}
rgba32 make_rgba32(const sRGB&) const
{
return convert_from_sRGB<rgba32>();
}
rgba32 make_rgba32(const sRGB&) const { return convert_from_sRGB<rgba32>(); }
operator rgba32() const
{
return make_rgba32(Colorspace());
}
operator rgba32() const { return make_rgba32(Colorspace()); }
//--------------------------------------------------------------------
static AGG_INLINE double to_double(value_type a)
{
return double(a) / base_mask;
}
static AGG_INLINE double to_double(value_type a) { return double(a) / base_mask; }
//--------------------------------------------------------------------
static AGG_INLINE value_type from_double(double a)
{
return value_type(uround(a * base_mask));
}
static AGG_INLINE value_type from_double(double a) { return value_type(uround(a * base_mask)); }
//--------------------------------------------------------------------
static AGG_INLINE value_type empty_value()
{
return 0;
}
static AGG_INLINE value_type empty_value() { return 0; }
//--------------------------------------------------------------------
static AGG_INLINE value_type full_value()
{
return base_mask;
}
static AGG_INLINE value_type full_value() { return base_mask; }
//--------------------------------------------------------------------
AGG_INLINE bool is_transparent() const
{
return a == 0;
}
AGG_INLINE bool is_transparent() const { return a == 0; }
//--------------------------------------------------------------------
AGG_INLINE bool is_opaque() const
{
return a == base_mask;
}
AGG_INLINE bool is_opaque() const { return a == base_mask; }
//--------------------------------------------------------------------
// Fixed-point multiply, exact over int8u.
@ -267,7 +222,8 @@ struct gray8T
{
return base_mask;
}
else return value_type((a * base_mask + (b >> 1)) / b);
else
return value_type((a * base_mask + (b >> 1)) / b);
}
//--------------------------------------------------------------------
@ -287,23 +243,14 @@ struct gray8T
//--------------------------------------------------------------------
// Fixed-point multiply, exact over int8u.
// Specifically for multiplying a color component by a cover.
static AGG_INLINE value_type mult_cover(value_type a, value_type b)
{
return multiply(a, b);
}
static AGG_INLINE value_type mult_cover(value_type a, value_type b) { return multiply(a, b); }
//--------------------------------------------------------------------
static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
{
return multiply(b, a);
}
static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) { return multiply(b, a); }
//--------------------------------------------------------------------
// Interpolate p to q by a, assuming q is premultiplied by a.
static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
{
return p + q - multiply(p, a);
}
static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a) { return p + q - multiply(p, a); }
//--------------------------------------------------------------------
// Interpolate p to q by a.
@ -330,25 +277,27 @@ struct gray8T
//--------------------------------------------------------------------
self_type& opacity(double a_)
{
if (a_ < 0) a = 0;
else if (a_ > 1) a = 1;
else a = (value_type)uround(a_ * double(base_mask));
if (a_ < 0)
a = 0;
else if (a_ > 1)
a = 1;
else
a = (value_type)uround(a_ * double(base_mask));
return *this;
}
//--------------------------------------------------------------------
double opacity() const
{
return double(a) / double(base_mask);
}
double opacity() const { return double(a) / double(base_mask); }
//--------------------------------------------------------------------
self_type& premultiply()
{
if (a < base_mask)
{
if (a == 0) v = 0;
else v = multiply(v, a);
if (a == 0)
v = 0;
else
v = multiply(v, a);
}
return *this;
}
@ -408,24 +357,22 @@ struct gray8T
}
//--------------------------------------------------------------------
static self_type no_color() { return self_type(0,0); }
static self_type no_color() { return self_type(0, 0); }
};
typedef gray8T<linear> gray8;
typedef gray8T<sRGB> sgray8;
//==================================================================gray16
struct gray16
{
typedef int16u value_type;
typedef int32u calc_type;
typedef int64 long_type;
enum base_scale_e
{
typedef int64 long_type;
enum base_scale_e {
base_shift = 16,
base_scale = 1 << base_shift,
base_mask = base_scale - 1,
base_mask = base_scale - 1,
base_MSB = 1 << (base_shift - 1)
};
typedef gray16 self_type;
@ -445,67 +392,65 @@ struct gray16
return value_type((13933u * c.r + 46872u * c.g + 4732u * c.b) >> 16);
}
static value_type luminance(const rgba8& c)
{
return luminance(rgba16(c));
}
static value_type luminance(const rgba8& c) { return luminance(rgba16(c)); }
static value_type luminance(const srgba8& c)
{
return luminance(rgba16(c));
}
static value_type luminance(const srgba8& c) { return luminance(rgba16(c)); }
static value_type luminance(const rgba32& c)
{
return luminance(rgba(c));
}
static value_type luminance(const rgba32& c) { return luminance(rgba(c)); }
//--------------------------------------------------------------------
gray16() {}
//--------------------------------------------------------------------
gray16(unsigned v_, unsigned a_ = base_mask) :
v(int16u(v_)), a(int16u(a_)) {}
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 self_type& c, unsigned a_)
: v(c.v)
, a(value_type(a_))
{}
//--------------------------------------------------------------------
gray16(const rgba& c) :
v(luminance(c)),
a((value_type)uround(c.a * double(base_mask))) {}
gray16(const rgba& c)
: v(luminance(c))
, a((value_type)uround(c.a * double(base_mask)))
{}
//--------------------------------------------------------------------
gray16(const rgba8& c) :
v(luminance(c)),
a((value_type(c.a) << 8) | c.a) {}
gray16(const rgba8& c)
: v(luminance(c))
, a((value_type(c.a) << 8) | c.a)
{}
//--------------------------------------------------------------------
gray16(const srgba8& c) :
v(luminance(c)),
a((value_type(c.a) << 8) | c.a) {}
gray16(const srgba8& c)
: v(luminance(c))
, a((value_type(c.a) << 8) | c.a)
{}
//--------------------------------------------------------------------
gray16(const rgba16& c) :
v(luminance(c)),
a(c.a) {}
gray16(const rgba16& c)
: v(luminance(c))
, a(c.a)
{}
//--------------------------------------------------------------------
gray16(const gray8& c) :
v((value_type(c.v) << 8) | c.v),
a((value_type(c.a) << 8) | c.a) {}
gray16(const gray8& c)
: v((value_type(c.v) << 8) | c.v)
, a((value_type(c.a) << 8) | c.a)
{}
//--------------------------------------------------------------------
gray16(const sgray8& c) :
v(sRGB_conv<value_type>::rgb_from_sRGB(c.v)),
a(sRGB_conv<value_type>::alpha_from_sRGB(c.a)) {}
gray16(const sgray8& c)
: v(sRGB_conv<value_type>::rgb_from_sRGB(c.v))
, a(sRGB_conv<value_type>::alpha_from_sRGB(c.a))
{}
//--------------------------------------------------------------------
operator rgba8() const
{
return rgba8(v >> 8, v >> 8, v >> 8, a >> 8);
}
operator rgba8() const { return rgba8(v >> 8, v >> 8, v >> 8, a >> 8); }
//--------------------------------------------------------------------
operator srgba8() const
@ -515,60 +460,34 @@ struct gray16
}
//--------------------------------------------------------------------
operator rgba16() const
{
return rgba16(v, v, v, a);
}
operator rgba16() const { return rgba16(v, v, v, a); }
//--------------------------------------------------------------------
operator gray8() const
{
return gray8(v >> 8, a >> 8);
}
operator gray8() const { return gray8(v >> 8, a >> 8); }
//--------------------------------------------------------------------
operator sgray8() const
{
return sgray8(
sRGB_conv<value_type>::rgb_to_sRGB(v),
sRGB_conv<value_type>::alpha_to_sRGB(a));
return sgray8(sRGB_conv<value_type>::rgb_to_sRGB(v), sRGB_conv<value_type>::alpha_to_sRGB(a));
}
//--------------------------------------------------------------------
static AGG_INLINE double to_double(value_type a)
{
return double(a) / base_mask;
}
static AGG_INLINE double to_double(value_type a) { return double(a) / base_mask; }
//--------------------------------------------------------------------
static AGG_INLINE value_type from_double(double a)
{
return value_type(uround(a * base_mask));
}
static AGG_INLINE value_type from_double(double a) { return value_type(uround(a * base_mask)); }
//--------------------------------------------------------------------
static AGG_INLINE value_type empty_value()
{
return 0;
}
static AGG_INLINE value_type empty_value() { return 0; }
//--------------------------------------------------------------------
static AGG_INLINE value_type full_value()
{
return base_mask;
}
static AGG_INLINE value_type full_value() { return base_mask; }
//--------------------------------------------------------------------
AGG_INLINE bool is_transparent() const
{
return a == 0;
}
AGG_INLINE bool is_transparent() const { return a == 0; }
//--------------------------------------------------------------------
AGG_INLINE bool is_opaque() const
{
return a == base_mask;
}
AGG_INLINE bool is_opaque() const { return a == base_mask; }
//--------------------------------------------------------------------
// Fixed-point multiply, exact over int16u.
@ -589,7 +508,8 @@ struct gray16
{
return base_mask;
}
else return value_type((a * base_mask + (b >> 1)) / b);
else
return value_type((a * base_mask + (b >> 1)) / b);
}
//--------------------------------------------------------------------
@ -609,23 +529,14 @@ struct gray16
//--------------------------------------------------------------------
// Fixed-point multiply, almost exact over int16u.
// Specifically for multiplying a color component by a cover.
static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
{
return multiply(a, b << 8 | b);
}
static AGG_INLINE value_type mult_cover(value_type a, cover_type b) { return multiply(a, b << 8 | b); }
//--------------------------------------------------------------------
static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
{
return mult_cover(b, a) >> 8;
}
static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) { return mult_cover(b, a) >> 8; }
//--------------------------------------------------------------------
// Interpolate p to q by a, assuming q is premultiplied by a.
static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
{
return p + q - multiply(p, a);
}
static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a) { return p + q - multiply(p, a); }
//--------------------------------------------------------------------
// Interpolate p to q by a.
@ -652,26 +563,27 @@ struct gray16
//--------------------------------------------------------------------
self_type& opacity(double a_)
{
if (a_ < 0) a = 0;
else if(a_ > 1) a = 1;
else a = (value_type)uround(a_ * double(base_mask));
if (a_ < 0)
a = 0;
else if (a_ > 1)
a = 1;
else
a = (value_type)uround(a_ * double(base_mask));
return *this;
}
//--------------------------------------------------------------------
double opacity() const
{
return double(a) / double(base_mask);
}
double opacity() const { return double(a) / double(base_mask); }
//--------------------------------------------------------------------
self_type& premultiply()
{
if (a < base_mask)
{
if(a == 0) v = 0;
else v = multiply(v, a);
if (a == 0)
v = 0;
else
v = multiply(v, a);
}
return *this;
}
@ -731,10 +643,9 @@ struct gray16
}
//--------------------------------------------------------------------
static self_type no_color() { return self_type(0,0); }
static self_type no_color() { return self_type(0, 0); }
};
//===================================================================gray32
struct gray32
{
@ -746,11 +657,10 @@ struct gray32
value_type v;
value_type a;
enum base_scale_e
{
enum base_scale_e {
base_shift = 8,
base_scale = 1 << base_shift,
base_mask = base_scale - 1,
base_mask = base_scale - 1,
};
// Calculate grayscale value as per ITU-R BT.709.
@ -759,103 +669,92 @@ struct gray32
return value_type(0.2126 * r + 0.7152 * g + 0.0722 * b);
}
static value_type luminance(const rgba& c)
{
return luminance(c.r, c.g, c.b);
}
static value_type luminance(const rgba& c) { return luminance(c.r, c.g, c.b); }
static value_type luminance(const rgba32& c)
{
return luminance(c.r, c.g, c.b);
}
static value_type luminance(const rgba32& c) { return luminance(c.r, c.g, c.b); }
static value_type luminance(const rgba8& c)
{
return luminance(c.r / 255.0, c.g / 255.0, c.g / 255.0);
}
static value_type luminance(const rgba8& c) { return luminance(c.r / 255.0, c.g / 255.0, c.g / 255.0); }
static value_type luminance(const rgba16& c)
{
return luminance(c.r / 65535.0, c.g / 65535.0, c.g / 65535.0);
}
static value_type luminance(const rgba16& c) { return luminance(c.r / 65535.0, c.g / 65535.0, c.g / 65535.0); }
//--------------------------------------------------------------------
gray32() {}
//--------------------------------------------------------------------
gray32(value_type v_, value_type a_ = 1) :
v(v_), a(a_) {}
gray32(value_type v_, value_type a_ = 1)
: v(v_)
, a(a_)
{}
//--------------------------------------------------------------------
gray32(const self_type& c, value_type a_) :
v(c.v), a(a_) {}
gray32(const self_type& c, value_type a_)
: v(c.v)
, a(a_)
{}
//--------------------------------------------------------------------
gray32(const rgba& c) :
v(luminance(c)),
a(value_type(c.a)) {}
gray32(const rgba& c)
: v(luminance(c))
, a(value_type(c.a))
{}
//--------------------------------------------------------------------
gray32(const rgba8& c) :
v(luminance(c)),
a(value_type(c.a / 255.0)) {}
gray32(const rgba8& c)
: v(luminance(c))
, a(value_type(c.a / 255.0))
{}
//--------------------------------------------------------------------
gray32(const srgba8& c) :
v(luminance(rgba32(c))),
a(value_type(c.a / 255.0)) {}
gray32(const srgba8& c)
: v(luminance(rgba32(c)))
, a(value_type(c.a / 255.0))
{}
//--------------------------------------------------------------------
gray32(const rgba16& c) :
v(luminance(c)),
a(value_type(c.a / 65535.0)) {}
gray32(const rgba16& c)
: v(luminance(c))
, a(value_type(c.a / 65535.0))
{}
//--------------------------------------------------------------------
gray32(const rgba32& c) :
v(luminance(c)),
a(value_type(c.a)) {}
gray32(const rgba32& c)
: v(luminance(c))
, a(value_type(c.a))
{}
//--------------------------------------------------------------------
gray32(const gray8& c) :
v(value_type(c.v / 255.0)),
a(value_type(c.a / 255.0)) {}
gray32(const gray8& c)
: v(value_type(c.v / 255.0))
, a(value_type(c.a / 255.0))
{}
//--------------------------------------------------------------------
gray32(const sgray8& c) :
v(sRGB_conv<value_type>::rgb_from_sRGB(c.v)),
a(sRGB_conv<value_type>::alpha_from_sRGB(c.a)) {}
gray32(const sgray8& c)
: v(sRGB_conv<value_type>::rgb_from_sRGB(c.v))
, a(sRGB_conv<value_type>::alpha_from_sRGB(c.a))
{}
//--------------------------------------------------------------------
gray32(const gray16& c) :
v(value_type(c.v / 65535.0)),
a(value_type(c.a / 65535.0)) {}
gray32(const gray16& c)
: v(value_type(c.v / 65535.0))
, a(value_type(c.a / 65535.0))
{}
//--------------------------------------------------------------------
operator rgba() const
{
return rgba(v, v, v, a);
}
operator rgba() const { return rgba(v, v, v, a); }
//--------------------------------------------------------------------
operator gray8() const
{
return gray8(uround(v * 255.0), uround(a * 255.0));
}
operator gray8() const { return gray8(uround(v * 255.0), uround(a * 255.0)); }
//--------------------------------------------------------------------
operator sgray8() const
{
// Return (non-premultiplied) sRGB values.
return sgray8(
sRGB_conv<value_type>::rgb_to_sRGB(v),
sRGB_conv<value_type>::alpha_to_sRGB(a));
return sgray8(sRGB_conv<value_type>::rgb_to_sRGB(v), sRGB_conv<value_type>::alpha_to_sRGB(a));
}
//--------------------------------------------------------------------
operator gray16() const
{
return gray16(uround(v * 65535.0), uround(a * 65535.0));
}
operator gray16() const { return gray16(uround(v * 65535.0), uround(a * 65535.0)); }
//--------------------------------------------------------------------
operator rgba8() const
@ -879,58 +778,31 @@ struct gray32
}
//--------------------------------------------------------------------
static AGG_INLINE double to_double(value_type a)
{
return a;
}
static AGG_INLINE double to_double(value_type a) { return a; }
//--------------------------------------------------------------------
static AGG_INLINE value_type from_double(double a)
{
return value_type(a);
}
static AGG_INLINE value_type from_double(double a) { return value_type(a); }
//--------------------------------------------------------------------
static AGG_INLINE value_type empty_value()
{
return 0;
}
static AGG_INLINE value_type empty_value() { return 0; }
//--------------------------------------------------------------------
static AGG_INLINE value_type full_value()
{
return 1;
}
static AGG_INLINE value_type full_value() { return 1; }
//--------------------------------------------------------------------
AGG_INLINE bool is_transparent() const
{
return a <= 0;
}
AGG_INLINE bool is_transparent() const { return a <= 0; }
//--------------------------------------------------------------------
AGG_INLINE bool is_opaque() const
{
return a >= 1;
}
AGG_INLINE bool is_opaque() const { return a >= 1; }
//--------------------------------------------------------------------
static AGG_INLINE value_type invert(value_type x)
{
return 1 - x;
}
static AGG_INLINE value_type invert(value_type x) { return 1 - x; }
//--------------------------------------------------------------------
static AGG_INLINE value_type multiply(value_type a, value_type b)
{
return value_type(a * b);
}
static AGG_INLINE value_type multiply(value_type a, value_type b) { return value_type(a * b); }
//--------------------------------------------------------------------
static AGG_INLINE value_type demultiply(value_type a, value_type b)
{
return (b == 0) ? 0 : value_type(a / b);
}
static AGG_INLINE value_type demultiply(value_type a, value_type b) { return (b == 0) ? 0 : value_type(a / b); }
//--------------------------------------------------------------------
template<typename T>
@ -947,16 +819,10 @@ struct gray32
}
//--------------------------------------------------------------------
static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
{
return value_type(a * b / cover_mask);
}
static AGG_INLINE value_type mult_cover(value_type a, cover_type b) { return value_type(a * b / cover_mask); }
//--------------------------------------------------------------------
static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
{
return cover_type(uround(a * b));
}
static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) { return cover_type(uround(a * b)); }
//--------------------------------------------------------------------
// Interpolate p to q by a, assuming q is premultiplied by a.
@ -993,49 +859,47 @@ struct gray32
//--------------------------------------------------------------------
self_type& opacity(double a_)
{
if (a_ < 0) a = 0;
else if (a_ > 1) a = 1;
else a = value_type(a_);
if (a_ < 0)
a = 0;
else if (a_ > 1)
a = 1;
else
a = value_type(a_);
return *this;
}
//--------------------------------------------------------------------
double opacity() const
{
return a;
}
double opacity() const { return a; }
//--------------------------------------------------------------------
self_type& premultiply()
{
if (a < 0) v = 0;
else if(a < 1) v *= a;
if (a < 0)
v = 0;
else if (a < 1)
v *= a;
return *this;
}
//--------------------------------------------------------------------
self_type& demultiply()
{
if (a < 0) v = 0;
else if (a < 1) v /= a;
if (a < 0)
v = 0;
else if (a < 1)
v /= a;
return *this;
}
//--------------------------------------------------------------------
self_type gradient(self_type c, double k) const
{
return self_type(
value_type(v + (c.v - v) * k),
value_type(a + (c.a - a) * k));
return self_type(value_type(v + (c.v - v) * k), value_type(a + (c.a - a) * k));
}
//--------------------------------------------------------------------
static self_type no_color() { return self_type(0,0); }
static self_type no_color() { return self_type(0, 0); }
};
}
} // namespace agg
#endif

View file

@ -28,20 +28,39 @@
#include "agg_basics.h"
#include "agg_gamma_lut.h"
namespace agg
{
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, hasAlpha=false }; }; //----order_rgb
struct order_bgr { enum bgr_e { B=0, G=1, R=2, rgb_tag, hasAlpha=false }; }; //----order_bgr
struct order_rgba { enum rgba_e { R=0, G=1, B=2, A=3, rgba_tag, hasAlpha=true }; }; //----order_rgba
struct order_argb { enum argb_e { A=0, R=1, G=2, B=3, rgba_tag, hasAlpha=true }; }; //----order_argb
struct order_abgr { enum abgr_e { A=0, B=1, G=2, R=3, rgba_tag, hasAlpha=true }; }; //----order_abgr
struct order_bgra { enum bgra_e { B=0, G=1, R=2, A=3, rgba_tag, hasAlpha=true }; }; //----order_bgra
struct order_rgb
{
enum rgb_e { R = 0, G = 1, B = 2, rgb_tag, hasAlpha = false };
}; //----order_rgb
struct order_bgr
{
enum bgr_e { B = 0, G = 1, R = 2, rgb_tag, hasAlpha = false };
}; //----order_bgr
struct order_rgba
{
enum rgba_e { R = 0, G = 1, B = 2, A = 3, rgba_tag, hasAlpha = true };
}; //----order_rgba
struct order_argb
{
enum argb_e { A = 0, R = 1, G = 2, B = 3, rgba_tag, hasAlpha = true };
}; //----order_argb
struct order_abgr
{
enum abgr_e { A = 0, B = 1, G = 2, R = 3, rgba_tag, hasAlpha = true };
}; //----order_abgr
struct order_bgra
{
enum bgra_e { B = 0, G = 1, R = 2, A = 3, rgba_tag, hasAlpha = true };
}; //----order_bgra
// Colorspace tag types.
struct linear {};
struct sRGB {};
struct linear
{};
struct sRGB
{};
//====================================================================rgba
struct rgba
@ -57,11 +76,20 @@ struct rgba
rgba() {}
//--------------------------------------------------------------------
rgba(double r_, double g_, double b_, double a_=1.0) :
r(r_), g(g_), b(b_), a(a_) {}
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_) {}
rgba(const rgba& c, double a_)
: r(c.r)
, g(c.g)
, b(c.b)
, a(a_)
{}
//--------------------------------------------------------------------
rgba& clear()
@ -80,17 +108,17 @@ struct rgba
//--------------------------------------------------------------------
rgba& opacity(double a_)
{
if (a_ < 0) a = 0;
else if (a_ > 1) a = 1;
else a = a_;
if (a_ < 0)
a = 0;
else if (a_ > 1)
a = 1;
else
a = a_;
return *this;
}
//--------------------------------------------------------------------
double opacity() const
{
return a;
}
double opacity() const { return a; }
//--------------------------------------------------------------------
rgba& premultiply()
@ -114,7 +142,7 @@ struct rgba
r *= a_;
g *= a_;
b *= a_;
a = a_;
a = a_;
}
return *this;
}
@ -136,7 +164,6 @@ struct rgba
return *this;
}
//--------------------------------------------------------------------
rgba gradient(rgba c, double k) const
{
@ -167,17 +194,13 @@ struct rgba
}
//--------------------------------------------------------------------
static rgba no_color() { return rgba(0,0,0,0); }
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);
}
explicit rgba(double wavelen, double gamma = 1.0) { *this = from_wavelength(wavelen, gamma); }
};
inline rgba operator+(const rgba& a, const rgba& b)
@ -226,8 +249,10 @@ inline rgba rgba::from_wavelength(double wl, double gamma)
}
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);
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);
@ -240,24 +265,21 @@ inline rgba rgba_pre(double r, double g, double b, double a)
return rgba(r, g, b, a).premultiply();
}
//===================================================================rgba8
template<class Colorspace>
struct rgba8T
{
typedef int8u value_type;
typedef int8u value_type;
typedef int32u calc_type;
typedef int32 long_type;
enum base_scale_e
{
typedef int32 long_type;
enum base_scale_e {
base_shift = 8,
base_scale = 1 << base_shift,
base_mask = base_scale - 1,
base_mask = base_scale - 1,
base_MSB = 1 << (base_shift - 1)
};
typedef rgba8T self_type;
value_type r;
value_type g;
value_type b;
@ -317,21 +339,23 @@ struct rgba8T
rgba8T() {}
//--------------------------------------------------------------------
rgba8T(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_)) {}
rgba8T(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_))
{}
//--------------------------------------------------------------------
rgba8T(const rgba& c)
{
convert(*this, c);
}
rgba8T(const rgba& c) { convert(*this, c); }
//--------------------------------------------------------------------
rgba8T(const self_type& c, unsigned a_) :
r(c.r), g(c.g), b(c.b), a(value_type(a_)) {}
rgba8T(const self_type& c, unsigned a_)
: r(c.r)
, g(c.g)
, b(c.b)
, a(value_type(a_))
{}
//--------------------------------------------------------------------
template<class T>
@ -349,46 +373,25 @@ struct rgba8T
}
//--------------------------------------------------------------------
static AGG_INLINE double to_double(value_type a)
{
return double(a) / base_mask;
}
static AGG_INLINE double to_double(value_type a) { return double(a) / base_mask; }
//--------------------------------------------------------------------
static AGG_INLINE value_type from_double(double a)
{
return value_type(uround(a * base_mask));
}
static AGG_INLINE value_type from_double(double a) { return value_type(uround(a * base_mask)); }
//--------------------------------------------------------------------
static AGG_INLINE value_type empty_value()
{
return 0;
}
static AGG_INLINE value_type empty_value() { return 0; }
//--------------------------------------------------------------------
static AGG_INLINE value_type full_value()
{
return base_mask;
}
static AGG_INLINE value_type full_value() { return base_mask; }
//--------------------------------------------------------------------
AGG_INLINE bool is_transparent() const
{
return a == 0;
}
AGG_INLINE bool is_transparent() const { return a == 0; }
//--------------------------------------------------------------------
AGG_INLINE bool is_opaque() const
{
return a == base_mask;
}
AGG_INLINE bool is_opaque() const { return a == base_mask; }
//--------------------------------------------------------------------
static AGG_INLINE value_type invert(value_type x)
{
return base_mask - x;
}
static AGG_INLINE value_type invert(value_type x) { return base_mask - x; }
//--------------------------------------------------------------------
// Fixed-point multiply, exact over int8u.
@ -409,7 +412,8 @@ struct rgba8T
{
return base_mask;
}
else return value_type((a * base_mask + (b >> 1)) / b);
else
return value_type((a * base_mask + (b >> 1)) / b);
}
//--------------------------------------------------------------------
@ -429,23 +433,14 @@ struct rgba8T
//--------------------------------------------------------------------
// Fixed-point multiply, exact over int8u.
// Specifically for multiplying a color component by a cover.
static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
{
return multiply(a, b);
}
static AGG_INLINE value_type mult_cover(value_type a, cover_type b) { return multiply(a, b); }
//--------------------------------------------------------------------
static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
{
return multiply(b, a);
}
static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) { return multiply(b, a); }
//--------------------------------------------------------------------
// Interpolate p to q by a, assuming q is premultiplied by a.
static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
{
return p + q - multiply(p, a);
}
static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a) { return p + q - multiply(p, a); }
//--------------------------------------------------------------------
// Interpolate p to q by a.
@ -472,17 +467,17 @@ struct rgba8T
//--------------------------------------------------------------------
self_type& opacity(double a_)
{
if (a_ < 0) a = 0;
else if (a_ > 1) a = 1;
else a = (value_type)uround(a_ * double(base_mask));
if (a_ < 0)
a = 0;
else if (a_ > 1)
a = 1;
else
a = (value_type)uround(a_ * double(base_mask));
return *this;
}
//--------------------------------------------------------------------
double opacity() const
{
return double(a) / double(base_mask);
}
double opacity() const { return double(a) / double(base_mask); }
//--------------------------------------------------------------------
AGG_INLINE self_type& premultiply()
@ -604,7 +599,7 @@ struct rgba8T
}
//--------------------------------------------------------------------
static self_type no_color() { return self_type(0,0,0,0); }
static self_type no_color() { return self_type(0, 0, 0, 0); }
//--------------------------------------------------------------------
static self_type from_wavelength(double wl, double gamma = 1.0)
@ -617,10 +612,9 @@ typedef rgba8T<linear> rgba8;
typedef rgba8T<sRGB> srgba8;
//-------------------------------------------------------------rgba8_pre
inline rgba8 rgba8_pre(unsigned r, unsigned g, unsigned b,
unsigned a = rgba8::base_mask)
inline rgba8 rgba8_pre(unsigned r, unsigned g, unsigned b, unsigned a = rgba8::base_mask)
{
return rgba8(r,g,b,a).premultiply();
return rgba8(r, g, b, a).premultiply();
}
inline rgba8 rgba8_pre(const rgba8& c)
{
@ -628,7 +622,7 @@ inline rgba8 rgba8_pre(const rgba8& c)
}
inline rgba8 rgba8_pre(const rgba8& c, unsigned a)
{
return rgba8(c,a).premultiply();
return rgba8(c, a).premultiply();
}
inline rgba8 rgba8_pre(const rgba& c)
{
@ -636,12 +630,9 @@ inline rgba8 rgba8_pre(const rgba& c)
}
inline rgba8 rgba8_pre(const rgba& c, double a)
{
return rgba8(c,a).premultiply();
return rgba8(c, a).premultiply();
}
//-------------------------------------------------------------rgb8_packed
inline rgba8 rgb8_packed(unsigned v)
{
@ -674,19 +665,16 @@ 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
{
typedef int64 long_type;
enum base_scale_e {
base_shift = 16,
base_scale = 1 << base_shift,
base_mask = base_scale - 1,
base_mask = base_scale - 1,
base_MSB = 1 << (base_shift - 1)
};
typedef rgba16 self_type;
@ -700,105 +688,81 @@ struct rgba16
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(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 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)
: 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 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)
: 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 srgba8& c) :
r(sRGB_conv<value_type>::rgb_from_sRGB(c.r)),
g(sRGB_conv<value_type>::rgb_from_sRGB(c.g)),
b(sRGB_conv<value_type>::rgb_from_sRGB(c.b)),
a(sRGB_conv<value_type>::alpha_from_sRGB(c.a)) {}
rgba16(const srgba8& c)
: r(sRGB_conv<value_type>::rgb_from_sRGB(c.r))
, g(sRGB_conv<value_type>::rgb_from_sRGB(c.g))
, b(sRGB_conv<value_type>::rgb_from_sRGB(c.b))
, a(sRGB_conv<value_type>::alpha_from_sRGB(c.a))
{}
//--------------------------------------------------------------------
operator rgba() const
{
return rgba(
r / 65535.0,
g / 65535.0,
b / 65535.0,
a / 65535.0);
}
operator rgba() const { return rgba(r / 65535.0, g / 65535.0, b / 65535.0, a / 65535.0); }
//--------------------------------------------------------------------
operator rgba8() const
{
return rgba8(r >> 8, g >> 8, b >> 8, a >> 8);
}
operator rgba8() const { return rgba8(r >> 8, g >> 8, b >> 8, a >> 8); }
//--------------------------------------------------------------------
operator srgba8() const
{
// Return (non-premultiplied) sRGB values.
return srgba8(
sRGB_conv<value_type>::rgb_to_sRGB(r),
sRGB_conv<value_type>::rgb_to_sRGB(g),
sRGB_conv<value_type>::rgb_to_sRGB(b),
sRGB_conv<value_type>::alpha_to_sRGB(a));
return srgba8(sRGB_conv<value_type>::rgb_to_sRGB(r),
sRGB_conv<value_type>::rgb_to_sRGB(g),
sRGB_conv<value_type>::rgb_to_sRGB(b),
sRGB_conv<value_type>::alpha_to_sRGB(a));
}
//--------------------------------------------------------------------
static AGG_INLINE double to_double(value_type a)
{
return double(a) / base_mask;
}
static AGG_INLINE double to_double(value_type a) { return double(a) / base_mask; }
//--------------------------------------------------------------------
static AGG_INLINE value_type from_double(double a)
{
return value_type(uround(a * base_mask));
}
static AGG_INLINE value_type from_double(double a) { return value_type(uround(a * base_mask)); }
//--------------------------------------------------------------------
static AGG_INLINE value_type empty_value()
{
return 0;
}
static AGG_INLINE value_type empty_value() { return 0; }
//--------------------------------------------------------------------
static AGG_INLINE value_type full_value()
{
return base_mask;
}
static AGG_INLINE value_type full_value() { return base_mask; }
//--------------------------------------------------------------------
AGG_INLINE bool is_transparent() const
{
return a == 0;
}
AGG_INLINE bool is_transparent() const { return a == 0; }
//--------------------------------------------------------------------
AGG_INLINE bool is_opaque() const
{
return a == base_mask;
}
AGG_INLINE bool is_opaque() const { return a == base_mask; }
//--------------------------------------------------------------------
static AGG_INLINE value_type invert(value_type x)
{
return base_mask - x;
}
static AGG_INLINE value_type invert(value_type x) { return base_mask - x; }
//--------------------------------------------------------------------
// Fixed-point multiply, exact over int16u.
@ -819,7 +783,8 @@ struct rgba16
{
return base_mask;
}
else return value_type((a * base_mask + (b >> 1)) / b);
else
return value_type((a * base_mask + (b >> 1)) / b);
}
//--------------------------------------------------------------------
@ -839,23 +804,14 @@ struct rgba16
//--------------------------------------------------------------------
// Fixed-point multiply, almost exact over int16u.
// Specifically for multiplying a color component by a cover.
static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
{
return multiply(a, (b << 8) | b);
}
static AGG_INLINE value_type mult_cover(value_type a, cover_type b) { return multiply(a, (b << 8) | b); }
//--------------------------------------------------------------------
static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
{
return multiply((a << 8) | a, b) >> 8;
}
static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) { return multiply((a << 8) | a, b) >> 8; }
//--------------------------------------------------------------------
// Interpolate p to q by a, assuming q is premultiplied by a.
static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
{
return p + q - multiply(p, a);
}
static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a) { return p + q - multiply(p, a); }
//--------------------------------------------------------------------
// Interpolate p to q by a.
@ -882,17 +838,16 @@ struct rgba16
//--------------------------------------------------------------------
AGG_INLINE self_type& opacity(double a_)
{
if (a_ < 0) a = 0;
if (a_ > 1) a = 1;
if (a_ < 0)
a = 0;
if (a_ > 1)
a = 1;
a = value_type(uround(a_ * double(base_mask)));
return *this;
}
//--------------------------------------------------------------------
double opacity() const
{
return double(a) / double(base_mask);
}
double opacity() const { return double(a) / double(base_mask); }
//--------------------------------------------------------------------
AGG_INLINE self_type& premultiply()
@ -1014,7 +969,7 @@ struct rgba16
}
//--------------------------------------------------------------------
static self_type no_color() { return self_type(0,0,0,0); }
static self_type no_color() { return self_type(0, 0, 0, 0); }
//--------------------------------------------------------------------
static self_type from_wavelength(double wl, double gamma = 1.0)
@ -1023,7 +978,6 @@ struct rgba16
}
};
//------------------------------------------------------rgba16_gamma_dir
template<class GammaLUT>
rgba16 rgba16_gamma_dir(rgba16 c, const GammaLUT& gamma)
@ -1055,127 +1009,100 @@ struct rgba32
rgba32() {}
//--------------------------------------------------------------------
rgba32(value_type r_, value_type g_, value_type b_, value_type a_= 1) :
r(r_), g(g_), b(b_), a(a_) {}
rgba32(value_type r_, value_type g_, value_type b_, value_type a_ = 1)
: r(r_)
, g(g_)
, b(b_)
, a(a_)
{}
//--------------------------------------------------------------------
rgba32(const self_type& c, float a_) :
r(c.r), g(c.g), b(c.b), a(a_) {}
rgba32(const self_type& c, float a_)
: r(c.r)
, g(c.g)
, b(c.b)
, a(a_)
{}
//--------------------------------------------------------------------
rgba32(const rgba& c) :
r(value_type(c.r)), g(value_type(c.g)), b(value_type(c.b)), a(value_type(c.a)) {}
rgba32(const rgba& c)
: r(value_type(c.r))
, g(value_type(c.g))
, b(value_type(c.b))
, a(value_type(c.a))
{}
//--------------------------------------------------------------------
rgba32(const rgba8& c) :
r(value_type(c.r / 255.0)),
g(value_type(c.g / 255.0)),
b(value_type(c.b / 255.0)),
a(value_type(c.a / 255.0)) {}
rgba32(const rgba8& c)
: r(value_type(c.r / 255.0))
, g(value_type(c.g / 255.0))
, b(value_type(c.b / 255.0))
, a(value_type(c.a / 255.0))
{}
//--------------------------------------------------------------------
rgba32(const srgba8& c) :
r(sRGB_conv<value_type>::rgb_from_sRGB(c.r)),
g(sRGB_conv<value_type>::rgb_from_sRGB(c.g)),
b(sRGB_conv<value_type>::rgb_from_sRGB(c.b)),
a(sRGB_conv<value_type>::alpha_from_sRGB(c.a)) {}
rgba32(const srgba8& c)
: r(sRGB_conv<value_type>::rgb_from_sRGB(c.r))
, g(sRGB_conv<value_type>::rgb_from_sRGB(c.g))
, b(sRGB_conv<value_type>::rgb_from_sRGB(c.b))
, a(sRGB_conv<value_type>::alpha_from_sRGB(c.a))
{}
//--------------------------------------------------------------------
rgba32(const rgba16& c) :
r(value_type(c.r / 65535.0)),
g(value_type(c.g / 65535.0)),
b(value_type(c.b / 65535.0)),
a(value_type(c.a / 65535.0)) {}
rgba32(const rgba16& c)
: r(value_type(c.r / 65535.0))
, g(value_type(c.g / 65535.0))
, b(value_type(c.b / 65535.0))
, a(value_type(c.a / 65535.0))
{}
//--------------------------------------------------------------------
operator rgba() const
{
return rgba(r, g, b, a);
}
operator rgba() const { return rgba(r, g, b, a); }
//--------------------------------------------------------------------
operator rgba8() const
{
return rgba8(
uround(r * 255.0),
uround(g * 255.0),
uround(b * 255.0),
uround(a * 255.0));
}
operator rgba8() const { return rgba8(uround(r * 255.0), uround(g * 255.0), uround(b * 255.0), uround(a * 255.0)); }
//--------------------------------------------------------------------
operator srgba8() const
{
return srgba8(
sRGB_conv<value_type>::rgb_to_sRGB(r),
sRGB_conv<value_type>::rgb_to_sRGB(g),
sRGB_conv<value_type>::rgb_to_sRGB(b),
sRGB_conv<value_type>::alpha_to_sRGB(a));
return srgba8(sRGB_conv<value_type>::rgb_to_sRGB(r),
sRGB_conv<value_type>::rgb_to_sRGB(g),
sRGB_conv<value_type>::rgb_to_sRGB(b),
sRGB_conv<value_type>::alpha_to_sRGB(a));
}
//--------------------------------------------------------------------
operator rgba16() const
{
return rgba8(
uround(r * 65535.0),
uround(g * 65535.0),
uround(b * 65535.0),
uround(a * 65535.0));
return rgba8(uround(r * 65535.0), uround(g * 65535.0), uround(b * 65535.0), uround(a * 65535.0));
}
//--------------------------------------------------------------------
static AGG_INLINE double to_double(value_type a)
{
return a;
}
static AGG_INLINE double to_double(value_type a) { return a; }
//--------------------------------------------------------------------
static AGG_INLINE value_type from_double(double a)
{
return value_type(a);
}
static AGG_INLINE value_type from_double(double a) { return value_type(a); }
//--------------------------------------------------------------------
static AGG_INLINE value_type empty_value()
{
return 0;
}
static AGG_INLINE value_type empty_value() { return 0; }
//--------------------------------------------------------------------
static AGG_INLINE value_type full_value()
{
return 1;
}
static AGG_INLINE value_type full_value() { return 1; }
//--------------------------------------------------------------------
AGG_INLINE bool is_transparent() const
{
return a <= 0;
}
AGG_INLINE bool is_transparent() const { return a <= 0; }
//--------------------------------------------------------------------
AGG_INLINE bool is_opaque() const
{
return a >= 1;
}
AGG_INLINE bool is_opaque() const { return a >= 1; }
//--------------------------------------------------------------------
static AGG_INLINE value_type invert(value_type x)
{
return 1 - x;
}
static AGG_INLINE value_type invert(value_type x) { return 1 - x; }
//--------------------------------------------------------------------
static AGG_INLINE value_type multiply(value_type a, value_type b)
{
return value_type(a * b);
}
static AGG_INLINE value_type multiply(value_type a, value_type b) { return value_type(a * b); }
//--------------------------------------------------------------------
static AGG_INLINE value_type demultiply(value_type a, value_type b)
{
return (b == 0) ? 0 : value_type(a / b);
}
static AGG_INLINE value_type demultiply(value_type a, value_type b) { return (b == 0) ? 0 : value_type(a / b); }
//--------------------------------------------------------------------
template<typename T>
@ -1192,16 +1119,10 @@ struct rgba32
}
//--------------------------------------------------------------------
static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
{
return value_type(a * b / cover_mask);
}
static AGG_INLINE value_type mult_cover(value_type a, cover_type b) { return value_type(a * b / cover_mask); }
//--------------------------------------------------------------------
static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
{
return cover_type(uround(a * b));
}
static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) { return cover_type(uround(a * b)); }
//--------------------------------------------------------------------
// Interpolate p to q by a, assuming q is premultiplied by a.
@ -1238,17 +1159,17 @@ struct rgba32
//--------------------------------------------------------------------
AGG_INLINE self_type& opacity(double a_)
{
if (a_ < 0) a = 0;
else if (a_ > 1) a = 1;
else a = value_type(a_);
if (a_ < 0)
a = 0;
else if (a_ > 1)
a = 1;
else
a = value_type(a_);
return *this;
}
//--------------------------------------------------------------------
double opacity() const
{
return a;
}
double opacity() const { return a; }
//--------------------------------------------------------------------
AGG_INLINE self_type& premultiply()
@ -1324,10 +1245,14 @@ struct rgba32
b += mult_cover(c.b, cover);
a += mult_cover(c.a, cover);
}
if (a > 1) a = 1;
if (r > a) r = a;
if (g > a) g = a;
if (b > a) b = a;
if (a > 1)
a = 1;
if (r > a)
r = a;
if (g > a)
g = a;
if (b > a)
b = a;
}
//--------------------------------------------------------------------
@ -1349,7 +1274,7 @@ struct rgba32
}
//--------------------------------------------------------------------
static self_type no_color() { return self_type(0,0,0,0); }
static self_type no_color() { return self_type(0, 0, 0, 0); }
//--------------------------------------------------------------------
static self_type from_wavelength(double wl, double gamma = 1)
@ -1357,8 +1282,6 @@ struct rgba32
return self_type(rgba::from_wavelength(wl, gamma));
}
};
}
} // namespace agg
#endif

View file

@ -5,7 +5,7 @@
//---------------------------------------
// 1. Default basic types such as:
//
//
// AGG_INT8
// AGG_INT8U
// AGG_INT16
@ -15,7 +15,7 @@
// AGG_INT64
// AGG_INT64U
//
// Just replace this file with new defines if necessary.
// 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:
//
@ -23,22 +23,21 @@
// #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
// 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,
// 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
// 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.

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -18,106 +18,95 @@
#include "agg_basics.h"
namespace agg
namespace agg {
//------------------------------------------------------------null_markers
struct null_markers
{
//------------------------------------------------------------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; }
unsigned type() const { return 0; }
};
//------------------------------------------------------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)
{}
conv_adaptor_vcgen(conv_adaptor_vcgen<VertexSource, Generator, Markers>&&) = default;
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)
{
void remove_all() {}
void add_vertex(double, double, unsigned) {}
void prepare_src() {}
m_source->rewind(path_id);
m_status = initial;
}
void rewind(unsigned) {}
unsigned vertex(double*, double*) { return path_cmd_stop; }
unsigned type() const { return 0; }
};
unsigned vertex(double* x, double* y);
unsigned type() const { return m_source->type(); }
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>&);
//------------------------------------------------------conv_adaptor_vcgen
template<class VertexSource,
class Generator,
class Markers=null_markers> class conv_adaptor_vcgen
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)
{
enum status
switch (m_status)
{
initial,
accumulate,
generate
};
public:
explicit conv_adaptor_vcgen(VertexSource& source) :
m_source(&source),
m_status(initial)
{}
conv_adaptor_vcgen(conv_adaptor_vcgen<VertexSource, Generator, Markers> &&) = default;
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);
unsigned type() const { return m_source->type(); }
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;
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(;;)
for (;;)
{
cmd = m_source->vertex(x, y);
if(is_vertex(cmd))
if (is_vertex(cmd))
{
m_last_cmd = cmd;
if(is_move_to(cmd))
if (is_move_to(cmd))
{
m_start_x = *x;
m_start_y = *y;
@ -128,12 +117,12 @@ namespace agg
}
else
{
if(is_stop(cmd))
if (is_stop(cmd))
{
m_last_cmd = path_cmd_stop;
break;
}
if(is_end_poly(cmd))
if (is_end_poly(cmd))
{
m_generator.add_vertex(*x, *y, cmd);
break;
@ -145,18 +134,18 @@ namespace agg
case generate:
cmd = m_generator.vertex(x, y);
if(is_stop(cmd))
if (is_stop(cmd))
{
m_status = accumulate;
break;
}
done = true;
break;
}
}
return cmd;
}
return cmd;
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -18,143 +18,140 @@
#include "agg_basics.h"
namespace agg
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; }
//======================================================conv_adaptor_vpgen
template<class VertexSource, class VPGen> class conv_adaptor_vpgen
VPGen& vpgen() { return m_vpgen; }
const VPGen& vpgen() const { return m_vpgen; }
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
unsigned type() const { return m_source->type(); }
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 (;;)
{
public:
explicit conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {}
void attach(VertexSource& source) { m_source = &source; }
cmd = m_vpgen.vertex(x, y);
if (!is_stop(cmd))
break;
VPGen& vpgen() { return m_vpgen; }
const VPGen& vpgen() const { return m_vpgen; }
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
unsigned type() const { return m_source->type(); }
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(;;)
if (m_poly_flags && !m_vpgen.auto_unclose())
{
cmd = m_vpgen.vertex(x, y);
if(!is_stop(cmd)) break;
*x = 0.0;
*y = 0.0;
cmd = m_poly_flags;
m_poly_flags = 0;
break;
}
if(m_poly_flags && !m_vpgen.auto_unclose())
if (m_vertices < 0)
{
if (m_vertices < -1)
{
*x = 0.0;
*y = 0.0;
cmd = m_poly_flags;
m_poly_flags = 0;
break;
m_vertices = 0;
return path_cmd_stop;
}
m_vpgen.move_to(m_start_x, m_start_y);
m_vertices = 1;
continue;
}
if(m_vertices < 0)
double tx, ty;
cmd = m_source->vertex(&tx, &ty);
if (is_vertex(cmd))
{
if (is_move_to(cmd))
{
if(m_vertices < -1)
if (m_vpgen.auto_close() && m_vertices > 2)
{
m_vertices = 0;
return path_cmd_stop;
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(m_start_x, m_start_y);
m_vpgen.move_to(tx, ty);
m_start_x = tx;
m_start_y = ty;
m_vertices = 1;
continue;
}
double tx, ty;
cmd = m_source->vertex(&tx, &ty);
if(is_vertex(cmd))
else
{
if(is_move_to(cmd))
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_vertices > 2)
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_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;
m_vertices = 0;
}
}
else
{
if(is_end_poly(cmd))
// path_cmd_stop
if (m_vpgen.auto_close() && m_vertices > 2)
{
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;
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;
}
return cmd;
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -19,30 +19,26 @@
#include "agg_vcgen_bspline.h"
#include "agg_conv_adaptor_vcgen.h"
namespace agg {
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
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)
{}
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(); }
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>&);
};
}
private:
conv_bspline(const conv_bspline<VertexSource>&);
const conv_bspline<VertexSource>& operator=(const conv_bspline<VertexSource>&);
};
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -14,12 +14,12 @@
//----------------------------------------------------------------------------
//
// Polygon clipping converter
// There an optimized Liang-Basky algorithm is used.
// 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
// 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,
// 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.
//
//----------------------------------------------------------------------------
@ -30,35 +30,31 @@
#include "agg_conv_adaptor_vpgen.h"
#include "agg_vpgen_clip_polygon.h"
namespace agg
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
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)
{}
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); }
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(); }
unsigned type() const { return base_type::type(); }
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(); }
unsigned type() const { return base_type::type(); }
private:
conv_clip_polygon(const conv_clip_polygon<VertexSource>&);
const conv_clip_polygon<VertexSource>& operator=(const conv_clip_polygon<VertexSource>&);
};
private:
conv_clip_polygon(const conv_clip_polygon<VertexSource>&);
const conv_clip_polygon<VertexSource>&
operator = (const conv_clip_polygon<VertexSource>&);
};
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -14,12 +14,12 @@
//----------------------------------------------------------------------------
//
// polyline clipping converter
// There an optimized Liang-Basky algorithm is used.
// 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
// 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,
// 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.
//
//----------------------------------------------------------------------------
@ -30,35 +30,31 @@
#include "agg_conv_adaptor_vpgen.h"
#include "agg_vpgen_clip_polyline.h"
namespace agg
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
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)
{}
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); }
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(); }
unsigned type() const { return base_type::type(); }
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(); }
unsigned type() const { return base_type::type(); }
private:
conv_clip_polyline(const conv_clip_polyline<VertexSource>&);
const conv_clip_polyline<VertexSource>& operator=(const conv_clip_polyline<VertexSource>&);
};
private:
conv_clip_polyline(const conv_clip_polyline<VertexSource>&);
const conv_clip_polyline<VertexSource>&
operator = (const conv_clip_polyline<VertexSource>&);
};
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -18,108 +18,105 @@
#include "agg_basics.h"
namespace agg
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; }
//======================================================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);
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>&);
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;
}
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;
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -18,56 +18,57 @@
#include "agg_basics.h"
namespace agg
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
{
//=============================================================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)
{
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; }
m_source1->rewind(path_id);
m_source2->rewind(0);
m_status = 0;
}
void rewind(unsigned path_id)
{
m_source1->rewind(path_id);
m_source2->rewind(0);
m_status = 0;
}
unsigned vertex(double* x, double* y)
unsigned vertex(double* x, double* y)
{
unsigned cmd;
if (m_status == 0)
{
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;
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;
};
}
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;
};
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -23,43 +23,40 @@
#include "agg_vcgen_contour.h"
#include "agg_conv_adaptor_vcgen.h"
namespace agg
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
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)
{}
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); }
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(); }
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>&);
};
private:
conv_contour(const conv_contour<VertexSource>&);
const conv_contour<VertexSource>&
operator = (const conv_contour<VertexSource>&);
};
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -23,157 +23,140 @@
#include "agg_basics.h"
#include "agg_curves.h"
namespace agg
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)
{}
//---------------------------------------------------------------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
conv_curve(self_type&&) = default;
void attach(VertexSource& source) { m_source = &source; }
void approximation_method(curve_approximation_method_e v)
{
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) {}
conv_curve(self_type &&) = default;
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();
m_curve3.approximation_method(v);
m_curve4.approximation_method(v);
}
curve_approximation_method_e approximation_method() const { return m_curve4.approximation_method(); }
//------------------------------------------------------------------------
template<class VertexSource, class Curve3, class Curve4>
unsigned conv_curve<VertexSource, Curve3, Curve4>::vertex(double* x, double* y)
void approximation_scale(double s)
{
if(!is_stop(m_curve3.vertex(x, y)))
{
m_last_x = *x;
m_last_y = *y;
return path_cmd_line_to;
}
m_curve3.approximation_scale(s);
m_curve4.approximation_scale(s);
}
if(!is_stop(m_curve4.vertex(x, y)))
{
m_last_x = *x;
m_last_y = *y;
return path_cmd_line_to;
}
double approximation_scale() const { return m_curve4.approximation_scale(); }
double ct2_x=0;
double ct2_y=0;
double end_x=0;
double end_y=0;
void angle_tolerance(double v)
{
m_curve3.angle_tolerance(v);
m_curve4.angle_tolerance(v);
}
unsigned cmd = m_source->vertex(x, y);
switch(cmd)
{
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 = 0;
double ct2_y = 0;
double end_x = 0;
double end_y = 0;
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.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
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;
@ -181,24 +164,18 @@ namespace agg
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.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
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;
}
m_last_x = *x;
m_last_y = *y;
return cmd;
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -23,46 +23,33 @@
#include "agg_vcgen_dash.h"
#include "agg_conv_adaptor_vcgen.h"
namespace agg
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
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)
{}
conv_dash(VertexSource& vs) :
conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers>(vs)
{
}
void remove_all_dashes() { base_type::generator().remove_all_dashes(); }
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 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 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(); }
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>&);
};
private:
conv_dash(const conv_dash<VertexSource, Markers>&);
const conv_dash<VertexSource, Markers>&
operator = (const conv_dash<VertexSource, Markers>&);
};
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -13,7 +13,7 @@
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// General Polygon Clipper based on the GPC library by Alan Murta
// 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/
@ -28,405 +28,353 @@
#include "agg_basics.h"
#include "agg_array.h"
extern "C"
{
#include "gpc.h"
extern "C"
{
#include "gpc.h"
}
namespace agg
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 gpc_op_e
enum status { status_move_to, status_line_to, status_stop };
struct contour_header_type
{
gpc_or,
gpc_and,
gpc_xor,
gpc_a_minus_b,
gpc_b_minus_a
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;
//================================================================conv_gpc
template<class VSA, class VSB> class conv_gpc
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)
{
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_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; }
//------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_gpc<VSA, VSB>::free_gpc_data()
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)
{
free_polygon(m_poly_a);
free_polygon(m_poly_b);
free_result();
}
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();
//------------------------------------------------------------------------
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())
while (!is_stop(cmd = src.vertex(&x, &y)))
{
if(m_vertex_accumulator.size() > 2)
if (is_vertex(cmd))
{
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++)
if (is_move_to(cmd))
{
const gpc_vertex& s = m_vertex_accumulator[i];
d->x = s.x;
d->y = s.y;
++d;
if (line_to)
{
end_contour(orientation);
orientation = 0;
}
start_contour();
start_x = x;
start_y = y;
}
add_vertex(x, y);
line_to = true;
}
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))
if (is_end_poly(cmd))
{
m_status = status_line_to;
return path_cmd_move_to;
orientation = get_orientation(cmd);
if (line_to && is_closed(cmd))
{
add_vertex(start_x, start_y);
}
}
m_status = status_stop;
return path_cmd_end_poly | path_flags_close;
}
}
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
{
if(next_vertex(x, y))
{
return path_cmd_line_to;
}
else
{
m_status = status_move_to;
}
return path_cmd_end_poly | path_flags_close;
m_vertex_accumulator.remove_last();
}
return path_cmd_stop;
}
}
//------------------------------------------------------------------------
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;
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -22,82 +22,70 @@
#include "agg_basics.h"
#include "agg_trans_affine.h"
namespace agg
namespace agg {
//-------------------------------------------------------------conv_marker
template<class MarkerLocator, class MarkerShapes>
class conv_marker
{
//-------------------------------------------------------------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))
{
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
switch (m_status)
{
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)
if (m_num_markers == 0)
{
cmd = path_cmd_stop;
break;
cmd = path_cmd_stop;
break;
}
m_marker_locator->rewind(m_marker);
++m_marker;
@ -105,12 +93,12 @@ namespace agg
m_status = markers;
case markers:
if(is_stop(m_marker_locator->vertex(&x1, &y1)))
if (is_stop(m_marker_locator->vertex(&x1, &y1)))
{
m_status = initial;
break;
}
if(is_stop(m_marker_locator->vertex(&x2, &y2)))
if (is_stop(m_marker_locator->vertex(&x2, &y2)))
{
m_status = initial;
break;
@ -124,7 +112,7 @@ namespace agg
case polygon:
cmd = m_marker_shapes->vertex(x, y);
if(is_stop(cmd))
if (is_stop(cmd))
{
cmd = path_cmd_move_to;
m_status = markers;
@ -136,13 +124,11 @@ namespace agg
case stop:
cmd = path_cmd_stop;
break;
}
}
return cmd;
}
return cmd;
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -20,32 +20,27 @@
#include "agg_conv_adaptor_vcgen.h"
#include "agg_vcgen_vertex_sequence.h"
namespace agg
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
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)
{}
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(); }
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>&);
};
private:
conv_marker_adaptor(const conv_marker_adaptor<VertexSource, Markers>&);
const conv_marker_adaptor<VertexSource, Markers>&
operator = (const conv_marker_adaptor<VertexSource, Markers>&);
};
}
} // namespace agg
#endif

View file

@ -22,59 +22,53 @@
#include "agg_array.h"
#include "clipper.hpp"
namespace agg
{
namespace agg {
template<class VSA> class conv_offset
template<class VSA>
class conv_offset
{
enum status { status_move_to, status_line_to, status_stop };
typedef VSA source_a_type;
typedef conv_offset<source_a_type> self_type;
private:
source_a_type* m_src_a;
private:
source_a_type* m_src_a;
double m_offset;
status m_status;
int m_vertex;
int m_contour;
int m_scaling_factor;
pod_bvector<ClipperLib::IntPoint, 8> m_vertex_accumulator;
ClipperLib::Paths m_poly_a;
ClipperLib::Paths m_result;
ClipperLib::Paths m_poly_a;
ClipperLib::Paths m_result;
ClipperLib::ClipperOffset m_clipper_offset;
int Round(double val)
{
if ((val < 0)) return (int)(val - 0.5); else return (int)(val + 0.5);
if ((val < 0))
return (int)(val - 0.5);
else
return (int)(val + 0.5);
}
public:
conv_offset(source_a_type &a, double offset = 0.0,
int scaling_factor = 0)
: m_src_a(&a),
m_offset(offset),
m_status(status_move_to),
m_vertex(-1),
m_contour(-1)
public:
conv_offset(source_a_type& a, double offset = 0.0, int scaling_factor = 0)
: m_src_a(&a)
, m_offset(offset)
, m_status(status_move_to)
, m_vertex(-1)
, m_contour(-1)
{
m_scaling_factor = std::max(std::min(scaling_factor, 6),0);
m_scaling_factor = std::max(std::min(scaling_factor, 6), 0);
m_scaling_factor = Round(std::pow((double)10, m_scaling_factor));
}
~conv_offset()
{
}
~conv_offset() {}
void set_offset(double offset) { m_offset = offset;}
unsigned type() const
{
return static_cast<unsigned>(m_src_a->type());
}
void set_offset(double offset) { m_offset = offset; }
unsigned type() const { return static_cast<unsigned>(m_src_a->type()); }
double get_offset() const
{
return m_offset;
}
double get_offset() const { return m_offset; }
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
@ -82,13 +76,17 @@ public:
bool next_contour();
bool next_vertex(double* x, double* y);
void start_extracting();
void add_vertex_(double &x, double &y);
void end_contour(ClipperLib::Paths &p);
void add_vertex_(double& x, double& y);
void end_contour(ClipperLib::Paths& p);
template<class VS> void add(VS &src, ClipperLib::Paths &p)
template<class VS>
void add(VS& src, ClipperLib::Paths& p)
{
unsigned cmd;
double x; double y; double start_x; double start_y;
double x;
double y;
double start_x;
double start_y;
bool starting_first_line;
start_x = 0.0;
@ -96,26 +94,27 @@ public:
starting_first_line = true;
p.resize(0);
cmd = src->vertex( &x , &y );
while(!is_stop(cmd))
cmd = src->vertex(&x, &y);
while (!is_stop(cmd))
{
if(is_vertex(cmd))
if (is_vertex(cmd))
{
if(is_move_to(cmd))
if (is_move_to(cmd))
{
if(!starting_first_line ) end_contour(p);
if (!starting_first_line)
end_contour(p);
start_x = x;
start_y = y;
}
add_vertex_( x, y );
add_vertex_(x, y);
starting_first_line = false;
}
else if(is_end_poly(cmd))
else if (is_end_poly(cmd))
{
if(!starting_first_line && is_closed(cmd))
add_vertex_( start_x, start_y );
if (!starting_first_line && is_closed(cmd))
add_vertex_(start_x, start_y);
}
cmd = src->vertex( &x, &y );
cmd = src->vertex(&x, &y);
}
end_contour(p);
}
@ -135,42 +134,43 @@ void conv_offset<VSA>::start_extracting()
template<class VSA>
void conv_offset<VSA>::rewind(unsigned path_id)
{
m_src_a->rewind( path_id );
//m_src_b->rewind( path_id );
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 );
add(m_src_a, m_poly_a);
// add( m_src_b , m_poly_b );
m_result.resize(0);
m_clipper_offset.Clear();
m_clipper_offset.AddPaths(m_poly_a,ClipperLib::jtMiter, ClipperLib::etOpenButt);//ClosedLine);//Polygon);
m_clipper_offset.AddPaths(m_poly_a, ClipperLib::jtMiter, ClipperLib::etOpenButt); // ClosedLine);//Polygon);
m_clipper_offset.Execute(m_result, m_offset * m_scaling_factor);
start_extracting();
}
//------------------------------------------------------------------------------
template<class VSA>
void conv_offset<VSA>::end_contour( ClipperLib::Paths &p)
void conv_offset<VSA>::end_contour(ClipperLib::Paths& p)
{
unsigned i, len;
if( m_vertex_accumulator.size() < 3 ) return;
if (m_vertex_accumulator.size() < 3)
return;
len = p.size();
p.resize(len+1);
p.resize(len + 1);
p[len].resize(m_vertex_accumulator.size());
for( i = 0 ; i < m_vertex_accumulator.size() ; i++ )
for (i = 0; i < m_vertex_accumulator.size(); i++)
p[len][i] = m_vertex_accumulator[i];
m_vertex_accumulator.remove_all();
}
//------------------------------------------------------------------------------
template<class VSA>
void conv_offset<VSA>::add_vertex_(double &x, double &y)
void conv_offset<VSA>::add_vertex_(double& x, double& y)
{
ClipperLib::IntPoint v;
v.X = Round(x * m_scaling_factor);
v.Y = Round(y * m_scaling_factor);
m_vertex_accumulator.add( v );
m_vertex_accumulator.add(v);
}
//------------------------------------------------------------------------------
@ -178,33 +178,35 @@ template<class VSA>
bool conv_offset<VSA>::next_contour()
{
m_contour++;
if(m_contour >= (int)m_result.size()) return false;
m_vertex =-1;
if (m_contour >= (int)m_result.size())
return false;
m_vertex = -1;
return true;
}
//------------------------------------------------------------------------------
template<class VSA>
bool conv_offset<VSA>::next_vertex(double *x, double *y)
bool conv_offset<VSA>::next_vertex(double* x, double* y)
{
m_vertex++;
if(m_vertex >= (int)m_result[m_contour].size()) return false;
*x = (double)m_result[ m_contour ][ m_vertex ].X / m_scaling_factor;
*y = (double)m_result[ m_contour ][ m_vertex ].Y / m_scaling_factor;
if (m_vertex >= (int)m_result[m_contour].size())
return false;
*x = (double)m_result[m_contour][m_vertex].X / m_scaling_factor;
*y = (double)m_result[m_contour][m_vertex].Y / m_scaling_factor;
return true;
}
//------------------------------------------------------------------------------
template<class VSA>
unsigned conv_offset<VSA>::vertex(double *x, double *y)
unsigned conv_offset<VSA>::vertex(double* x, double* y)
{
if( m_status == status_move_to )
if (m_status == status_move_to)
{
if( next_contour() )
if (next_contour())
{
if( next_vertex( x, y ) )
if (next_vertex(x, y))
{
m_status =status_line_to;
m_status = status_line_to;
return path_cmd_move_to;
}
else
@ -218,7 +220,7 @@ unsigned conv_offset<VSA>::vertex(double *x, double *y)
}
else
{
if( next_vertex( x, y ) )
if (next_vertex(x, y))
{
return path_cmd_line_to;
}
@ -231,6 +233,5 @@ unsigned conv_offset<VSA>::vertex(double *x, double *y)
}
//------------------------------------------------------------------------------
} //namespace agg
#endif //AGG_CONV_OFFSET_INCLUDED
} // namespace agg
#endif // AGG_CONV_OFFSET_INCLUDED

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -20,29 +20,26 @@
#include "agg_conv_adaptor_vpgen.h"
#include "agg_vpgen_segmentator.h"
namespace agg
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
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)
{}
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(); }
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>&);
};
private:
conv_segmentator(const conv_segmentator<VertexSource>&);
const conv_segmentator<VertexSource>&
operator = (const conv_segmentator<VertexSource>&);
};
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -20,31 +20,27 @@
#include "agg_conv_adaptor_vcgen.h"
#include "agg_vcgen_vertex_sequence.h"
namespace agg
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
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)
{}
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(); }
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>&);
};
private:
conv_shorten_path(const conv_shorten_path<VertexSource>&);
const conv_shorten_path<VertexSource>&
operator = (const conv_shorten_path<VertexSource>&);
};
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -24,70 +24,62 @@
#include "agg_conv_adaptor_vcgen.h"
#include "agg_conv_curve.h"
namespace agg {
namespace agg
//-------------------------------------------------------conv_smooth
template<class VertexSource, class VertexGenerator>
struct conv_smooth : public conv_adaptor_vcgen<VertexSource, VertexGenerator>
{
typedef conv_adaptor_vcgen<VertexSource, VertexGenerator> base_type;
//-------------------------------------------------------conv_smooth
template<class VertexSource, class VertexGenerator>
struct conv_smooth :
public conv_adaptor_vcgen<VertexSource, VertexGenerator>
conv_smooth(VertexSource& vs)
: conv_adaptor_vcgen<VertexSource, VertexGenerator>(vs)
{}
conv_smooth(conv_smooth<VertexSource, VertexGenerator>&&) = default;
conv_smooth(const conv_smooth<VertexSource, VertexGenerator>&) = delete;
const conv_smooth<VertexSource, VertexGenerator>&
operator=(const conv_smooth<VertexSource, VertexGenerator>&) = delete;
void smooth_value(double v) { base_type::generator().smooth_value(v); }
double smooth_value() const { return base_type::generator().smooth_value(); }
unsigned type() const { return base_type::type(); }
};
template<class VertexSource>
using conv_smooth_poly1 = conv_smooth<VertexSource, vcgen_smooth_poly1>;
//-------------------------------------------------conv_smooth_curve
template<class VertexSource, class VertexGenerator>
struct conv_smooth_curve : public conv_curve<conv_smooth<VertexSource, VertexGenerator>>
{
conv_smooth_curve(VertexSource& vs)
: conv_curve<conv_smooth<VertexSource, VertexGenerator>>(m_smooth)
, m_smooth(vs)
{}
conv_smooth_curve(conv_smooth_curve<VertexSource, VertexGenerator>&& rhs)
: conv_curve<conv_smooth<VertexSource, VertexGenerator>>(std::move(rhs))
, m_smooth(std::move(rhs.m_smooth))
{
typedef conv_adaptor_vcgen<VertexSource, VertexGenerator> base_type;
this->attach(m_smooth);
}
conv_smooth(VertexSource& vs) :
conv_adaptor_vcgen<VertexSource, VertexGenerator>(vs)
{
}
conv_smooth_curve(const conv_smooth_curve<VertexSource, VertexGenerator>&) = delete;
const conv_smooth_curve<VertexSource, VertexGenerator>&
operator=(const conv_smooth_curve<VertexSource, VertexGenerator>&) = delete;
conv_smooth(conv_smooth<VertexSource, VertexGenerator> &&) = default;
void smooth_value(double v) { m_smooth.generator().smooth_value(v); }
double smooth_value() const { return m_smooth.generator().smooth_value(); }
unsigned type() const { return m_smooth.type(); }
conv_smooth(const conv_smooth<VertexSource, VertexGenerator>&) = delete;
const conv_smooth<VertexSource, VertexGenerator>&
operator = (const conv_smooth<VertexSource, VertexGenerator>&) = delete;
void smooth_value(double v) { base_type::generator().smooth_value(v); }
double smooth_value() const { return base_type::generator().smooth_value(); }
unsigned type() const { return base_type::type(); }
};
template<class VertexSource>
using conv_smooth_poly1 = conv_smooth<VertexSource, vcgen_smooth_poly1>;
//-------------------------------------------------conv_smooth_curve
template<class VertexSource, class VertexGenerator>
struct conv_smooth_curve :
public conv_curve<conv_smooth<VertexSource, VertexGenerator>>
{
conv_smooth_curve(VertexSource& vs) :
conv_curve<conv_smooth<VertexSource, VertexGenerator>>(m_smooth),
m_smooth(vs)
{
}
conv_smooth_curve(conv_smooth_curve<VertexSource, VertexGenerator> && rhs) :
conv_curve<conv_smooth<VertexSource, VertexGenerator>>(std::move(rhs)),
m_smooth(std::move(rhs.m_smooth))
{
this->attach(m_smooth);
}
conv_smooth_curve(const conv_smooth_curve<VertexSource, VertexGenerator>&) = delete;
const conv_smooth_curve<VertexSource, VertexGenerator>&
operator = (const conv_smooth_curve<VertexSource, VertexGenerator>&) = delete;
void smooth_value(double v) { m_smooth.generator().smooth_value(v); }
double smooth_value() const { return m_smooth.generator().smooth_value(); }
unsigned type() const { return m_smooth.type(); }
private:
conv_smooth<VertexSource, VertexGenerator> m_smooth;
};
template<class VertexSource>
using conv_smooth_poly1_curve = conv_smooth_curve<VertexSource, vcgen_smooth_poly1>;
}
private:
conv_smooth<VertexSource, VertexGenerator> m_smooth;
};
template<class VertexSource>
using conv_smooth_poly1_curve = conv_smooth_curve<VertexSource, vcgen_smooth_poly1>;
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -23,51 +23,46 @@
#include "agg_vcgen_stroke.h"
#include "agg_conv_adaptor_vcgen.h"
namespace agg
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
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)
{}
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); }
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(); }
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); }
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(); }
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(); }
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>&);
};
private:
conv_stroke(const conv_stroke<VertexSource, Markers>&);
const conv_stroke<VertexSource, Markers>&
operator = (const conv_stroke<VertexSource, Markers>&);
};
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -22,50 +22,44 @@
#include "agg_basics.h"
#include "agg_trans_affine.h"
namespace agg
namespace agg {
//----------------------------------------------------------conv_transform
template<class VertexSource, class Transformer = trans_affine>
class conv_transform
{
public:
conv_transform(VertexSource& source, Transformer& tr)
: m_source(&source)
, m_trans(&tr)
{}
//----------------------------------------------------------conv_transform
template<class VertexSource, class Transformer=trans_affine> class conv_transform
void attach(VertexSource& source) { m_source = &source; }
void rewind(unsigned path_id) { m_source->rewind(path_id); }
unsigned vertex(double* x, double* y)
{
public:
conv_transform(VertexSource& source, 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))
{
unsigned cmd = m_source->vertex(x, y);
if(is_vertex(cmd))
{
m_trans->transform(x, y);
}
return cmd;
m_trans->transform(x, y);
}
return cmd;
}
void transformer(Transformer& tr)
{
m_trans = &tr;
}
void transformer(Transformer& tr) { m_trans = &tr; }
unsigned type() const { return m_source->type(); }
unsigned type() const { return m_source->type(); }
private:
conv_transform(const conv_transform<VertexSource>&);
const conv_transform<VertexSource>&
operator = (const conv_transform<VertexSource>&);
private:
conv_transform(const conv_transform<VertexSource>&);
const conv_transform<VertexSource>& operator=(const conv_transform<VertexSource>&);
VertexSource* m_source;
const Transformer* m_trans;
};
VertexSource* m_source;
const Transformer* m_trans;
};
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -18,35 +18,34 @@
#include "agg_basics.h"
namespace agg
namespace agg {
//====================================================conv_unclose_polygon
template<class VertexSource>
class conv_unclose_polygon
{
//====================================================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)
{
public:
explicit conv_unclose_polygon(VertexSource& vs) : m_source(&vs) {}
void attach(VertexSource& source) { m_source = &source; }
unsigned cmd = m_source->vertex(x, y);
if (is_end_poly(cmd))
cmd &= ~path_flags_close;
return cmd;
}
void rewind(unsigned path_id)
{
m_source->rewind(path_id);
}
private:
conv_unclose_polygon(const conv_unclose_polygon<VertexSource>&);
const conv_unclose_polygon<VertexSource>& operator=(const conv_unclose_polygon<VertexSource>&);
unsigned vertex(double* x, double* y)
{
unsigned cmd = m_source->vertex(x, y);
if(is_end_poly(cmd)) cmd &= ~path_flags_close;
return cmd;
}
VertexSource* m_source;
};
private:
conv_unclose_polygon(const conv_unclose_polygon<VertexSource>&);
const conv_unclose_polygon<VertexSource>&
operator = (const conv_unclose_polygon<VertexSource>&);
VertexSource* m_source;
};
}
} // namespace agg
#endif

File diff suppressed because it is too large Load diff

View file

@ -23,268 +23,229 @@
#include <cstdlib>
#include "agg_basics.h"
namespace agg
namespace agg {
//===================================================dda_line_interpolator
template<int FractionShift, int YShift = 0>
class dda_line_interpolator
{
static constexpr int factor = 2 << (FractionShift - 1);
//===================================================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) * factor) / static_cast<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)
{
static constexpr int factor = 2 << (FractionShift - 1);
public:
//--------------------------------------------------------------------
dda_line_interpolator() {}
//--------------------------------------------------------------------
dda_line_interpolator(int y1, int y2, unsigned count) :
m_y(y1),
m_inc(((y2 - y1) * factor) / static_cast<int>(count)),
m_dy(0)
if (m_mod <= 0)
{
m_mod += count;
m_rem += count;
m_lft--;
}
m_mod -= count;
}
//--------------------------------------------------------------------
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
//-------------------------------------------- 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)
{
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)
{
if(m_mod <= 0)
{
m_mod += count;
m_rem += count;
m_lft--;
}
m_mod -= count;
m_mod += count;
m_rem += count;
m_lft--;
}
}
//-------------------------------------------- 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)
//-------------------------------------------- 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)
{
if(m_mod <= 0)
{
m_mod += count;
m_rem += count;
m_lft--;
}
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 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()
//--------------------------------------------------------------------
void operator++()
{
m_mod += m_rem;
m_y += m_lft;
if (m_mod > 0)
{
m_mod -= m_cnt;
m_y++;
}
}
//--------------------------------------------------------------------
void adjust_backward()
//--------------------------------------------------------------------
void operator--()
{
if (m_mod <= m_rem)
{
m_mod += m_cnt;
m_y--;
}
m_mod -= m_rem;
m_y -= m_lft;
}
//--------------------------------------------------------------------
int mod() const { return m_mod; }
int rem() const { return m_rem; }
int lft() const { return m_lft; }
//--------------------------------------------------------------------
void adjust_forward() { m_mod -= m_cnt; }
//--------------------------------------------------------------------
int y() const { return m_y; }
//--------------------------------------------------------------------
void adjust_backward() { m_mod += m_cnt; }
private:
int m_cnt;
int m_lft;
int m_rem;
int m_mod;
int m_y;
//--------------------------------------------------------------------
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(std::abs(m_x2_lr - m_x1_lr) < std::abs(m_y2_lr - m_y1_lr))
, m_len(m_ver ? std::abs(m_y2_lr - m_y1_lr) : std::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; }
//---------------------------------------------line_bresenham_interpolator
class line_bresenham_interpolator
//--------------------------------------------------------------------
void hstep()
{
public:
enum subpixel_scale_e
{
subpixel_shift = 8,
subpixel_scale = 1 << subpixel_shift,
subpixel_mask = subpixel_scale - 1
};
++m_interpolator;
m_x1_lr += m_inc;
}
//--------------------------------------------------------------------
static int line_lr(int v) { return v >> subpixel_shift; }
//--------------------------------------------------------------------
void vstep()
{
++m_interpolator;
m_y1_lr += m_inc;
}
//--------------------------------------------------------------------
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(std::abs(m_x2_lr - m_x1_lr) < std::abs(m_y2_lr - m_y1_lr)),
m_len(m_ver ? std::abs(m_y2_lr - m_y1_lr) :
std::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;
};
}
//--------------------------------------------------------------------
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;
};
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -23,102 +23,111 @@
#include "agg_basics.h"
#include <cmath>
namespace agg
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
class ellipse
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)
{
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);
unsigned num_steps() { return m_num; }
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();
if (m_num == 0)
calc_num_steps();
}
//------------------------------------------------------------------------
inline void ellipse::approximation_scale(double scale)
{
m_scale = scale;
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);
unsigned num_steps() { return m_num; }
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::calc_num_steps()
{
double ra = (std::fabs(m_rx) + std::fabs(m_ry)) / 2;
double da = std::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 + std::cos(angle) * m_rx;
*y = m_y + std::sin(angle) * m_ry;
m_step++;
return ((m_step == 1) ? path_cmd_move_to : path_cmd_line_to);
}
}
//------------------------------------------------------------------------
inline void ellipse::approximation_scale(double scale)
{
m_scale = scale;
calc_num_steps();
}
//------------------------------------------------------------------------
inline void ellipse::calc_num_steps()
{
double ra = (std::fabs(m_rx) + std::fabs(m_ry)) / 2;
double da = std::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 + std::cos(angle) * m_rx;
*y = m_y + std::sin(angle) * m_ry;
m_step++;
return ((m_step == 1) ? path_cmd_move_to : path_cmd_line_to);
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -20,94 +20,92 @@
#ifndef AGG_ELLIPSE_BRESENHAM_INCLUDED
#define AGG_ELLIPSE_BRESENHAM_INCLUDED
#include "agg_basics.h"
namespace agg {
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)
{}
//------------------------------------------ellipse_bresenham_interpolator
class ellipse_bresenham_interpolator
int dx() const { return m_dx; }
int dy() const { return m_dy; }
void operator++()
{
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; }
int mx, my, mxy, min_m;
int fx, fy, fxy;
void operator++ ()
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)
{
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;
min_m = my;
flag = false;
}
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;
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;
};
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -18,42 +18,41 @@
#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[];
}
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[];
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -19,307 +19,265 @@
#include <cstring>
#include "agg_array.h"
namespace agg
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;
};
//---------------------------------------------------------glyph_data_type
enum glyph_data_type
//--------------------------------------------------------------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)
{
glyph_data_invalid = 0,
glyph_data_mono = 1,
glyph_data_gray8 = 2,
glyph_data_outline = 3
};
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; }
//-------------------------------------------------------------glyph_cache
struct glyph_cache
//--------------------------------------------------------------------
const glyph_cache* find_glyph(unsigned glyph_code) const
{
unsigned glyph_index;
int8u* data;
unsigned data_size;
glyph_data_type data_type;
rect_i bounds;
double advance_x;
double advance_y;
};
unsigned msb = (glyph_code >> 8) & 0xFF;
if (m_glyphs[msb])
{
return m_glyphs[msb][glyph_code & 0xFF];
}
return 0;
}
//--------------------------------------------------------------font_cache
class font_cache
//--------------------------------------------------------------------
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)
{
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)
unsigned msb = (glyph_code >> 8) & 0xFF;
if (m_glyphs[msb] == 0)
{
m_font_signature = (char*)m_allocator.allocate(strlen(font_signature) + 1);
strcpy(m_font_signature, font_signature);
memset(m_glyphs, 0, sizeof(m_glyphs));
m_glyphs[msb] = (glyph_cache**)m_allocator.allocate(sizeof(glyph_cache*) * 256, sizeof(glyph_cache*));
memset(m_glyphs[msb], 0, sizeof(glyph_cache*) * 256);
}
//--------------------------------------------------------------------
bool font_is(const char* font_signature) const
{
return strcmp(font_signature, m_font_signature) == 0;
}
unsigned lsb = glyph_code & 0xFF;
if (m_glyphs[msb][lsb])
return 0; // Already exists, do not overwrite
//--------------------------------------------------------------------
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* glyph = (glyph_cache*)m_allocator.allocate(sizeof(glyph_cache), sizeof(double));
//--------------------------------------------------------------------
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);
}
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;
}
unsigned lsb = glyph_code & 0xFF;
if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite
private:
block_allocator m_allocator;
glyph_cache** m_glyphs[256];
char* m_font_signature;
};
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
//---------------------------------------------------------font_cache_pool
class font_cache_pool
{
public:
//--------------------------------------------------------------------
~font_cache_pool()
{
public:
//--------------------------------------------------------------------
~font_cache_pool()
unsigned i;
for (i = 0; i < m_num_fonts; ++i)
{
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);
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)
{}
//--------------------------------------------------------------------
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
//--------------------------------------------------------------------
void font(const char* font_signature, bool reset_cache = false)
{
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()
int idx = find_font(font_signature);
if (idx >= 0)
{
m_prev_glyph = m_last_glyph = 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];
}
//--------------------------------------------------------------------
const glyph_cache* glyph(unsigned glyph_code)
else
{
synchronize();
const glyph_cache* gl = m_fonts.find_glyph(glyph_code);
if(gl)
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;
return m_last_glyph = gl;
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;
}
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;
}
return 0;
}
//--------------------------------------------------------------------
void init_embedded_adaptors(const glyph_cache* gl,
double x, double y,
double scale=1.0)
//--------------------------------------------------------------------
void init_embedded_adaptors(const glyph_cache* gl, double x, double y, double scale = 1.0)
{
if (gl)
{
if(gl)
switch (gl->data_type)
{
switch(gl->data_type)
{
default: return;
default:
return;
case glyph_data_mono:
m_mono_adaptor.init(gl->data, gl->data_size, x, y);
break;
@ -331,79 +289,76 @@ namespace agg
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; }
//--------------------------------------------------------------------
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; }
//--------------------------------------------------------------------
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)
//--------------------------------------------------------------------
bool add_kerning(double* x, double* y)
{
if (m_prev_glyph && m_last_glyph)
{
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;
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 precache(unsigned from, unsigned to)
{
for (; from <= to; ++from)
glyph(from);
}
//--------------------------------------------------------------------
void reset_cache()
//--------------------------------------------------------------------
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(), true);
m_fonts.font(m_engine.font_signature());
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&);
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;
};
//--------------------------------------------------------------------
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;
};
}
} // namespace agg
#endif

View file

@ -19,116 +19,135 @@
#include <cmath>
#include "agg_basics.h"
namespace agg
namespace agg {
//===============================================================gamma_none
struct gamma_none
{
//===============================================================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
{
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
{
if (x == 0.0) return 0.0;
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;
double delta = m_end - m_start;
// avoid nan from potential zero division
// https://github.com/mapnik/mapnik/issues/761
if (delta <= 0.0) return 0.0;
return (x - m_start) / delta;
}
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;
};
inline double sRGB_to_linear(double x)
{
return (x <= 0.04045) ? (x / 12.92) : pow((x + 0.055) / (1.055), 2.4);
if (x == 0.0)
return 0.0;
return pow(x, m_gamma);
}
inline double linear_to_sRGB(double x)
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)
{
return (x <= 0.0031308) ? (x * 12.92) : (1.055 * pow(x, 1 / 2.4) - 0.055);
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;
double delta = m_end - m_start;
// avoid nan from potential zero division
// https://github.com/mapnik/mapnik/issues/761
if (delta <= 0.0)
return 0.0;
return (x - m_start) / delta;
}
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;
};
inline double sRGB_to_linear(double x)
{
return (x <= 0.04045) ? (x / 12.92) : pow((x + 0.055) / (1.055), 2.4);
}
inline double linear_to_sRGB(double x)
{
return (x <= 0.0031308) ? (x * 12.92) : (1.055 * pow(x, 1 / 2.4) - 0.055);
}
} // namespace agg
#endif

View file

@ -20,286 +20,247 @@
#include "agg_basics.h"
#include "agg_gamma_functions.h"
namespace agg
namespace agg {
template<class LoResT = int8u, class HiResT = int8u, unsigned GammaShift = 8, unsigned HiResShift = 8>
class gamma_lut
{
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()
{
public:
typedef gamma_lut<LoResT, HiResT, GammaShift, HiResShift> self_type;
pod_allocator<LoResT>::deallocate(m_inv_gamma, hi_res_size);
pod_allocator<HiResT>::deallocate(m_dir_gamma, gamma_size);
}
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;
};
//
// sRGB support classes
//
// Optimized sRGB lookup table. The direct conversion (sRGB to linear)
// is a straightforward lookup. The inverse conversion (linear to sRGB)
// is implemented using binary search.
template<class LinearType>
class sRGB_lut_base
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))
{
public:
LinearType dir(int8u v) const
unsigned i;
for (i = 0; i < gamma_size; i++)
{
return m_dir_table[v];
m_dir_gamma[i] = HiResT(i << (hi_res_shift - gamma_shift));
}
int8u inv(LinearType v) const
for (i = 0; i < hi_res_size; i++)
{
// Unrolled binary search.
int8u x = 0;
if (v > m_inv_table[128]) x = 128;
if (v > m_inv_table[x + 64]) x += 64;
if (v > m_inv_table[x + 32]) x += 32;
if (v > m_inv_table[x + 16]) x += 16;
if (v > m_inv_table[x + 8]) x += 8;
if (v > m_inv_table[x + 4]) x += 4;
if (v > m_inv_table[x + 2]) x += 2;
if (v > m_inv_table[x + 1]) x += 1;
return x;
m_inv_gamma[i] = LoResT(i >> (hi_res_shift - gamma_shift));
}
}
protected:
LinearType m_dir_table[256];
LinearType m_inv_table[256];
// Only derived classes may instantiate.
sRGB_lut_base()
{
}
};
// sRGB_lut - implements sRGB conversion for the various types.
// Base template is undefined, specializations are provided below.
template<class LinearType>
class sRGB_lut;
template<>
class sRGB_lut<float> : public sRGB_lut_base<float>
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))
{
public:
sRGB_lut()
{
// Generate lookup tables.
m_dir_table[0] = 0;
m_inv_table[0] = 0;
for (unsigned i = 1; i <= 255; ++i)
{
// Floating-point RGB is in range [0,1].
m_dir_table[i] = float(sRGB_to_linear(i / 255.0));
m_inv_table[i] = float(sRGB_to_linear((i - 0.5) / 255.0));
}
}
};
gamma(g);
}
template<>
class sRGB_lut<int16u> : public sRGB_lut_base<int16u>
void gamma(double g)
{
public:
sRGB_lut()
{
// Generate lookup tables.
m_dir_table[0] = 0;
m_inv_table[0] = 0;
for (unsigned i = 1; i <= 255; ++i)
{
// 16-bit RGB is in range [0,65535].
m_dir_table[i] = uround(65535.0 * sRGB_to_linear(i / 255.0));
m_inv_table[i] = uround(65535.0 * sRGB_to_linear((i - 0.5) / 255.0));
}
}
};
m_gamma = g;
template<>
class sRGB_lut<int8u> : public sRGB_lut_base<int8u>
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;
};
//
// sRGB support classes
//
// Optimized sRGB lookup table. The direct conversion (sRGB to linear)
// is a straightforward lookup. The inverse conversion (linear to sRGB)
// is implemented using binary search.
template<class LinearType>
class sRGB_lut_base
{
public:
LinearType dir(int8u v) const { return m_dir_table[v]; }
int8u inv(LinearType v) const
{
public:
sRGB_lut()
{
// Generate lookup tables.
m_dir_table[0] = 0;
m_inv_table[0] = 0;
for (unsigned i = 1; i <= 255; ++i)
{
// 8-bit RGB is handled with simple bidirectional lookup tables.
m_dir_table[i] = uround(255.0 * sRGB_to_linear(i / 255.0));
m_inv_table[i] = uround(255.0 * linear_to_sRGB(i / 255.0));
}
}
// Unrolled binary search.
int8u x = 0;
if (v > m_inv_table[128])
x = 128;
if (v > m_inv_table[x + 64])
x += 64;
if (v > m_inv_table[x + 32])
x += 32;
if (v > m_inv_table[x + 16])
x += 16;
if (v > m_inv_table[x + 8])
x += 8;
if (v > m_inv_table[x + 4])
x += 4;
if (v > m_inv_table[x + 2])
x += 2;
if (v > m_inv_table[x + 1])
x += 1;
return x;
}
int8u inv(int8u v) const
{
// In this case, the inverse transform is a simple lookup.
return m_inv_table[v];
}
};
protected:
LinearType m_dir_table[256];
LinearType m_inv_table[256];
// Common base class for sRGB_conv objects. Defines an internal
// sRGB_lut object so that users don't have to.
template<class T>
class sRGB_conv_base
// Only derived classes may instantiate.
sRGB_lut_base() {}
};
// sRGB_lut - implements sRGB conversion for the various types.
// Base template is undefined, specializations are provided below.
template<class LinearType>
class sRGB_lut;
template<>
class sRGB_lut<float> : public sRGB_lut_base<float>
{
public:
sRGB_lut()
{
public:
static T rgb_from_sRGB(int8u x)
// Generate lookup tables.
m_dir_table[0] = 0;
m_inv_table[0] = 0;
for (unsigned i = 1; i <= 255; ++i)
{
return lut.dir(x);
// Floating-point RGB is in range [0,1].
m_dir_table[i] = float(sRGB_to_linear(i / 255.0));
m_inv_table[i] = float(sRGB_to_linear((i - 0.5) / 255.0));
}
}
};
static int8u rgb_to_sRGB(T x)
{
return lut.inv(x);
}
private:
static sRGB_lut<T> lut;
};
// Definition of sRGB_conv_base::lut. Due to the fact that this a template,
// we don't need to place the definition in a cpp file. Hurrah.
template<class T>
sRGB_lut<T> sRGB_conv_base<T>::lut;
// Wrapper for sRGB-linear conversion.
// Base template is undefined, specializations are provided below.
template<class T>
class sRGB_conv;
template<>
class sRGB_conv<float> : public sRGB_conv_base<float>
template<>
class sRGB_lut<int16u> : public sRGB_lut_base<int16u>
{
public:
sRGB_lut()
{
public:
static float alpha_from_sRGB(int8u x)
// Generate lookup tables.
m_dir_table[0] = 0;
m_inv_table[0] = 0;
for (unsigned i = 1; i <= 255; ++i)
{
return float(x / 255.0);
// 16-bit RGB is in range [0,65535].
m_dir_table[i] = uround(65535.0 * sRGB_to_linear(i / 255.0));
m_inv_table[i] = uround(65535.0 * sRGB_to_linear((i - 0.5) / 255.0));
}
}
};
static int8u alpha_to_sRGB(float x)
{
if (x <= 0) return 0;
else if (x >= 1) return 255;
else return int8u(0.5 + x * 255);
}
};
template<>
class sRGB_conv<int16u> : public sRGB_conv_base<int16u>
template<>
class sRGB_lut<int8u> : public sRGB_lut_base<int8u>
{
public:
sRGB_lut()
{
public:
static int16u alpha_from_sRGB(int8u x)
// Generate lookup tables.
m_dir_table[0] = 0;
m_inv_table[0] = 0;
for (unsigned i = 1; i <= 255; ++i)
{
return (x << 8) | x;
// 8-bit RGB is handled with simple bidirectional lookup tables.
m_dir_table[i] = uround(255.0 * sRGB_to_linear(i / 255.0));
m_inv_table[i] = uround(255.0 * linear_to_sRGB(i / 255.0));
}
}
static int8u alpha_to_sRGB(int16u x)
{
return x >> 8;
}
};
template<>
class sRGB_conv<int8u> : public sRGB_conv_base<int8u>
int8u inv(int8u v) const
{
public:
static int8u alpha_from_sRGB(int8u x)
{
return x;
}
// In this case, the inverse transform is a simple lookup.
return m_inv_table[v];
}
};
static int8u alpha_to_sRGB(int8u x)
{
return x;
}
};
}
// Common base class for sRGB_conv objects. Defines an internal
// sRGB_lut object so that users don't have to.
template<class T>
class sRGB_conv_base
{
public:
static T rgb_from_sRGB(int8u x) { return lut.dir(x); }
static int8u rgb_to_sRGB(T x) { return lut.inv(x); }
private:
static sRGB_lut<T> lut;
};
// Definition of sRGB_conv_base::lut. Due to the fact that this a template,
// we don't need to place the definition in a cpp file. Hurrah.
template<class T>
sRGB_lut<T> sRGB_conv_base<T>::lut;
// Wrapper for sRGB-linear conversion.
// Base template is undefined, specializations are provided below.
template<class T>
class sRGB_conv;
template<>
class sRGB_conv<float> : public sRGB_conv_base<float>
{
public:
static float alpha_from_sRGB(int8u x) { return float(x / 255.0); }
static int8u alpha_to_sRGB(float x)
{
if (x <= 0)
return 0;
else if (x >= 1)
return 255;
else
return int8u(0.5 + x * 255);
}
};
template<>
class sRGB_conv<int16u> : public sRGB_conv_base<int16u>
{
public:
static int16u alpha_from_sRGB(int8u x) { return (x << 8) | x; }
static int8u alpha_to_sRGB(int16u x) { return x >> 8; }
};
template<>
class sRGB_conv<int8u> : public sRGB_conv_base<int8u>
{
public:
static int8u alpha_from_sRGB(int8u x) { return x; }
static int8u alpha_to_sRGB(int8u x) { return x; }
};
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -19,137 +19,134 @@
#include <cstring>
#include "agg_basics.h"
namespace agg
namespace agg {
//========================================================glyph_raster_bin
template<class ColorT>
class glyph_raster_bin
{
public:
typedef ColorT color_type;
//========================================================glyph_raster_bin
template<class ColorT> class glyph_raster_bin
//--------------------------------------------------------------------
struct glyph_rect
{
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;
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;
};
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -21,226 +21,200 @@
#include "agg_color_rgba.h"
#include "agg_color_gray.h"
namespace agg
namespace agg {
//======================================================color_interpolator
template<class ColorT>
struct color_interpolator
{
public:
typedef ColorT color_type;
//======================================================color_interpolator
template<class ColorT> struct color_interpolator
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++()
{
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);
bool 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();
++r;
++g;
++b;
++a;
}
//------------------------------------------------------------------------
template<class T, unsigned S>
void gradient_lut<T,S>::add_color(double offset, const color_type& color)
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++()
{
m_color_profile.add(color_point(offset, color));
++v;
++a;
}
//------------------------------------------------------------------------
template<class T, unsigned S>
bool gradient_lut<T,S>::build_lut()
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);
bool 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
{
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)
double offset;
color_type color;
color_point() {}
color_point(double off, const color_type& c)
: offset(off)
, color(c)
{
unsigned i;
unsigned start = uround(m_color_profile[0].offset * color_lut_size);
unsigned end = 0;
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;
}
return true;
if (offset < 0.0)
offset = 0.0;
if (offset > 1.0)
offset = 1.0;
}
return false;
}
};
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>
bool 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 = 0;
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;
}
return true;
}
return false;
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -24,130 +24,107 @@
#include "agg_conv_stroke.h"
#include "agg_conv_transform.h"
namespace agg
namespace agg {
//---------------------------------------------------------------gsv_text
//
// See Implementation agg_gsv_text.cpp
//
class gsv_text
{
enum status { initial, next_char, start_glyph, glyph };
public:
gsv_text();
//---------------------------------------------------------------gsv_text
//
// See Implementation agg_gsv_text.cpp
//
class 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
{
enum status
int16u v;
if (m_big_endian)
{
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;
*(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;
};
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); }
//--------------------------------------------------------gsv_text_outline
template<class Transformer = trans_affine> class gsv_text_outline
void rewind(unsigned path_id)
{
public:
gsv_text_outline(gsv_text& text, const Transformer& trans) :
m_polyline(text),
m_trans(m_polyline, trans)
{
}
m_trans.rewind(path_id);
m_polyline.line_join(round_join);
m_polyline.line_cap(round_cap);
}
void width(double w)
{
m_polyline.width(w);
}
unsigned vertex(double* x, double* y) { return m_trans.vertex(x, y); }
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;
};
}
private:
conv_stroke<gsv_text> m_polyline;
conv_transform<conv_stroke<gsv_text>, Transformer> m_trans;
};
} // namespace agg
#endif

View file

@ -18,464 +18,439 @@
#include "agg_basics.h"
namespace agg
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
template<class PixFmt> class image_accessor_clip
image_accessor_clip() {}
explicit image_accessor_clip(const pixfmt_type& pixf, const color_type& bk)
: m_pixf(&pixf)
{
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 };
pixfmt_type::make_pix(m_bk_buf, bk);
}
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 attach(const pixfmt_type& pixf)
{
m_pixf = &pixf;
}
void background_color(const color_type& bk) { pixfmt_type::make_pix(m_bk_buf, bk); }
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
private:
AGG_INLINE const int8u* pixel() const
{
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)
if (m_y >= 0 && m_y < (int)m_pixf->height() && m_x >= 0 && m_x < (int)m_pixf->width())
{
m_pixf = &pixf;
return m_pixf->pix_ptr(m_x, m_y);
}
return m_bk_buf;
}
AGG_INLINE const int8u* span(int x, int y, unsigned)
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())
{
m_x = x;
m_y = y;
return m_pix_ptr = m_pixf->pix_ptr(x, y);
}
m_pix_ptr = 0;
return pixel();
}
AGG_INLINE const int8u* next_x()
{
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()
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())
{
++m_y;
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_y;
const int8u* m_pix_ptr;
};
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; }
//----------------------------------------------------image_accessor_clone
template<class PixFmt> class image_accessor_clone
AGG_INLINE const int8u* span(int x, int y, unsigned)
{
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 };
m_x = x;
m_y = y;
return m_pix_ptr = m_pixf->pix_ptr(x, y);
}
image_accessor_clone() {}
explicit image_accessor_clone(const pixfmt_type& pixf) :
m_pixf(&pixf)
{}
AGG_INLINE const int8u* next_x() { return m_pix_ptr += pix_width; }
void attach(const pixfmt_type& pixf)
{
m_pixf = &pixf;
}
private:
AGG_INLINE const int8u* pixel() const
{
int x = m_x;
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+(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;
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
AGG_INLINE const int8u* next_y()
{
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 };
++m_y;
return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y);
}
image_accessor_wrap() {}
explicit image_accessor_wrap(const pixfmt_type& pixf) :
m_pixf(&pixf),
m_wrap_x(pixf.width()),
m_wrap_y(pixf.height())
{}
private:
const pixfmt_type* m_pixf;
int m_x, m_y;
const int8u* m_pix_ptr;
};
void attach(const pixfmt_type& pixf)
{
m_pixf = &pixf;
}
//----------------------------------------------------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 };
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;
}
image_accessor_clone() {}
explicit image_accessor_clone(const pixfmt_type& pixf)
: m_pixf(&pixf)
{}
AGG_INLINE const int8u* next_x()
{
int x = ++m_wrap_x;
return m_row_ptr + x * pix_width;
}
void attach(const pixfmt_type& pixf) { m_pixf = &pixf; }
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
private:
AGG_INLINE const int8u* pixel() const
{
public:
wrap_mode_repeat() {}
wrap_mode_repeat(unsigned size) :
m_size(size),
m_add(size * (0x3FFFFFFF / size)),
m_value(0)
{}
int x = m_x;
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);
}
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:
AGG_INLINE const int8u* span(int x, int y, unsigned len)
{
public:
wrap_mode_repeat_pow2() {}
wrap_mode_repeat_pow2(unsigned size) : m_value(0)
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())
{
m_mask = 1;
while(m_mask < size) m_mask = (m_mask << 1) | 1;
m_mask >>= 1;
return m_pix_ptr = m_pixf->pix_ptr(x, y);
}
AGG_INLINE unsigned operator() (int v)
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;
}
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
return m_value = (unsigned(v) + m_add) % m_size;
}
AGG_INLINE unsigned operator++()
{
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)
{}
++m_value;
if (m_value >= m_size)
m_value = 0;
return m_value;
}
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;
};
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)
{}
//-------------------------------------------------------wrap_mode_reflect
class wrap_mode_reflect
AGG_INLINE unsigned operator()(int v)
{
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)
{}
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() (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
AGG_INLINE unsigned operator++()
{
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;
};
++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_auto_pow2
class wrap_mode_reflect_auto_pow2
//--------------------------------------------------wrap_mode_reflect_pow2
class wrap_mode_reflect_pow2
{
public:
wrap_mode_reflect_pow2() {}
wrap_mode_reflect_pow2(unsigned size)
: m_value(0)
{
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_mask = 1;
m_size = 1;
while (m_mask < size)
{
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;
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_size2;
unsigned m_add;
unsigned m_mask;
unsigned 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;
};
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -23,426 +23,499 @@
#include "agg_array.h"
#include "agg_math.h"
namespace agg
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
{
// See Implementation agg_image_filters.cpp
enum image_filter_scale_e
public:
template<class FilterF>
void calculate(const FilterF& filter, bool normalization = true)
{
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 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();
}
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);
}
image_filter_lut() : m_radius(0), m_diameter(0), m_start(0) {}
template<class FilterF> image_filter_lut(const FilterF& filter,
bool normalization=true)
unsigned end = (diameter() << image_subpixel_shift) - 1;
m_weight_array[0] = m_weight_array[end];
if (normalization)
{
calculate(filter, normalization);
normalize();
}
}
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();
image_filter_lut()
: m_radius(0)
, m_diameter(0)
, m_start(0)
{}
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
template<class FilterF>
image_filter_lut(const FilterF& filter, bool normalization = true)
{
public:
image_filter()
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 * std::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 * std::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)
{
calculate(m_filter_function);
t = x - 1.5;
return 0.5 * t * t;
}
private:
FilterF m_filter_function;
};
return 0.0;
}
};
//------------------------------------------------image_filter_bicubic
class image_filter_bicubic
{
static double pow3(double x) { return (x <= 0.0) ? 0.0 : x * x * x; }
//-----------------------------------------------image_filter_bilinear
struct image_filter_bilinear
public:
static double radius() { return 2.0; }
static double calc_weight(double x)
{
static double radius() { return 1.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++)
{
return 1.0 - x;
sum += t;
t *= (double)y / (i * i);
}
};
return sum;
}
};
//-----------------------------------------------image_filter_hanning
struct image_filter_hanning
//----------------------------------------------image_filter_catrom
struct image_filter_catrom
{
static double radius() { return 2.0; }
static double calc_weight(double x)
{
static double radius() { return 1.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 0.5 + 0.5 * std::cos(pi * x);
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_hamming
struct image_filter_hamming
//---------------------------------------------image_filter_spline36
struct image_filter_spline36
{
static double radius() { return 3.0; }
static double calc_weight(double x)
{
static double radius() { return 1.0; }
static double calc_weight(double x)
if (x < 1.0)
{
return 0.54 + 0.46 * std::cos(pi * x);
return ((13.0 / 11.0 * x - 453.0 / 209.0) * x - 3.0 / 209.0) * x + 1.0;
}
};
//-----------------------------------------------image_filter_hermite
struct image_filter_hermite
{
static double radius() { return 1.0; }
static double calc_weight(double x)
if (x < 2.0)
{
return (2.0 * x - 3.0) * x * x + 1.0;
return ((-6.0 / 11.0 * (x - 1) + 270.0 / 209.0) * (x - 1) - 156.0 / 209.0) * (x - 1);
}
};
//------------------------------------------------image_filter_quadric
struct image_filter_quadric
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
{
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;}
if (x == 0.0)
return 1.0;
x *= pi;
return std::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 (std::sin(x) / x) * (std::sin(xr) / xr);
}
//------------------------------------------------image_filter_bicubic
class image_filter_bicubic
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
{
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));
if (x == 0.0)
return 1.0;
if (x > m_radius)
return 0.0;
}
};
x *= pi;
double xr = x / m_radius;
return (std::sin(x) / x) * (0.42 + 0.5 * std::cos(xr) + 0.08 * std::cos(2 * xr));
}
private:
double m_radius;
};
//----------------------------------------------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_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_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_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_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_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_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_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_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 std::sin(x) / x;
}
private:
double m_radius;
};
//--------------------------------------------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_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 (std::sin(x) / x) * (std::sin(xr) / xr);
}
private:
double m_radius;
};
//--------------------------------------------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_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 (std::sin(x) / x) * (0.42 + 0.5 * std::cos(xr) + 0.08 * std::cos(2*xr));
}
private:
double m_radius;
};
//--------------------------------------------image_filter_blackman36
class image_filter_blackman36 : public image_filter_blackman
{
public:
image_filter_blackman36()
: image_filter_blackman(3.0)
{}
};
//------------------------------------------------image_filter_sinc36
class image_filter_sinc36 : public image_filter_sinc
{ public: image_filter_sinc36() : image_filter_sinc(3.0){} };
//--------------------------------------------image_filter_blackman64
class image_filter_blackman64 : public image_filter_blackman
{
public:
image_filter_blackman64()
: image_filter_blackman(4.0)
{}
};
//------------------------------------------------image_filter_sinc64
class image_filter_sinc64 : public image_filter_sinc
{ public: image_filter_sinc64() : image_filter_sinc(4.0){} };
//-------------------------------------------image_filter_blackman100
class image_filter_blackman100 : public image_filter_blackman
{
public:
image_filter_blackman100()
: image_filter_blackman(5.0)
{}
};
//-----------------------------------------------image_filter_sinc100
class image_filter_sinc100 : public image_filter_sinc
{ public: image_filter_sinc100() : image_filter_sinc(5.0){} };
//-------------------------------------------image_filter_blackman144
class image_filter_blackman144 : public image_filter_blackman
{
public:
image_filter_blackman144()
: image_filter_blackman(6.0)
{}
};
//-----------------------------------------------image_filter_sinc144
class image_filter_sinc144 : public image_filter_sinc
{ public: image_filter_sinc144() : image_filter_sinc(6.0){} };
//-------------------------------------------image_filter_blackman196
class image_filter_blackman196 : public image_filter_blackman
{
public:
image_filter_blackman196()
: image_filter_blackman(7.0)
{}
};
//-----------------------------------------------image_filter_sinc196
class image_filter_sinc196 : public image_filter_sinc
{ public: image_filter_sinc196() : image_filter_sinc(7.0){} };
//-------------------------------------------image_filter_blackman256
class image_filter_blackman256 : public image_filter_blackman
{
public:
image_filter_blackman256()
: image_filter_blackman(8.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){} };
}
} // namespace agg
#endif

View file

@ -18,172 +18,154 @@
#include <cstdlib>
#include "agg_basics.h"
namespace agg
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)
{
// 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_scale;
}
//---------------------------------------------------------------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(std::abs(x2_ - x1_)),
dy(std::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 = std::abs(lp1.x2 - lp1.x1);
lp1.dy = std::abs(lp1.y2 - lp1.y1);
lp2.x1 = xmid;
lp2.y1 = ymid;
lp2.len = len2;
lp2.dx = std::abs(lp2.x2 - lp2.x1);
lp2.dy = std::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);
}
}
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_scale;
}
//---------------------------------------------------------------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(std::abs(x2_ - x1_))
, dy(std::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 = std::abs(lp1.x2 - lp1.x1);
lp1.dy = std::abs(lp1.y2 - lp1.y1);
lp2.x1 = xmid;
lp2.y1 = ymid;
lp2.len = len2;
lp2.dx = std::abs(lp2.x2 - lp2.x1);
lp2.dy = std::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);
}
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -12,7 +12,7 @@
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
// Bessel function (besj) was adapted for use in AGG library by Andy Wilk
// Bessel function (besj) was adapted for use in AGG library by Andy Wilk
// Contact: castor.vulgaris@gmail.com
//----------------------------------------------------------------------------
@ -22,251 +22,236 @@
#include <cmath>
#include "agg_basics.h"
namespace agg
namespace agg {
//------------------------------------------------------vertex_dist_epsilon
// Coinciding points maximal distance (Epsilon)
const double vertex_dist_epsilon = 1e-5;
//-----------------------------------------------------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);
}
//------------------------------------------------------vertex_dist_epsilon
// Coinciding points maximal distance (Epsilon)
const double vertex_dist_epsilon = 1e-5;
//--------------------------------------------------------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;
}
//-----------------------------------------------------intersection_epsilon
// See calc_intersection
const double intersection_epsilon = 1.0e-30;
//-----------------------------------------------------------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);
}
//------------------------------------------------------------cross_product
AGG_INLINE double cross_product(double x1, double y1,
double x2, double y2,
double x, double y)
//--------------------------------------------------------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 (x - x2) * (y2 - y1) - (y - y2) * (x2 - x1);
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;
}
//--------------------------------------------------------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;
}
double pdx = x - x1;
double pdy = y - y1;
//-----------------------------------------------------------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);
}
return (pdx * dx + pdy * dy) / (dx * dx + dy * dy);
}
//--------------------------------------------------------calc_sq_distance
AGG_INLINE double calc_sq_distance(double x1, double y1, double x2, double y2)
//---------------------------------------------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)
{
double dx = x2-x1;
double dy = y2-y1;
return dx * dx + dy * dy;
return calc_sq_distance(x, y, x1, y1);
}
//------------------------------------------------calc_line_point_distance
AGG_INLINE double calc_line_point_distance(double x1, double y1,
double x2, double y2,
double x, double y)
else if (u >= 1)
{
double dx = x2-x1;
double dy = y2-y1;
double d = sqrt(dx * dx + dy * dy);
if(d < vertex_dist_epsilon)
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 (std::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(std::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 (std::fabs(loc) > intersection_epsilon)
{
if (cross_product(x1, y1, x2, y2, x3, y3) > 0.0)
{
return calc_distance(x1, y1, x, y);
d = -d;
}
return ((x - x2) * dy - (y - y2) * dx) / 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_line_point_u
AGG_INLINE double calc_segment_point_u(double x1, double y1,
double x2, double y2,
double x, double y)
//------------------------------------------------------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++)
{
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);
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;
}
//---------------------------------------------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));
}
//------------------------------------------------------------------------
// Tables for fast sqrt
extern int16u g_sqrt_table[1024];
extern int8 g_elder_bit_table[256];
//---------------------------------------------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(std::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(std::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(std::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
{
//---------------------------------------------------------------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
@ -282,156 +267,153 @@ namespace agg
mov ax, g_sqrt_table[ebx*2]
mov ecx, edx
shr eax, cl
}
#else
}
#else
//This code is actually pure C and portable to most
//arcitectures including 64bit ones.
unsigned t = val;
int bit=0;
unsigned shift = 11;
// 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)
// 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] + 24;
bit = g_elder_bit_table[bit] + 16;
}
else
{
bit = (t >> 16) & 0xFF;
if(bit)
bit = (t >> 8) & 0xFF;
if (bit)
{
bit = g_elder_bit_table[bit] + 16;
bit = g_elder_bit_table[bit] + 8;
}
else
{
bit = (t >> 8) & 0xFF;
if(bit)
{
bit = g_elder_bit_table[bit] + 8;
}
else
{
bit = g_elder_bit_table[t];
}
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)
// This code calculates the sqrt.
bit -= 9;
if (bit > 0)
{
if(n < 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 (std::fabs(x) <= d)
{
if (n != 0)
return 0;
}
double d = 1E-6;
double b = 0;
if(std::fabs(x) <= d)
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 (std::fabs(x) > 5)
{
m1 = (int)(std::fabs(1.4 * x + 60 / x));
}
int m2 = (int)(n + 2 + std::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)
{
if(n != 0) return 0;
return 1;
m8 = -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(std::fabs(x) > 5)
int imax = m2 - 2;
for (int i = 1; i <= imax; i++)
{
m1 = (int)(std::fabs(1.4 * x + 60 / x));
}
int m2 = (int)(n + 2 + std::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)
double c6 = 2 * (m2 - i) * c2 / x - c3;
c3 = c2;
c2 = c6;
if (m2 - i - 1 == n)
{
b = c6;
}
c4 += c6;
b /= c4;
if(std::fabs(b - b1) < d)
m8 = -1 * m8;
if (m8 > 0)
{
return b;
c4 = c4 + 2 * c6;
}
b1 = b;
m2 += 3;
}
double c6 = 2 * c2 / x - c3;
if (n == 0)
{
b = c6;
}
c4 += c6;
b /= c4;
if (std::fabs(b - b1) < d)
{
return b;
}
b1 = b;
m2 += 3;
}
}
} // namespace agg
#endif

View file

@ -23,254 +23,236 @@
#include "agg_math.h"
#include "agg_vertex_sequence.h"
namespace agg
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
{
//-------------------------------------------------------------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)
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;
}
//-----------------------------------------------------------------------
template<class VC> void math_stroke<VC>::width(double w)
else
{
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;
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)
//-----------------------------------------------------------------------
template<class VC>
void math_stroke<VC>::miter_limit_theta(double t)
{
m_miter_limit = 1.0 / std::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 = std::atan2(dy1 * m_width_sign, dx1 * m_width_sign);
double a2 = std::atan2(dy2 * m_width_sign, dx2 * m_width_sign);
double da = a1 - a2;
int i, n;
da = std::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)
{
m_miter_limit = 1.0 / std::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 = std::atan2(dy1 * m_width_sign, dx1 * m_width_sign);
double a2 = std::atan2(dy2 * m_width_sign, dx2 * m_width_sign);
double da = a1 - a2;
int i, n;
da = std::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++)
{
if(a1 > a2) a2 += 2 * pi;
n = int((a2 - a1) / da);
da = (a2 - a1) / (n + 1);
add_vertex(vc, x + std::cos(a1) * m_width, y + std::sin(a1) * m_width);
a1 += da;
for(i = 0; i < n; i++)
{
add_vertex(vc, x + std::cos(a1) * m_width, y + std::sin(a1) * m_width);
a1 += da;
}
}
else
}
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++)
{
if(a1 < a2) a2 -= 2 * pi;
n = int((a1 - a2) / da);
da = (a1 - a2) / (n + 1);
add_vertex(vc, x + std::cos(a1) * m_width, y + std::sin(a1) * m_width);
a1 -= da;
for(i = 0; i < n; i++)
{
add_vertex(vc, x + std::cos(a1) * m_width, y + std::sin(a1) * m_width);
a1 -= da;
}
}
add_vertex(vc, x + dx2, y + dy2);
}
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;
}
}
//-----------------------------------------------------------------------
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)
if (miter_limit_exceeded)
{
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))
// Miter limit exceeded
//------------------------
switch (lj)
{
// 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
@ -287,13 +269,11 @@ namespace agg
default:
// If no miter-revert, calculate new dx1, dy1, dx2, dy2
//----------------
if(intersection_failed)
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);
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
{
@ -302,208 +282,196 @@ namespace agg
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);
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)
//--------------------------------------------------------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)
{
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)
{
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 = std::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 = std::atan2(dy1, -dx1);
a1 += da;
for (i = 0; i < n; i++)
{
dx2 = dy1 * m_width_sign;
dy2 = dx1 * m_width_sign;
add_vertex(vc, v0.x + std::cos(a1) * m_width, v0.y + std::sin(a1) * m_width);
a1 += da;
}
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 = std::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 = std::atan2(-dy1, dx1);
a1 -= da;
for (i = 0; i < n; i++)
{
a1 = std::atan2(dy1, -dx1);
a1 += da;
for(i = 0; i < n; i++)
{
add_vertex(vc, v0.x + std::cos(a1) * m_width,
v0.y + std::sin(a1) * m_width);
a1 += da;
}
}
else
{
a1 = std::atan2(-dy1, dx1);
add_vertex(vc, v0.x + std::cos(a1) * m_width, v0.y + std::sin(a1) * m_width);
a1 -= da;
for(i = 0; i < n; i++)
{
add_vertex(vc, v0.x + std::cos(a1) * m_width,
v0.y + std::sin(a1) * m_width);
a1 -= da;
}
}
add_vertex(vc, v0.x + dx1, v0.y - dy1);
}
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)
//-----------------------------------------------------------------------
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) && m_width_abs > 0)
{
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) && m_width_abs > 0)
// Inner join
//---------------
double limit = ((len1 < len2) ? len1 : len2) / m_width_abs;
if (limit < m_inner_miter_limit)
{
// Inner join
//---------------
double limit = ((len1 < len2) ? len1 : len2) / m_width_abs;
if (limit < m_inner_miter_limit)
{
limit = m_inner_miter_limit;
}
limit = m_inner_miter_limit;
}
switch(m_inner_join)
{
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);
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)
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);
calc_miter(vc, v0, v1, v2, dx1, dy1, dx2, dy2, miter_join_revert, limit, 0);
}
else
{
if(m_inner_join == inner_jag)
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, 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 );
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, 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;
}
}
else
switch (m_line_join)
{
// 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);
calc_miter(vc, v0, v1, v2, dx1, dy1, dx2, dy2, m_line_join, m_miter_limit, dbevel);
break;
case round_join:
@ -514,13 +482,10 @@ namespace agg
add_vertex(vc, v1.x + dx1, v1.y - dy1);
add_vertex(vc, v1.x + dx2, v1.y - dy2);
break;
}
}
}
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -17,49 +17,48 @@
#include "agg_math.h"
namespace agg
namespace agg {
template<class VertexSource>
double path_length(VertexSource& vs, unsigned path_id = 0)
{
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;
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)))
unsigned cmd;
vs.rewind(path_id);
while (!is_stop(cmd = vs.vertex(&x2, &y2)))
{
if (is_vertex(cmd))
{
if(is_vertex(cmd))
if (first || is_move_to(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;
start_x = x2;
start_y = y2;
}
else
{
if(is_close(cmd) && !first)
{
len += calc_distance(x1, y1, start_x, start_y);
}
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;
}
return len;
}
} // namespace agg
#endif

File diff suppressed because it is too large Load diff

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -19,277 +19,259 @@
#include <cstring>
#include "agg_array.h"
namespace agg
namespace agg {
//---------------------------------------------------------vertex_integer
template<class T, unsigned CoordShift = 6>
struct vertex_integer
{
//---------------------------------------------------------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
{
enum path_cmd
*x_ = dx + (double(x >> 1) / coord_scale) * scale;
*y_ = dy + (double(y >> 1) / coord_scale) * scale;
switch (((y & 1) << 1) | (x & 1))
{
cmd_move_to = 0,
cmd_line_to = 1,
cmd_curve3 = 2,
cmd_curve4 = 3
};
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;
}
};
enum coord_scale_e
//---------------------------------------------------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++)
{
coord_shift = CoordShift,
coord_scale = 1 << coord_shift
};
memcpy(ptr, &m_storage[i], sizeof(vertex_integer_type));
ptr += sizeof(vertex_integer_type);
}
}
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)) {}
//--------------------------------------------------------------------
void rewind(unsigned)
{
m_vertex_idx = 0;
m_closed = true;
}
unsigned vertex(double* x_, double* y_,
double dx=0, double dy=0,
double scale=1.0) const
//--------------------------------------------------------------------
unsigned vertex(double* x, double* y)
{
if (m_storage.size() < 2 || m_vertex_idx > m_storage.size())
{
*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;
}
*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;
}
//---------------------------------------------------path_storage_integer
template<class T, unsigned CoordShift=6> class path_storage_integer
//--------------------------------------------------------------------
rect_d bounding_rect() const
{
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)
rect_d bounds(1e100, 1e100, -1e100, -1e100);
if (m_storage.size() == 0)
{
m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_move_to));
bounds.x1 = bounds.y1 = bounds.x2 = bounds.y2 = 0.0;
}
//--------------------------------------------------------------------
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
else
{
unsigned i;
for(i = 0; i < m_storage.size(); i++)
for (i = 0; i < m_storage.size(); i++)
{
memcpy(ptr, &m_storage[i], sizeof(vertex_integer_type));
ptr += sizeof(vertex_integer_type);
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;
}
//--------------------------------------------------------------------
void rewind(unsigned)
{
m_vertex_idx = 0;
m_closed = true;
}
private:
pod_bvector<vertex_integer_type, 6> m_storage;
unsigned m_vertex_idx;
bool m_closed;
};
//--------------------------------------------------------------------
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;
}
//-----------------------------------------serialized_integer_path_adaptor
template<class T, unsigned CoordShift = 6>
class serialized_integer_path_adaptor
{
public:
typedef vertex_integer<T, CoordShift> vertex_integer_type;
//--------------------------------------------------------------------
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;
}
//--------------------------------------------------------------------
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)
{}
private:
pod_bvector<vertex_integer_type, 6> m_storage;
unsigned m_vertex_idx;
bool m_closed;
};
//--------------------------------------------------------------------
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)
{}
//-----------------------------------------serialized_integer_path_adaptor
template<class T, unsigned CoordShift=6> class serialized_integer_path_adaptor
//--------------------------------------------------------------------
void init(const int8u* data, unsigned size, double dx, double dy, double scale = 1.0)
{
public:
typedef vertex_integer<T, CoordShift> vertex_integer_type;
m_data = data;
m_end = data + size;
m_ptr = data;
m_dx = dx;
m_dy = dy;
m_scale = scale;
m_vertices = 0;
}
//--------------------------------------------------------------------
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)
{}
//--------------------------------------------------------------------
void rewind(unsigned)
{
m_ptr = m_data;
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)
//--------------------------------------------------------------------
unsigned vertex(double* x, double* y)
{
if (m_data == 0 || m_ptr > m_end)
{
m_data = data;
m_end = data + size;
m_ptr = data;
m_dx = dx;
m_dy = dy;
m_scale = scale;
m_vertices = 0;
*x = 0;
*y = 0;
return path_cmd_stop;
}
//--------------------------------------------------------------------
void rewind(unsigned)
{
m_ptr = m_data;
m_vertices = 0;
}
//--------------------------------------------------------------------
unsigned vertex(double* x, double* y)
if (m_ptr == m_end)
{
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;
*x = 0;
*y = 0;
m_ptr += sizeof(vertex_integer_type);
return cmd;
return path_cmd_end_poly | path_flags_close;
}
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;
};
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;
};
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -19,104 +19,90 @@
#include "agg_line_aa_basics.h"
#include "agg_color_rgba.h"
namespace agg {
namespace agg
//=======================================================pattern_filter_nn
template<class ColorT>
struct pattern_filter_nn
{
typedef ColorT color_type;
static unsigned dilation() { return 0; }
//=======================================================pattern_filter_nn
template<class ColorT> struct pattern_filter_nn
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)
{
typedef ColorT color_type;
static unsigned dilation() { return 0; }
*p = buf[y >> line_subpixel_shift][x >> line_subpixel_shift];
}
};
static void AGG_INLINE pixel_low_res(color_type const* const* buf,
color_type* p, int x, int y)
{
*p = buf[y][x];
}
typedef pattern_filter_nn<rgba8> pattern_filter_nn_rgba8;
typedef pattern_filter_nn<rgba16> pattern_filter_nn_rgba16;
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];
}
};
//===========================================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;
typedef pattern_filter_nn<rgba8> pattern_filter_nn_rgba8;
typedef pattern_filter_nn<rgba16> pattern_filter_nn_rgba16;
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]; }
//===========================================pattern_filter_bilinear_rgba
template<class ColorT> struct pattern_filter_bilinear_rgba
static AGG_INLINE void pixel_high_res(color_type const* const* buf, color_type* p, int x, int y)
{
typedef ColorT color_type;
typedef typename color_type::value_type value_type;
typedef typename color_type::calc_type calc_type;
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;
static unsigned dilation() { return 1; }
x &= line_subpixel_mask;
y &= line_subpixel_mask;
const color_type* ptr = buf[y_lr] + x_lr;
static AGG_INLINE void pixel_low_res(color_type const* const* buf,
color_type* p, int x, int y)
{
*p = buf[y][x];
}
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;
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;
++ptr;
calc_type weight;
int x_lr = x >> line_subpixel_shift;
int y_lr = y >> line_subpixel_shift;
weight = x * (line_subpixel_scale - y);
r += weight * ptr->r;
g += weight * ptr->g;
b += weight * ptr->b;
a += weight * ptr->a;
x &= line_subpixel_mask;
y &= line_subpixel_mask;
const color_type* ptr = buf[y_lr] + x_lr;
ptr = buf[y_lr + 1] + 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;
weight = (line_subpixel_scale - x) * y;
r += weight * ptr->r;
g += weight * ptr->g;
b += weight * ptr->b;
a += weight * ptr->a;
++ptr;
++ptr;
weight = x * (line_subpixel_scale - y);
r += weight * ptr->r;
g += weight * ptr->g;
b += weight * ptr->b;
a += weight * ptr->a;
weight = x * y;
r += weight * ptr->r;
g += weight * ptr->g;
b += weight * ptr->b;
a += weight * ptr->a;
ptr = buf[y_lr + 1] + x_lr;
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);
}
};
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;
}
typedef pattern_filter_bilinear_rgba<rgba8> pattern_filter_bilinear_rgba8;
typedef pattern_filter_bilinear_rgba<rgba16> pattern_filter_bilinear_rgba16;
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -16,225 +16,196 @@
#ifndef AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED
#define AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED
#include <cstring>
#include "agg_array.h"
#include "agg_rendering_buffer.h"
namespace agg
namespace agg {
//==================================================pixfmt_amask_adaptor
template<class PixFmt, class AlphaMask>
class pixfmt_amask_adaptor
{
//==================================================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)
{
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())
{
if(len > m_span.size())
{
m_span.resize(len + span_extra_tail);
}
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)
{
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));
}
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()
{}
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; }
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);
}
//--------------------------------------------------------------------
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(); }
//--------------------------------------------------------------------
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); }
//--------------------------------------------------------------------
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 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 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 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 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 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 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 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 blend_solid_hspan(int x, int y,
unsigned len,
const color_type& c,
const cover_type* covers)
//--------------------------------------------------------------------
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);
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)
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_full);
}
m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover);
}
//--------------------------------------------------------------------
void copy_color_vspan(int x, int y, unsigned len, const color_type* colors)
//--------------------------------------------------------------------
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_full);
}
m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover);
}
//--------------------------------------------------------------------
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);
}
private:
pixfmt_type* m_pixf;
const amask_type* m_mask;
pod_array<cover_type> m_span;
};
//--------------------------------------------------------------------
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;
};
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -20,78 +20,69 @@
#include "agg_color_gray.h"
#include "agg_color_rgba.h"
namespace agg
namespace agg {
struct pixfmt_gray_tag
{};
struct pixfmt_rgb_tag
{};
struct pixfmt_rgba_tag
{};
//--------------------------------------------------------------blender_base
template<class ColorT, class Order = void>
struct blender_base
{
struct pixfmt_gray_tag
{
};
typedef ColorT color_type;
typedef Order order_type;
typedef typename color_type::value_type value_type;
struct pixfmt_rgb_tag
static rgba get(value_type r, value_type g, value_type b, value_type a, cover_type cover = cover_full)
{
};
struct pixfmt_rgba_tag
{
};
//--------------------------------------------------------------blender_base
template<class ColorT, class Order = void>
struct blender_base
{
typedef ColorT color_type;
typedef Order order_type;
typedef typename color_type::value_type value_type;
static rgba get(value_type r, value_type g, value_type b, value_type a, cover_type cover = cover_full)
if (cover > cover_none)
{
if (cover > cover_none)
rgba c(color_type::to_double(r),
color_type::to_double(g),
color_type::to_double(b),
color_type::to_double(a));
if (cover < cover_full)
{
rgba c(
color_type::to_double(r),
color_type::to_double(g),
color_type::to_double(b),
color_type::to_double(a));
if (cover < cover_full)
{
double x = double(cover) / cover_full;
c.r *= x;
c.g *= x;
c.b *= x;
c.a *= x;
}
return c;
double x = double(cover) / cover_full;
c.r *= x;
c.g *= x;
c.b *= x;
c.a *= x;
}
else return rgba::no_color();
}
static rgba get(const value_type* p, cover_type cover = cover_full)
{
return get(
p[order_type::R],
p[order_type::G],
p[order_type::B],
p[order_type::A],
cover);
return c;
}
else
return rgba::no_color();
}
static void set(value_type* p, value_type r, value_type g, value_type b, value_type a)
{
p[order_type::R] = r;
p[order_type::G] = g;
p[order_type::B] = b;
p[order_type::A] = a;
}
static rgba get(const value_type* p, cover_type cover = cover_full)
{
return get(p[order_type::R], p[order_type::G], p[order_type::B], p[order_type::A], cover);
}
static void set(value_type* p, const rgba& c)
{
p[order_type::R] = color_type::from_double(c.r);
p[order_type::G] = color_type::from_double(c.g);
p[order_type::B] = color_type::from_double(c.b);
p[order_type::A] = color_type::from_double(c.a);
}
};
}
static void set(value_type* p, value_type r, value_type g, value_type b, value_type a)
{
p[order_type::R] = r;
p[order_type::G] = g;
p[order_type::B] = b;
p[order_type::A] = a;
}
static void set(value_type* p, const rgba& c)
{
p[order_type::R] = color_type::from_double(c.r);
p[order_type::G] = color_type::from_double(c.g);
p[order_type::B] = color_type::from_double(c.b);
p[order_type::A] = color_type::from_double(c.a);
}
};
} // namespace agg
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -18,140 +18,99 @@
#include "agg_basics.h"
namespace agg
namespace agg {
//=======================================================pixfmt_transposer
template<class PixFmt>
class pixfmt_transposer
{
//=======================================================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)
{
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;
m_pixf->blend_vline(y, x, len, c, cover);
}
//--------------------------------------------------------------------
pixfmt_transposer() : m_pixf(0) {}
explicit pixfmt_transposer(pixfmt_type& pixf) : m_pixf(&pixf) {}
void attach(pixfmt_type& pixf) { m_pixf = &pixf; }
//--------------------------------------------------------------------
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 unsigned width() const { return m_pixf->height(); }
AGG_INLINE unsigned height() const { return m_pixf->width(); }
//--------------------------------------------------------------------
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 color_type pixel(int x, int y) const
{
return m_pixf->pixel(y, x);
}
//--------------------------------------------------------------------
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_pixel(int x, int y, const color_type& c)
{
m_pixf->copy_pixel(y, x, c);
}
//--------------------------------------------------------------------
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 blend_pixel(int x, int y,
const color_type& c,
int8u cover)
{
m_pixf->blend_pixel(y, x, c, cover);
}
//--------------------------------------------------------------------
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 copy_hline(int x, int y,
unsigned len,
const color_type& c)
{
m_pixf->copy_vline(y, x, len, c);
}
//--------------------------------------------------------------------
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 copy_vline(int x, int y,
unsigned len,
const color_type& c)
{
m_pixf->copy_hline(y, x, len, c);
}
//--------------------------------------------------------------------
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);
}
//--------------------------------------------------------------------
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;
};
}
private:
pixfmt_type* m_pixf;
};
} // namespace agg
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -17,131 +17,116 @@
#include "agg_basics.h"
namespace agg
namespace agg {
//======================================================rasterizer_outline
template<class Renderer>
class rasterizer_outline
{
//======================================================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)
{
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; }
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(int x, int 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)
{
m_vertices = 1;
m_ren->move_to(m_start_x = x, m_start_y = y);
line_to(m_start_x, m_start_y);
}
m_vertices = 0;
}
//--------------------------------------------------------------------
void line_to(int x, int y)
//--------------------------------------------------------------------
void add_vertex(double x, double y, unsigned cmd)
{
if (is_move_to(cmd))
{
++m_vertices;
m_ren->line_to(x, y);
move_to_d(x, y);
}
//--------------------------------------------------------------------
void move_to_d(double x, double y)
else
{
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)
if (is_end_poly(cmd))
{
line_to(m_start_x, m_start_y);
if (is_closed(cmd))
close();
}
m_vertices = 0;
}
//--------------------------------------------------------------------
void add_vertex(double x, double y, unsigned cmd)
{
if(is_move_to(cmd))
else
{
move_to_d(x, y);
}
else
{
if(is_end_poly(cmd))
{
if(is_closed(cmd)) close();
}
else
{
line_to_d(x, y);
}
line_to_d(x, y);
}
}
}
//--------------------------------------------------------------------
template<class VertexSource>
void add_path(VertexSource& vs, unsigned path_id = 0)
{
double x;
double y;
//--------------------------------------------------------------------
template<class VertexSource>
void add_path(VertexSource& vs, unsigned path_id=0)
unsigned cmd;
vs.rewind(path_id);
while (!is_stop(cmd = vs.vertex(&x, &y)))
{
double x;
double y;
unsigned cmd;
vs.rewind(path_id);
while(!is_stop(cmd = vs.vertex(&x, &y)))
{
add_vertex(x, y, cmd);
}
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)
//--------------------------------------------------------------------
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++)
{
for(unsigned i = 0; i < num_paths; i++)
{
m_ren->line_color(colors[i]);
add_path(vs, path_id[i]);
}
m_ren->line_color(colors[i]);
add_path(vs, path_id[i]);
}
}
//--------------------------------------------------------------------
template<class Ctrl> void render_ctrl(Ctrl& c)
//--------------------------------------------------------------------
template<class Ctrl>
void render_ctrl(Ctrl& c)
{
unsigned i;
for (i = 0; i < c.num_paths(); i++)
{
unsigned i;
for(i = 0; i < c.num_paths(); i++)
{
m_ren->line_color(c.color(i));
add_path(c, 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;
};
private:
Renderer* m_ren;
int m_start_x;
int m_start_y;
unsigned m_vertices;
};
}
} // namespace agg
#endif

File diff suppressed because it is too large Load diff

View file

@ -33,477 +33,445 @@
#include "agg_rasterizer_sl_clip.h"
#include "agg_gamma_functions.h"
namespace agg {
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;
//-----------------------------------------------------------------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
void initial()
{
int x;
int y;
int cover;
int area;
x = 0x7FFFFFFF;
y = 0x7FFFFFFF;
cover = 0;
area = 0;
}
void initial()
{
x = 0x7FFFFFFF;
y = 0x7FFFFFFF;
cover = 0;
area = 0;
}
void style(const cell_aa&) {}
void style(const cell_aa&) {}
int not_equal(int ex, int ey, const cell_aa&) const { return (ex - x) | (ey - y); }
};
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
// 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
//--------------------------------------------------------------------
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)
{
enum status
{
status_initial,
status_move_to,
status_line_to,
status_closed
};
int i;
for (i = 0; i < aa_scale; i++)
m_gamma[i] = i;
}
public:
typedef Clip clip_type;
typedef typename Clip::conv_type conv_type;
typedef typename Clip::coord_type coord_type;
//--------------------------------------------------------------------
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);
}
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
};
//--------------------------------------------------------------------
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; }
//--------------------------------------------------------------------
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)
//--------------------------------------------------------------------
template<class GammaF>
void gamma(const GammaF& gamma_function)
{
int i;
for (i = 0; i < aa_scale; i++)
{
int i;
for(i = 0; i < aa_scale; i++) m_gamma[i] = i;
m_gamma[i] = uround(gamma_function(double(i) / aa_mask) * aa_mask);
}
}
//--------------------------------------------------------------------
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)
//--------------------------------------------------------------------
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)))
{
gamma(gamma_function);
add_vertex(x, y, cmd);
}
}
//--------------------------------------------------------------------
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; }
//--------------------------------------------------------------------
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(); }
//--------------------------------------------------------------------
template<class GammaF> void gamma(const GammaF& gamma_function)
//--------------------------------------------------------------------
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)
{
int i;
for(i = 0; i < aa_scale; i++)
cover &= aa_mask2;
if (cover > aa_scale)
{
m_gamma[i] = uround(gamma_function(double(i) / aa_mask) * aa_mask);
cover = aa_scale2 - cover;
}
}
if (cover > aa_mask)
cover = aa_mask;
return m_gamma[cover];
}
//--------------------------------------------------------------------
unsigned apply_gamma(unsigned cover) const
//--------------------------------------------------------------------
template<class Scanline>
bool sweep_scanline(Scanline& sl)
{
for (;;)
{
return m_gamma[cover];
}
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);
unsigned cover = 0;
//--------------------------------------------------------------------
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)))
while (num_cells)
{
add_vertex(x, y, cmd);
}
}
const cell_aa* cur_cell = *cells;
int x = cur_cell->x;
int area = cur_cell->area;
unsigned alpha;
//--------------------------------------------------------------------
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(); }
cover += cur_cell->cover;
//--------------------------------------------------------------------
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)
// accumulate all cells with the same X
while (--num_cells)
{
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);
unsigned cover = 0;
while(num_cells)
{
const cell_aa* cur_cell = *cells;
int x = cur_cell->x;
int area = cur_cell->area;
unsigned alpha;
cur_cell = *++cells;
if (cur_cell->x != x)
break;
area += cur_cell->area;
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;
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);
}
}
}
sl.finalize(m_scan_y);
if (sl.num_spans())
break;
++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();
sl.finalize(m_scan_y);
++m_scan_y;
return true;
}
//--------------------------------------------------------------------
bool hit_test(int tx, int ty);
//------------------------------------------------------------------------
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();
}
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();
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -17,226 +17,201 @@
#include "agg_clip_liang_barsky.h"
namespace agg
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
{
//--------------------------------------------------------poly_max_coord_e
enum poly_max_coord_e
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)
{
poly_max_coord = (1 << 30) - 1 //----poly_max_coord
};
//------------------------------------------------------------ras_conv_int
struct ras_conv_int
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)
{
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; }
};
m_clip_box = rect_type(x1, y1, x2, y2);
m_clip_box.normalize();
m_clipping = true;
}
//--------------------------------------------------------ras_conv_int_sat
struct ras_conv_int_sat
//--------------------------------------------------------------------
void move_to(coord_type x1, coord_type y1)
{
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; }
};
m_x1 = x1;
m_y1 = y1;
if (m_clipping)
m_f1 = clipping_flags(x1, y1, m_clip_box);
}
//---------------------------------------------------------ras_conv_int_3x
struct ras_conv_int_3x
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
{
typedef int coord_type;
static AGG_INLINE int mul_div(double a, double b, double c)
f1 &= 10;
f2 &= 10;
if ((f1 | f2) == 0)
{
return iround(a * b / c);
// Fully visible
ras.line(Conv::xi(x1), Conv::yi(y1), Conv::xi(x2), Conv::yi(y2));
}
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)
else
{
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)
if (f1 == f2)
{
// Fully visible
ras.line(Conv::xi(x1), Conv::yi(y1), Conv::xi(x2), Conv::yi(y2));
// Invisible by Y
return;
}
else
coord_type tx1 = x1;
coord_type ty1 = y1;
coord_type tx2 = x2;
coord_type ty2 = y2;
if (f1 & 8) // y1 < clip.y1
{
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));
tx1 = x1 + Conv::mul_div(m_clip_box.y1 - y1, x2 - x1, y2 - y1);
ty1 = m_clip_box.y1;
}
}
public:
//--------------------------------------------------------------------
template<class Rasterizer>
void line_to(Rasterizer& ras, coord_type x2, coord_type y2)
{
if(m_clipping)
if (f1 & 2) // y1 > clip.y2
{
unsigned f2 = clipping_flags(x2, y2, m_clip_box);
tx1 = x1 + Conv::mul_div(m_clip_box.y2 - y1, x2 - x1, y2 - y1);
ty1 = m_clip_box.y2;
}
if((m_f1 & 10) == (f2 & 10) && (m_f1 & 10) != 0)
{
// Invisible by Y
m_x1 = x2;
m_y1 = y2;
m_f1 = f2;
return;
}
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;
}
coord_type x1 = m_x1;
coord_type y1 = m_y1;
unsigned f1 = m_f1;
coord_type y3, y4;
unsigned f3, f4;
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));
}
}
switch(((f1 & 5) << 1) | (f2 & 5))
{
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);
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);
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);
@ -247,15 +222,15 @@ namespace agg
break;
case 4: // x2 < clip.x1
y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-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);
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);
@ -264,15 +239,15 @@ namespace agg
break;
case 8: // x1 < clip.x1
y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-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);
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);
@ -283,69 +258,69 @@ namespace agg
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;
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;
};
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)
{}
//---------------------------------------------------rasterizer_sl_no_clip
class rasterizer_sl_no_clip
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)
{
public:
typedef ras_conv_int conv_type;
typedef int coord_type;
m_x1 = x1;
m_y1 = y1;
}
rasterizer_sl_no_clip() : m_x1(0), m_y1(0) {}
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;
}
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; }
private:
int m_x1, m_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;
}
// -----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;
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;
}
} // namespace agg
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -24,326 +24,303 @@
#include "agg_array.h"
#include "agg_renderer_base.h"
namespace agg
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;
//----------------------------------------------------------renderer_mclip
template<class PixelFormat> class renderer_mclip
//--------------------------------------------------------------------
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)
{
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;
m_ren.attach(pixf);
reset_clipping(true);
}
//--------------------------------------------------------------------
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)
//--------------------------------------------------------------------
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())
{
m_ren.attach(pixf);
reset_clipping(true);
const rect_i& cb = m_clip[0];
m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2);
}
//--------------------------------------------------------------------
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()
//--------------------------------------------------------------------
bool next_clip_box()
{
if (++m_curr_cb < m_clip.size())
{
m_curr_cb = 0;
if(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))
{
const rect_i& cb = m_clip[0];
m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2);
m_ren.ren().copy_pixel(x, y, c);
break;
}
}
} while (next_clip_box());
}
//--------------------------------------------------------------------
bool next_clip_box()
{
if(++m_curr_cb < m_clip.size())
//--------------------------------------------------------------------
void blend_pixel(int x, int y, const color_type& c, cover_type cover)
{
first_clip_box();
do
{
if (m_ren.inbox(x, y))
{
const rect_i& cb = m_clip[m_curr_cb];
m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2);
return true;
m_ren.ren().blend_pixel(x, y, c, cover);
break;
}
return false;
}
} while (next_clip_box());
}
//--------------------------------------------------------------------
void reset_clipping(bool visibility)
//--------------------------------------------------------------------
color_type pixel(int x, int y) const
{
first_clip_box();
do
{
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)))
if (m_ren.inbox(x, y))
{
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;
return m_ren.ren().pixel(x, y);
}
}
} while (next_clip_box());
return color_type::no_color();
}
//--------------------------------------------------------------------
void clear(const color_type& c)
//--------------------------------------------------------------------
void copy_hline(int x1, int y, int x2, const color_type& c)
{
first_clip_box();
do
{
m_ren.clear(c);
}
//--------------------------------------------------------------------
void copy_pixel(int x, int y, const color_type& c)
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
{
first_clip_box();
do
{
if(m_ren.inbox(x, y))
{
m_ren.ren().copy_pixel(x, y, c);
break;
}
}
while(next_clip_box());
}
m_ren.copy_vline(x, y1, y2, c);
} while (next_clip_box());
}
//--------------------------------------------------------------------
void blend_pixel(int x, int y, const color_type& c, cover_type cover)
//--------------------------------------------------------------------
void blend_hline(int x1, int y, int x2, const color_type& c, cover_type cover)
{
first_clip_box();
do
{
first_clip_box();
do
{
if(m_ren.inbox(x, y))
{
m_ren.ren().blend_pixel(x, y, c, cover);
break;
}
}
while(next_clip_box());
}
m_ren.blend_hline(x1, y, x2, c, cover);
} while (next_clip_box());
}
//--------------------------------------------------------------------
color_type pixel(int x, int y) const
//--------------------------------------------------------------------
void blend_vline(int x, int y1, int y2, const color_type& c, cover_type cover)
{
first_clip_box();
do
{
first_clip_box();
do
{
if(m_ren.inbox(x, y))
{
return m_ren.ren().pixel(x, y);
}
}
while(next_clip_box());
return color_type::no_color();
}
m_ren.blend_vline(x, y1, y2, c, cover);
} while (next_clip_box());
}
//--------------------------------------------------------------------
void copy_hline(int x1, int y, int x2, const color_type& c)
//--------------------------------------------------------------------
void copy_bar(int x1, int y1, int x2, int y2, const color_type& c)
{
first_clip_box();
do
{
first_clip_box();
do
{
m_ren.copy_hline(x1, y, x2, c);
}
while(next_clip_box());
}
m_ren.copy_bar(x1, y1, x2, y2, c);
} while (next_clip_box());
}
//--------------------------------------------------------------------
void copy_vline(int x, int y1, int y2, const color_type& c)
//--------------------------------------------------------------------
void blend_bar(int x1, int y1, int x2, int y2, const color_type& c, cover_type cover)
{
first_clip_box();
do
{
first_clip_box();
do
{
m_ren.copy_vline(x, y1, y2, c);
}
while(next_clip_box());
}
m_ren.blend_bar(x1, y1, x2, y2, c, cover);
} while (next_clip_box());
}
//--------------------------------------------------------------------
void blend_hline(int x1, int y, int x2,
const color_type& c, cover_type cover)
//--------------------------------------------------------------------
void blend_solid_hspan(int x, int y, int len, const color_type& c, const cover_type* covers)
{
first_clip_box();
do
{
first_clip_box();
do
{
m_ren.blend_hline(x1, y, x2, c, cover);
}
while(next_clip_box());
}
m_ren.blend_solid_hspan(x, y, len, c, covers);
} while (next_clip_box());
}
//--------------------------------------------------------------------
void blend_vline(int x, int y1, int y2,
const color_type& c, cover_type cover)
//--------------------------------------------------------------------
void blend_solid_vspan(int x, int y, int len, const color_type& c, const cover_type* covers)
{
first_clip_box();
do
{
first_clip_box();
do
{
m_ren.blend_vline(x, y1, y2, c, cover);
}
while(next_clip_box());
}
m_ren.blend_solid_vspan(x, y, len, c, covers);
} while (next_clip_box());
}
//--------------------------------------------------------------------
void copy_bar(int x1, int y1, int x2, int y2, const color_type& c)
//--------------------------------------------------------------------
void copy_color_hspan(int x, int y, int len, const color_type* colors)
{
first_clip_box();
do
{
first_clip_box();
do
{
m_ren.copy_bar(x1, y1, x2, y2, c);
}
while(next_clip_box());
}
m_ren.copy_color_hspan(x, y, len, colors);
} while (next_clip_box());
}
//--------------------------------------------------------------------
void blend_bar(int x1, int y1, int x2, int y2,
const color_type& c, cover_type cover)
//--------------------------------------------------------------------
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
{
first_clip_box();
do
{
m_ren.blend_bar(x1, y1, x2, y2, c, cover);
}
while(next_clip_box());
}
m_ren.blend_color_hspan(x, y, len, colors, covers, cover);
} while (next_clip_box());
}
//--------------------------------------------------------------------
void blend_solid_hspan(int x, int y, int len,
const color_type& c, const cover_type* covers)
//--------------------------------------------------------------------
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
{
first_clip_box();
do
{
m_ren.blend_solid_hspan(x, y, len, c, covers);
}
while(next_clip_box());
}
m_ren.blend_color_vspan(x, y, len, colors, covers, cover);
} while (next_clip_box());
}
//--------------------------------------------------------------------
void blend_solid_vspan(int x, int y, int len,
const color_type& c, const cover_type* covers)
//--------------------------------------------------------------------
void copy_from(const rendering_buffer& from, const rect_i* rc = 0, int x_to = 0, int y_to = 0)
{
first_clip_box();
do
{
first_clip_box();
do
{
m_ren.blend_solid_vspan(x, y, len, c, covers);
}
while(next_clip_box());
}
m_ren.copy_from(from, rc, x_to, y_to);
} while (next_clip_box());
}
//--------------------------------------------------------------------
void copy_color_hspan(int x, int y, int len, const color_type* colors)
//--------------------------------------------------------------------
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
{
first_clip_box();
do
{
m_ren.copy_color_hspan(x, y, len, colors);
}
while(next_clip_box());
}
m_ren.blend_from(src, rect_src_ptr, dx, dy, cover);
} 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());
}
private:
renderer_mclip(const renderer_mclip<PixelFormat>&);
const renderer_mclip<PixelFormat>& operator=(const renderer_mclip<PixelFormat>&);
//--------------------------------------------------------------------
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());
}
base_ren_type m_ren;
pod_bvector<rect_i, 4> m_clip;
unsigned m_curr_cb;
rect_i m_bounds;
};
//--------------------------------------------------------------------
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;
};
}
} // namespace agg
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -25,200 +25,190 @@
#include "agg_dda_line.h"
#include "agg_ellipse_bresenham.h"
namespace agg
namespace agg {
//-----------------------------------------------------renderer_primitives
template<class BaseRenderer>
class renderer_primitives
{
//-----------------------------------------------------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)
{
public:
typedef BaseRenderer base_ren_type;
typedef typename base_ren_type::color_type color_type;
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);
}
//--------------------------------------------------------------------
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; }
//--------------------------------------------------------------------
void solid_rectangle(int x1, int y1, int x2, int y2) { m_ren->blend_bar(x1, y1, x2, y2, m_fill_color, cover_full); }
//--------------------------------------------------------------------
static int coord(double c)
{
return iround(c * line_bresenham_interpolator::subpixel_scale);
//--------------------------------------------------------------------
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;
}
//--------------------------------------------------------------------
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; }
if (last)
++len;
//--------------------------------------------------------------------
void rectangle(int x1, int y1, int x2, int y2)
if (li.is_ver())
{
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);
m_ren->blend_pixel(li.x2(), li.y1(), m_line_color, cover_full);
li.vstep();
} while (--len);
}
//--------------------------------------------------------------------
void solid_ellipse(int x, int y, int rx, int ry)
else
{
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);
m_ren->blend_pixel(li.x1(), li.y2(), m_line_color, cover_full);
li.hstep();
} while (--len);
}
}
//--------------------------------------------------------------------
void outlined_ellipse(int x, int y, int rx, int ry)
{
ellipse_bresenham_interpolator ei(rx, ry);
int dx = 0;
int dy = -ry;
//--------------------------------------------------------------------
void move_to(int x, int y)
{
m_curr_x = x;
m_curr_y = y;
}
do
{
dx += ei.dx();
dy += ei.dy();
//--------------------------------------------------------------------
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;
}
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);
//--------------------------------------------------------------------
const base_ren_type& ren() const { return *m_ren; }
base_ren_type& ren() { return *m_ren; }
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);
}
//--------------------------------------------------------------------
const rendering_buffer& rbuf() const { return m_ren->rbuf(); }
rendering_buffer& rbuf() { return m_ren->rbuf(); }
//--------------------------------------------------------------------
void line(int x1, int y1, int x2, int y2, bool last=false)
{
line_bresenham_interpolator li(x1, y1, x2, y2);
private:
base_ren_type* m_ren;
color_type m_fill_color;
color_type m_line_color;
int m_curr_x;
int m_curr_y;
};
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;
};
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -18,247 +18,215 @@
#include "agg_basics.h"
namespace agg
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
template<class BaseRenderer, class GlyphGenerator>
class renderer_raster_htext_solid
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)
{
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)
{
glyph_rect r;
while(*str)
m_glyph->prepare(&r, x, y, *str, flip);
if (r.x2 >= r.x1)
{
m_glyph->prepare(&r, x, y, *str, flip);
if(r.x2 >= r.x1)
int i;
if (flip)
{
int i;
if(flip)
for (i = r.y1; i <= r.y2; i++)
{
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));
}
m_ren->blend_solid_hspan(r.x1, i, (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_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)
else
{
int i;
if(flip)
for (i = r.y1; i <= r.y2; i++)
{
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));
}
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;
}
x += r.dx;
y += r.dy;
++str;
}
}
private:
ren_type* m_ren;
glyph_gen_type* m_glyph;
color_type m_color;
};
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; }
//===================================================renderer_raster_htext
template<class ScanlineRenderer, class GlyphGenerator>
class renderer_raster_htext
//--------------------------------------------------------------------
template<class CharT>
void render_text(double x, double y, const CharT* str, bool flip = false)
{
public:
typedef ScanlineRenderer ren_type;
typedef GlyphGenerator glyph_gen_type;
typedef typename glyph_gen_type::glyph_rect glyph_rect;
class scanline_single_span
glyph_rect r;
while (*str)
{
public:
typedef agg::cover_type cover_type;
//----------------------------------------------------------------
struct const_span
m_glyph->prepare(&r, x, y, *str, !flip);
if (r.x2 >= r.x1)
{
int x;
unsigned len;
const cover_type* covers;
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;
}
}
const_span() {}
const_span(int x_, unsigned len_, const cover_type* covers_) :
x(x_), len(len_), covers(covers_)
{}
};
private:
ren_type* m_ren;
glyph_gen_type* m_glyph;
color_type m_color;
};
typedef const const_span* const_iterator;
//===================================================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;
//----------------------------------------------------------------
scanline_single_span(int x, int y, unsigned len,
const cover_type* covers) :
m_y(y),
m_span(x, len, covers)
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_)
{}
//----------------------------------------------------------------
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;
};
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)
{}
//--------------------------------------------------------------------
renderer_raster_htext(ren_type& ren, glyph_gen_type& glyph) :
m_ren(&ren),
m_glyph(&glyph)
{
}
//----------------------------------------------------------------
int y() const { return m_y; }
unsigned num_spans() const { return 1; }
const_iterator begin() const { return &m_span; }
//--------------------------------------------------------------------
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;
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;
};
}
} // namespace agg
#endif

File diff suppressed because it is too large Load diff

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -22,284 +22,261 @@
#include "agg_array.h"
namespace agg
namespace agg {
//===========================================================row_accessor
template<class T>
class row_accessor
{
public:
typedef const_row_info<T> row_data;
//===========================================================row_accessor
template<class T> class row_accessor
//-------------------------------------------------------------------
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)
{
public:
typedef const_row_info<T> row_data;
attach(buf, width, height, stride);
}
//-------------------------------------------------------------------
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 rendering 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
//--------------------------------------------------------------------
void attach(T* buf, unsigned width, unsigned height, int stride)
{
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)
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;
}
}
//--------------------------------------------------------------------
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)
//--------------------------------------------------------------------
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++)
{
attach(buf, width, height, stride);
memcpy(row_ptr(0, y, w), src.row_ptr(y), l);
}
}
//--------------------------------------------------------------------
void attach(T* buf, unsigned width, unsigned height, int stride)
//--------------------------------------------------------------------
void clear(T value)
{
unsigned y;
unsigned w = width();
unsigned stride = stride_abs();
for (y = 0; y < height(); y++)
{
m_buf = buf;
m_width = width;
m_height = height;
m_stride = stride;
if(height > m_rows.size())
T* p = row_ptr(0, y, w);
unsigned x;
for (x = 0; x < stride; x++)
{
m_rows.resize(height);
}
else if(height == 0)
{
return;
}
T* row_ptr = m_buf;
if(stride < 0)
{
row_ptr = m_buf - int(height - 1) * stride;
}
T** rows = &m_rows[0];
while(height > 0)
{
*rows++ = row_ptr;
row_ptr += stride;
--height;
*p++ = value;
}
}
}
//--------------------------------------------------------------------
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
private:
//--------------------------------------------------------------------
T* m_buf; // Pointer to rendering 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())
{
return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride);
m_rows.resize(height);
}
//--------------------------------------------------------------------
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)
else if (height == 0)
{
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);
return;
}
unsigned y;
unsigned w = width();
for (y = 0; y < h; y++)
T* row_ptr = m_buf;
if (stride < 0)
{
row_ptr = m_buf - int(height - 1) * stride;
}
T** rows = &m_rows[0];
while (height > 0)
{
*rows++ = row_ptr;
row_ptr += stride;
--height;
}
}
//--------------------------------------------------------------------
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++)
{
memcpy(row_ptr(0, y, w), src.row_ptr(y), l);
*p++ = value;
}
}
}
//--------------------------------------------------------------------
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 rendering 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
};
private:
//--------------------------------------------------------------------
T* m_buf; // Pointer to rendering 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
//------------------------------------------------------------------------
//========================================================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;
typedef AGG_RENDERING_BUFFER rendering_buffer;
#else
typedef row_ptr_cache<int8u> rendering_buffer;
//typedef row_accessor<int8u> rendering_buffer;
typedef row_ptr_cache<int8u> rendering_buffer;
// typedef row_accessor<int8u> rendering_buffer;
#endif
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -22,116 +22,114 @@
#include "agg_array.h"
namespace agg
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
// 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
//-------------------------------------------------------------------
~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)
{
public:
typedef row_info<int8u> row_data;
memset(&m_rows[0], 0, sizeof(row_data) * height);
}
//-------------------------------------------------------------------
~rendering_buffer_dynarow()
// Allocate and clear the buffer
//--------------------------------------------------------------------
void init(unsigned width, unsigned height, unsigned byte_width)
{
unsigned i;
for (i = 0; i < m_height; ++i)
{
init(0,0,0);
pod_allocator<int8u>::deallocate((int8u*)m_rows[i].ptr, m_byte_width);
}
//-------------------------------------------------------------------
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)
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);
}
}
// Allocate and clear the buffer
//--------------------------------------------------------------------
void init(unsigned width, unsigned height, unsigned byte_width)
//--------------------------------------------------------------------
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)
{
unsigned i;
for(i = 0; i < m_height; ++i)
if (x < r->x1)
{
pod_allocator<int8u>::deallocate((int8u*)m_rows[i].ptr, m_byte_width);
r->x1 = x;
}
if(width && height)
if (x2 > r->x2)
{
m_width = width;
m_height = height;
m_byte_width = byte_width;
m_rows.resize(height);
memset(&m_rows[0], 0, sizeof(row_data) * height);
r->x2 = x2;
}
}
//--------------------------------------------------------------------
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)
else
{
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;
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]; }
//--------------------------------------------------------------------
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:
//--------------------------------------------------------------------
// 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
};
}
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
};
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -23,50 +23,47 @@
#include "agg_basics.h"
#include "agg_arc.h"
namespace agg
namespace agg {
//------------------------------------------------------------rounded_rect
//
// See Implemantation agg_rounded_rect.cpp
//
class rounded_rect
{
//------------------------------------------------------------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);
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 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 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);
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;
};
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;
};
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -17,12 +17,12 @@
//
//----------------------------------------------------------------------------
//
// Adaptation for 32-bit screen coordinates (scanline32_bin) has been sponsored by
// 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
@ -30,235 +30,215 @@
#include "agg_array.h"
namespace agg
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;
//=============================================================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
struct span
{
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;
int16 x;
int16 len;
};
typedef const span* const_iterator;
//--------------------------------------------------------------------
scanline_bin()
: m_last_x(0x7FFFFFF0)
, m_spans()
, m_cur_span(0)
{}
//===========================================================scanline32_bin
class scanline32_bin
//--------------------------------------------------------------------
void reset(int min_x, int max_x)
{
public:
typedef int32 coord_type;
//--------------------------------------------------------------------
struct span
unsigned max_len = max_x - min_x + 3;
if (max_len > m_spans.size())
{
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, int)
{
m_last_x = 0x7FFFFFF0;
m_spans.remove_all();
m_spans.resize(max_len);
}
m_last_x = 0x7FFFFFF0;
m_cur_span = &m_spans[0];
}
//--------------------------------------------------------------------
void add_cell(int x, unsigned)
//--------------------------------------------------------------------
void add_cell(int x, unsigned)
{
if (x == m_last_x + 1)
{
if(x == m_last_x+1)
{
m_spans.last().len++;
}
else
{
m_spans.add(span(coord_type(x), 1));
}
m_last_x = x;
m_cur_span->len++;
}
//--------------------------------------------------------------------
void add_span(int x, unsigned len, unsigned)
else
{
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;
++m_cur_span;
m_cur_span->x = (int16)x;
m_cur_span->len = 1;
}
m_last_x = x;
}
//--------------------------------------------------------------------
void add_cells(int x, unsigned len, const void*)
//--------------------------------------------------------------------
void add_span(int x, unsigned len, unsigned)
{
if (x == m_last_x + 1)
{
add_span(x, len, 0);
m_cur_span->len = (int16)(m_cur_span->len + len);
}
//--------------------------------------------------------------------
void finalize(int y)
{
m_y = y;
}
//--------------------------------------------------------------------
void reset_spans()
else
{
m_last_x = 0x7FFFFFF0;
m_spans.remove_all();
++m_cur_span;
m_cur_span->x = (int16)x;
m_cur_span->len = (int16)len;
}
m_last_x = x + len - 1;
}
//--------------------------------------------------------------------
int y() const { return m_y; }
unsigned num_spans() const { return m_spans.size(); }
const_iterator begin() const { return const_iterator(m_spans); }
//--------------------------------------------------------------------
void add_cells(int x, unsigned len, const void*) { add_span(x, len, 0); }
private:
scanline32_bin(const scanline32_bin&);
const scanline32_bin operator = (const scanline32_bin&);
//--------------------------------------------------------------------
void finalize(int y) { m_y = y; }
unsigned m_max_len;
int m_last_x;
int m_y;
span_array_type m_spans;
//--------------------------------------------------------------------
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, int)
{
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;
};
} // namespace agg
#endif

File diff suppressed because it is too large Load diff

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -17,313 +17,291 @@
//
//----------------------------------------------------------------------------
//
// Adaptation for 32-bit screen coordinates (scanline32_p) has been sponsored by
// 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
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;
//=============================================================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
//--------------------------------------------------------------------
struct span
{
public:
typedef scanline_p8 self_type;
typedef int8u cover_type;
typedef int16 coord_type;
coord_type x;
coord_type len; // If negative, it's a solid span, covers is valid
const cover_type* covers;
};
//--------------------------------------------------------------------
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)
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 reset(int min_x, int max_x)
//--------------------------------------------------------------------
void add_cell(int x, unsigned cover)
{
*m_cover_ptr = (cover_type)cover;
if (x == m_last_x + 1 && m_cur_span->len > 0)
{
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;
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_cell(int x, unsigned cover)
//--------------------------------------------------------------------
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;
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++;
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 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 finalize(int y) { m_y = y; }
//--------------------------------------------------------------------
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 reset_spans()
{
m_last_x = 0x7FFFFFF0;
m_cover_ptr = &m_covers[0];
m_cur_span = &m_spans[0];
m_cur_span->len = 0;
}
//--------------------------------------------------------------------
void finalize(int y)
{
m_y = y;
}
//--------------------------------------------------------------------
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]; }
//--------------------------------------------------------------------
void reset_spans()
{
m_last_x = 0x7FFFFFF0;
m_cover_ptr = &m_covers[0];
m_cur_span = &m_spans[0];
m_cur_span->len = 0;
}
private:
scanline_p8(const self_type&);
const self_type& operator=(const self_type&);
//--------------------------------------------------------------------
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]; }
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;
};
private:
scanline_p8(const self_type&);
const self_type& operator = (const self_type&);
//==========================================================scanline32_p8
class scanline32_p8
{
public:
typedef scanline32_p8 self_type;
typedef int8u cover_type;
typedef int32 coord_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;
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)
{}
//==========================================================scanline32_p8
class scanline32_p8
//--------------------------------------------------------------------
void reset(int min_x, int max_x)
{
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)
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 reset(int min_x, int max_x)
//--------------------------------------------------------------------
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)
{
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();
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_cell(int x, unsigned cover)
//--------------------------------------------------------------------
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);
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++;
m_spans.add(span(coord_type(x), -coord_type(len), m_cover_ptr++));
}
m_last_x = x + len - 1;
}
//--------------------------------------------------------------------
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 finalize(int y) { m_y = y; }
//--------------------------------------------------------------------
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 reset_spans()
{
m_last_x = 0x7FFFFFF0;
m_cover_ptr = &m_covers[0];
m_spans.remove_all();
}
//--------------------------------------------------------------------
void finalize(int y)
{
m_y = y;
}
//--------------------------------------------------------------------
int y() const { return m_y; }
unsigned num_spans() const { return m_spans.size(); }
const_iterator begin() const { return const_iterator(m_spans); }
//--------------------------------------------------------------------
void reset_spans()
{
m_last_x = 0x7FFFFFF0;
m_cover_ptr = &m_covers[0];
m_spans.remove_all();
}
private:
scanline32_p8(const self_type&);
const self_type& operator=(const self_type&);
//--------------------------------------------------------------------
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;
};
}
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;
};
} // namespace agg
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -13,12 +13,12 @@
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Adaptation for 32-bit screen coordinates (scanline32_u) has been sponsored by
// 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
@ -26,475 +26,456 @@
#include "agg_array.h"
namespace agg
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
{
//=============================================================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
{
public:
typedef scanline_u8 self_type;
typedef int8u cover_type;
typedef int16 coord_type;
coord_type x;
coord_type len;
cover_type* covers;
};
//--------------------------------------------------------------------
struct span
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())
{
coord_type x;
coord_type len;
cover_type* covers;
};
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];
}
typedef span* iterator;
typedef const span* const_iterator;
//--------------------------------------------------------------------
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;
}
//--------------------------------------------------------------------
scanline_u8() :
m_min_x(0),
m_last_x(0x7FFFFFF0),
m_cur_span(0)
//--------------------------------------------------------------------
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_)
{}
//--------------------------------------------------------------------
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;
coord_type x;
coord_type len;
cover_type* covers;
};
typedef pod_bvector<span, 4> span_array_type;
//==========================================================scanline_u8_am
//
// The scanline container with alpha-masking
//
//------------------------------------------------------------------------
template<class AlphaMask>
class scanline_u8_am : public scanline_u8
//--------------------------------------------------------------------
class const_iterator
{
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()
public:
const_iterator(const span_array_type& spans)
: m_spans(spans)
, m_span_idx(0)
{}
//--------------------------------------------------------------------
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();
}
const span& operator*() const { return m_spans[m_span_idx]; }
const span* operator->() const { return &m_spans[m_span_idx]; }
//--------------------------------------------------------------------
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 operator++() { ++m_span_idx; }
//--------------------------------------------------------------------
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;
private:
const span_array_type& m_spans;
unsigned m_span_idx;
};
//========================================================scanline32_u8_am
//
// The scanline container with alpha-masking
//
//------------------------------------------------------------------------
template<class AlphaMask>
class scanline32_u8_am : public scanline32_u8
//--------------------------------------------------------------------
class iterator
{
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;
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]; }
scanline32_u8_am() : base_type(), m_alpha_mask(0) {}
scanline32_u8_am(const AlphaMask& am) : base_type(), m_alpha_mask(&am) {}
void operator++() { ++m_span_idx; }
//--------------------------------------------------------------------
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;
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;
};
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -19,48 +19,48 @@
#include "agg_basics.h"
#include "agg_vertex_sequence.h"
namespace agg
namespace agg {
//===========================================================shorten_path
template<class VertexSequence>
void shorten_path(VertexSequence& vs, double s, unsigned closed = 0)
{
typedef typename VertexSequence::value_type vertex_type;
//===========================================================shorten_path
template<class VertexSequence>
void shorten_path(VertexSequence& vs, double s, unsigned closed = 0)
if (s > 0.0 && vs.size() > 1)
{
typedef typename VertexSequence::value_type vertex_type;
if(s > 0.0 && vs.size() > 1)
double d;
int n = int(vs.size() - 2);
while (n)
{
double d;
int n = int(vs.size() - 2);
while(n)
{
d = vs[n].dist;
if(d > s) break;
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();
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);
}
vs.close(closed != 0);
}
}
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -22,126 +22,119 @@
#include <cmath>
#include "agg_basics.h"
namespace agg
namespace agg {
//=============================================================swap_arrays
template<class T>
void swap_arrays(T* a1, T* a2, unsigned n)
{
//=============================================================swap_arrays
template<class T> void swap_arrays(T* a1, T* a2, unsigned n)
unsigned i;
for (i = 0; i < n; i++)
{
unsigned i;
for(i = 0; i < n; i++)
{
T tmp = *a1;
*a1++ = *a2;
*a2++ = tmp;
}
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 = std::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;
}
};
}
//============================================================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 = std::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;
}
};
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -18,37 +18,34 @@
#include "agg_array.h"
namespace agg
namespace agg {
//----------------------------------------------------------span_allocator
template<class ColorT>
class span_allocator
{
//----------------------------------------------------------span_allocator
template<class ColorT> class span_allocator
public:
typedef ColorT color_type;
//--------------------------------------------------------------------
AGG_INLINE color_type* allocate(unsigned span_len)
{
public:
typedef ColorT color_type;
//--------------------------------------------------------------------
AGG_INLINE color_type* allocate(unsigned span_len)
if (span_len > m_span.size())
{
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];
// 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;
};
}
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;
};
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -18,39 +18,41 @@
#include "agg_basics.h"
namespace agg
namespace agg {
//----------------------------------------------------------span_converter
template<class SpanGenerator, class SpanConverter>
class span_converter
{
//----------------------------------------------------------span_converter
template<class SpanGenerator, class SpanConverter> class span_converter
public:
typedef typename SpanGenerator::color_type color_type;
span_converter(SpanGenerator& span_gen, SpanConverter& span_cnv)
: m_span_gen(&span_gen)
, m_span_cnv(&span_cnv)
{}
void attach_generator(SpanGenerator& span_gen) { m_span_gen = &span_gen; }
void attach_converter(SpanConverter& span_cnv) { m_span_cnv = &span_cnv; }
//--------------------------------------------------------------------
void prepare()
{
public:
typedef typename SpanGenerator::color_type color_type;
m_span_gen->prepare();
m_span_cnv->prepare();
}
span_converter(SpanGenerator& span_gen, SpanConverter& span_cnv) :
m_span_gen(&span_gen), m_span_cnv(&span_cnv) {}
//--------------------------------------------------------------------
void generate(color_type* span, int x, int y, unsigned len)
{
m_span_gen->generate(span, x, y, len);
m_span_cnv->generate(span, x, y, len);
}
void attach_generator(SpanGenerator& span_gen) { m_span_gen = &span_gen; }
void attach_converter(SpanConverter& span_cnv) { m_span_cnv = &span_cnv; }
private:
SpanGenerator* m_span_gen;
SpanConverter* m_span_cnv;
};
//--------------------------------------------------------------------
void prepare()
{
m_span_gen->prepare();
m_span_cnv->prepare();
}
//--------------------------------------------------------------------
void generate(color_type* span, int x, int y, unsigned len)
{
m_span_gen->generate(span, x, y, len);
m_span_cnv->generate(span, x, y, len);
}
private:
SpanGenerator* m_span_gen;
SpanConverter* m_span_cnv;
};
}
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -19,154 +19,176 @@
#include "agg_basics.h"
#include "agg_math.h"
namespace agg
namespace agg {
//============================================================span_gouraud
template<class ColorT>
class span_gouraud
{
public:
typedef ColorT color_type;
//============================================================span_gouraud
template<class ColorT> class span_gouraud
struct coord_type
{
public:
typedef ColorT color_type;
struct coord_type
{
double x;
double y;
color_type color;
};
//--------------------------------------------------------------------
span_gouraud() :
m_vertex(0)
{
m_cmd[0] = path_cmd_stop;
}
//--------------------------------------------------------------------
span_gouraud(const color_type& c1,
const color_type& c2,
const color_type& c3,
double x1, double y1,
double x2, double y2,
double x3, double y3,
double d) :
m_vertex(0)
{
colors(c1, c2, c3);
triangle(x1, y1, x2, y2, x3, y3, d);
}
//--------------------------------------------------------------------
void colors(ColorT c1, ColorT c2, ColorT c3)
{
m_coord[0].color = c1;
m_coord[1].color = c2;
m_coord[2].color = c3;
}
//--------------------------------------------------------------------
// Sets the triangle and dilates it if needed.
// The trick here is to calculate beveled joins in the vertices of the
// triangle and render it as a 6-vertex polygon.
// It's necessary to achieve numerical stability.
// However, the coordinates to interpolate colors are calculated
// as miter joins (calc_intersection).
void triangle(double x1, double y1,
double x2, double y2,
double x3, double y3,
double d)
{
m_coord[0].x = m_x[0] = x1;
m_coord[0].y = m_y[0] = y1;
m_coord[1].x = m_x[1] = x2;
m_coord[1].y = m_y[1] = y2;
m_coord[2].x = m_x[2] = x3;
m_coord[2].y = m_y[2] = y3;
m_cmd[0] = path_cmd_move_to;
m_cmd[1] = path_cmd_line_to;
m_cmd[2] = path_cmd_line_to;
m_cmd[3] = path_cmd_stop;
if(d != 0.0)
{
dilate_triangle(m_coord[0].x, m_coord[0].y,
m_coord[1].x, m_coord[1].y,
m_coord[2].x, m_coord[2].y,
m_x, m_y, d);
calc_intersection(m_x[4], m_y[4], m_x[5], m_y[5],
m_x[0], m_y[0], m_x[1], m_y[1],
&m_coord[0].x, &m_coord[0].y);
calc_intersection(m_x[0], m_y[0], m_x[1], m_y[1],
m_x[2], m_y[2], m_x[3], m_y[3],
&m_coord[1].x, &m_coord[1].y);
calc_intersection(m_x[2], m_y[2], m_x[3], m_y[3],
m_x[4], m_y[4], m_x[5], m_y[5],
&m_coord[2].x, &m_coord[2].y);
m_cmd[3] = path_cmd_line_to;
m_cmd[4] = path_cmd_line_to;
m_cmd[5] = path_cmd_line_to;
m_cmd[6] = path_cmd_stop;
}
}
//--------------------------------------------------------------------
// Vertex Source Interface to feed the coordinates to the rasterizer
void rewind(unsigned)
{
m_vertex = 0;
}
//--------------------------------------------------------------------
unsigned vertex(double* x, double* y)
{
*x = m_x[m_vertex];
*y = m_y[m_vertex];
return m_cmd[m_vertex++];
}
protected:
//--------------------------------------------------------------------
void arrange_vertices(coord_type* coord) const
{
coord[0] = m_coord[0];
coord[1] = m_coord[1];
coord[2] = m_coord[2];
if(m_coord[0].y > m_coord[2].y)
{
coord[0] = m_coord[2];
coord[2] = m_coord[0];
}
coord_type tmp;
if(coord[0].y > coord[1].y)
{
tmp = coord[1];
coord[1] = coord[0];
coord[0] = tmp;
}
if(coord[1].y > coord[2].y)
{
tmp = coord[2];
coord[2] = coord[1];
coord[1] = tmp;
}
}
private:
//--------------------------------------------------------------------
coord_type m_coord[3];
double m_x[8];
double m_y[8];
unsigned m_cmd[8];
unsigned m_vertex;
double x;
double y;
color_type color;
};
}
//--------------------------------------------------------------------
span_gouraud()
: m_vertex(0)
{
m_cmd[0] = path_cmd_stop;
}
//--------------------------------------------------------------------
span_gouraud(const color_type& c1,
const color_type& c2,
const color_type& c3,
double x1,
double y1,
double x2,
double y2,
double x3,
double y3,
double d)
: m_vertex(0)
{
colors(c1, c2, c3);
triangle(x1, y1, x2, y2, x3, y3, d);
}
//--------------------------------------------------------------------
void colors(ColorT c1, ColorT c2, ColorT c3)
{
m_coord[0].color = c1;
m_coord[1].color = c2;
m_coord[2].color = c3;
}
//--------------------------------------------------------------------
// Sets the triangle and dilates it if needed.
// The trick here is to calculate beveled joins in the vertices of the
// triangle and render it as a 6-vertex polygon.
// It's necessary to achieve numerical stability.
// However, the coordinates to interpolate colors are calculated
// as miter joins (calc_intersection).
void triangle(double x1, double y1, double x2, double y2, double x3, double y3, double d)
{
m_coord[0].x = m_x[0] = x1;
m_coord[0].y = m_y[0] = y1;
m_coord[1].x = m_x[1] = x2;
m_coord[1].y = m_y[1] = y2;
m_coord[2].x = m_x[2] = x3;
m_coord[2].y = m_y[2] = y3;
m_cmd[0] = path_cmd_move_to;
m_cmd[1] = path_cmd_line_to;
m_cmd[2] = path_cmd_line_to;
m_cmd[3] = path_cmd_stop;
if (d != 0.0)
{
dilate_triangle(m_coord[0].x,
m_coord[0].y,
m_coord[1].x,
m_coord[1].y,
m_coord[2].x,
m_coord[2].y,
m_x,
m_y,
d);
calc_intersection(m_x[4],
m_y[4],
m_x[5],
m_y[5],
m_x[0],
m_y[0],
m_x[1],
m_y[1],
&m_coord[0].x,
&m_coord[0].y);
calc_intersection(m_x[0],
m_y[0],
m_x[1],
m_y[1],
m_x[2],
m_y[2],
m_x[3],
m_y[3],
&m_coord[1].x,
&m_coord[1].y);
calc_intersection(m_x[2],
m_y[2],
m_x[3],
m_y[3],
m_x[4],
m_y[4],
m_x[5],
m_y[5],
&m_coord[2].x,
&m_coord[2].y);
m_cmd[3] = path_cmd_line_to;
m_cmd[4] = path_cmd_line_to;
m_cmd[5] = path_cmd_line_to;
m_cmd[6] = path_cmd_stop;
}
}
//--------------------------------------------------------------------
// Vertex Source Interface to feed the coordinates to the rasterizer
void rewind(unsigned) { m_vertex = 0; }
//--------------------------------------------------------------------
unsigned vertex(double* x, double* y)
{
*x = m_x[m_vertex];
*y = m_y[m_vertex];
return m_cmd[m_vertex++];
}
protected:
//--------------------------------------------------------------------
void arrange_vertices(coord_type* coord) const
{
coord[0] = m_coord[0];
coord[1] = m_coord[1];
coord[2] = m_coord[2];
if (m_coord[0].y > m_coord[2].y)
{
coord[0] = m_coord[2];
coord[2] = m_coord[0];
}
coord_type tmp;
if (coord[0].y > coord[1].y)
{
tmp = coord[1];
coord[1] = coord[0];
coord[0] = tmp;
}
if (coord[1].y > coord[2].y)
{
tmp = coord[2];
coord[2] = coord[1];
coord[1] = tmp;
}
}
private:
//--------------------------------------------------------------------
coord_type m_coord[3];
double m_x[8];
double m_y[8];
unsigned m_cmd[8];
unsigned m_vertex;
};
} // namespace agg
#endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4
// 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.
// 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.
//
@ -13,12 +13,12 @@
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Adaptation for high precision colors has been sponsored by
// 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_SPAN_GOURAUD_GRAY_INCLUDED
@ -29,213 +29,222 @@
#include "agg_dda_line.h"
#include "agg_span_gouraud.h"
namespace agg
namespace agg {
//=======================================================span_gouraud_gray
template<class ColorT>
class span_gouraud_gray : public span_gouraud<ColorT>
{
public:
typedef ColorT color_type;
typedef typename color_type::value_type value_type;
typedef span_gouraud<color_type> base_type;
typedef typename base_type::coord_type coord_type;
enum subpixel_scale_e { subpixel_shift = 4, subpixel_scale = 1 << subpixel_shift };
//=======================================================span_gouraud_gray
template<class ColorT> class span_gouraud_gray : public span_gouraud<ColorT>
private:
//--------------------------------------------------------------------
struct gray_calc
{
public:
typedef ColorT color_type;
typedef typename color_type::value_type value_type;
typedef span_gouraud<color_type> base_type;
typedef typename base_type::coord_type coord_type;
enum subpixel_scale_e
{
subpixel_shift = 4,
subpixel_scale = 1 << subpixel_shift
};
private:
//--------------------------------------------------------------------
struct gray_calc
void init(const coord_type& c1, const coord_type& c2)
{
void init(const coord_type& c1, const coord_type& c2)
{
m_x1 = c1.x - 0.5;
m_y1 = c1.y - 0.5;
m_dx = c2.x - c1.x;
double dy = c2.y - c1.y;
m_1dy = (std::fabs(dy) < 1e-10) ? 1e10 : 1.0 / dy;
m_v1 = c1.color.v;
m_a1 = c1.color.a;
m_dv = c2.color.v - m_v1;
m_da = c2.color.a - m_a1;
}
void calc(double y)
{
double k = (y - m_y1) * m_1dy;
if(k < 0.0) k = 0.0;
if(k > 1.0) k = 1.0;
m_v = m_v1 + iround(m_dv * k);
m_a = m_a1 + iround(m_da * k);
m_x = iround((m_x1 + m_dx * k) * subpixel_scale);
}
double m_x1;
double m_y1;
double m_dx;
double m_1dy;
int m_v1;
int m_a1;
int m_dv;
int m_da;
int m_v;
int m_a;
int m_x;
};
public:
//--------------------------------------------------------------------
span_gouraud_gray() {}
span_gouraud_gray(const color_type& c1,
const color_type& c2,
const color_type& c3,
double x1, double y1,
double x2, double y2,
double x3, double y3,
double d = 0) :
base_type(c1, c2, c3, x1, y1, x2, y2, x3, y3, d)
{}
//--------------------------------------------------------------------
void prepare()
{
coord_type coord[3];
base_type::arrange_vertices(coord);
m_y2 = int(coord[1].y);
m_swap = cross_product(coord[0].x, coord[0].y,
coord[2].x, coord[2].y,
coord[1].x, coord[1].y) < 0.0;
m_c1.init(coord[0], coord[2]);
m_c2.init(coord[0], coord[1]);
m_c3.init(coord[1], coord[2]);
m_x1 = c1.x - 0.5;
m_y1 = c1.y - 0.5;
m_dx = c2.x - c1.x;
double dy = c2.y - c1.y;
m_1dy = (std::fabs(dy) < 1e-10) ? 1e10 : 1.0 / dy;
m_v1 = c1.color.v;
m_a1 = c1.color.a;
m_dv = c2.color.v - m_v1;
m_da = c2.color.a - m_a1;
}
//--------------------------------------------------------------------
void generate(color_type* span, int x, int y, unsigned len)
void calc(double y)
{
m_c1.calc(y);
const gray_calc* pc1 = &m_c1;
const gray_calc* pc2 = &m_c2;
if(y < m_y2)
{
// Bottom part of the triangle (first subtriangle)
//-------------------------
m_c2.calc(y + m_c2.m_1dy);
}
else
{
// Upper part (second subtriangle)
//-------------------------
m_c3.calc(y - m_c3.m_1dy);
pc2 = &m_c3;
}
if(m_swap)
{
// It means that the triangle is oriented clockwise,
// so that we need to swap the controlling structures
//-------------------------
const gray_calc* t = pc2;
pc2 = pc1;
pc1 = t;
}
// Get the horizontal length with subpixel accuracy
// and protect it from division by zero
//-------------------------
int nlen = std::abs(pc2->m_x - pc1->m_x);
if(nlen <= 0) nlen = 1;
dda_line_interpolator<14> v(pc1->m_v, pc2->m_v, nlen);
dda_line_interpolator<14> a(pc1->m_a, pc2->m_a, nlen);
// Calculate the starting point of the gradient with subpixel
// accuracy and correct (roll back) the interpolators.
// This operation will also clip the beginning of the span
// if necessary.
//-------------------------
int start = pc1->m_x - (x << subpixel_shift);
v -= start;
a -= start;
nlen += start;
int vv, va;
enum lim_e { lim = color_type::base_mask };
// Beginning part of the span. Since we rolled back the
// interpolators, the color values may have overflow.
// So that, we render the beginning part with checking
// for overflow. It lasts until "start" is positive;
// typically it's 1-2 pixels, but may be more in some cases.
//-------------------------
while(len && start > 0)
{
vv = v.y();
va = a.y();
if(vv < 0) vv = 0; if(vv > lim) vv = lim;
if(va < 0) va = 0; if(va > lim) va = lim;
span->v = (value_type)vv;
span->a = (value_type)va;
v += subpixel_scale;
a += subpixel_scale;
nlen -= subpixel_scale;
start -= subpixel_scale;
++span;
--len;
}
// Middle part, no checking for overflow.
// Actual spans can be longer than the calculated length
// because of anti-aliasing, thus, the interpolators can
// overflow. But while "nlen" is positive we are safe.
//-------------------------
while(len && nlen > 0)
{
span->v = (value_type)v.y();
span->a = (value_type)a.y();
v += subpixel_scale;
a += subpixel_scale;
nlen -= subpixel_scale;
++span;
--len;
}
// Ending part; checking for overflow.
// Typically it's 1-2 pixels, but may be more in some cases.
//-------------------------
while(len)
{
vv = v.y();
va = a.y();
if(vv < 0) vv = 0; if(vv > lim) vv = lim;
if(va < 0) va = 0; if(va > lim) va = lim;
span->v = (value_type)vv;
span->a = (value_type)va;
v += subpixel_scale;
a += subpixel_scale;
++span;
--len;
}
double k = (y - m_y1) * m_1dy;
if (k < 0.0)
k = 0.0;
if (k > 1.0)
k = 1.0;
m_v = m_v1 + iround(m_dv * k);
m_a = m_a1 + iround(m_da * k);
m_x = iround((m_x1 + m_dx * k) * subpixel_scale);
}
private:
bool m_swap;
int m_y2;
gray_calc m_c1;
gray_calc m_c2;
gray_calc m_c3;
double m_x1;
double m_y1;
double m_dx;
double m_1dy;
int m_v1;
int m_a1;
int m_dv;
int m_da;
int m_v;
int m_a;
int m_x;
};
public:
//--------------------------------------------------------------------
span_gouraud_gray() {}
span_gouraud_gray(const color_type& c1,
const color_type& c2,
const color_type& c3,
double x1,
double y1,
double x2,
double y2,
double x3,
double y3,
double d = 0)
: base_type(c1, c2, c3, x1, y1, x2, y2, x3, y3, d)
{}
}
//--------------------------------------------------------------------
void prepare()
{
coord_type coord[3];
base_type::arrange_vertices(coord);
m_y2 = int(coord[1].y);
m_swap = cross_product(coord[0].x, coord[0].y, coord[2].x, coord[2].y, coord[1].x, coord[1].y) < 0.0;
m_c1.init(coord[0], coord[2]);
m_c2.init(coord[0], coord[1]);
m_c3.init(coord[1], coord[2]);
}
//--------------------------------------------------------------------
void generate(color_type* span, int x, int y, unsigned len)
{
m_c1.calc(y);
const gray_calc* pc1 = &m_c1;
const gray_calc* pc2 = &m_c2;
if (y < m_y2)
{
// Bottom part of the triangle (first subtriangle)
//-------------------------
m_c2.calc(y + m_c2.m_1dy);
}
else
{
// Upper part (second subtriangle)
//-------------------------
m_c3.calc(y - m_c3.m_1dy);
pc2 = &m_c3;
}
if (m_swap)
{
// It means that the triangle is oriented clockwise,
// so that we need to swap the controlling structures
//-------------------------
const gray_calc* t = pc2;
pc2 = pc1;
pc1 = t;
}
// Get the horizontal length with subpixel accuracy
// and protect it from division by zero
//-------------------------
int nlen = std::abs(pc2->m_x - pc1->m_x);
if (nlen <= 0)
nlen = 1;
dda_line_interpolator<14> v(pc1->m_v, pc2->m_v, nlen);
dda_line_interpolator<14> a(pc1->m_a, pc2->m_a, nlen);
// Calculate the starting point of the gradient with subpixel
// accuracy and correct (roll back) the interpolators.
// This operation will also clip the beginning of the span
// if necessary.
//-------------------------
int start = pc1->m_x - (x << subpixel_shift);
v -= start;
a -= start;
nlen += start;
int vv, va;
enum lim_e { lim = color_type::base_mask };
// Beginning part of the span. Since we rolled back the
// interpolators, the color values may have overflow.
// So that, we render the beginning part with checking
// for overflow. It lasts until "start" is positive;
// typically it's 1-2 pixels, but may be more in some cases.
//-------------------------
while (len && start > 0)
{
vv = v.y();
va = a.y();
if (vv < 0)
vv = 0;
if (vv > lim)
vv = lim;
if (va < 0)
va = 0;
if (va > lim)
va = lim;
span->v = (value_type)vv;
span->a = (value_type)va;
v += subpixel_scale;
a += subpixel_scale;
nlen -= subpixel_scale;
start -= subpixel_scale;
++span;
--len;
}
// Middle part, no checking for overflow.
// Actual spans can be longer than the calculated length
// because of anti-aliasing, thus, the interpolators can
// overflow. But while "nlen" is positive we are safe.
//-------------------------
while (len && nlen > 0)
{
span->v = (value_type)v.y();
span->a = (value_type)a.y();
v += subpixel_scale;
a += subpixel_scale;
nlen -= subpixel_scale;
++span;
--len;
}
// Ending part; checking for overflow.
// Typically it's 1-2 pixels, but may be more in some cases.
//-------------------------
while (len)
{
vv = v.y();
va = a.y();
if (vv < 0)
vv = 0;
if (vv > lim)
vv = lim;
if (va < 0)
va = 0;
if (va > lim)
va = lim;
span->v = (value_type)vv;
span->a = (value_type)va;
v += subpixel_scale;
a += subpixel_scale;
++span;
--len;
}
}
private:
bool m_swap;
int m_y2;
gray_calc m_c1;
gray_calc m_c2;
gray_calc m_c3;
};
} // namespace agg
#endif

Some files were not shown because too many files have changed in this diff Show more